// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/public-api/math/math-utils.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/line-run.h>
#include <dali-toolkit/internal/text/visual-model-impl.h>
+#include <algorithm>
using namespace Dali;
sizesList.Clear();
positionsList.Clear();
- if(charactersToGlyphBuffer == nullptr || glyphsPerCharacterBuffer == nullptr || charactersPerGlyphBuffer == nullptr || glyphToCharacterBuffer == nullptr )
+ if(charactersToGlyphBuffer == nullptr || glyphsPerCharacterBuffer == nullptr || charactersPerGlyphBuffer == nullptr || glyphToCharacterBuffer == nullptr)
{
return;
}
blockPos = currentPosition;
blockSize = currentSize;
}
- else if((isPrevoiusRightToLeft != isCurrentRightToLeft) || (blockPos.y != currentPosition.y)) //new direction or new line
+ else if((isPrevoiusRightToLeft != isCurrentRightToLeft) || (!Dali::Equals(blockPos.y, currentPosition.y))) //new direction or new line
{
sizesList.PushBack(blockSize);
positionsList.PushBack(blockPos);
float GetLineTop(const Vector<LineRun>& lines, const LineRun& lineRun)
{
- float lineTop = 0;
+ float lineTop = 0;
const int numberOfLines = (int)lines.Count();
- int currentLineIndex = 0;
- Vector<LineRun>::ConstIterator endIt = (&lineRun);
+ int currentLineIndex = 0;
+ Vector<LineRun>::ConstIterator endIt = (&lineRun);
for(Vector<LineRun>::Iterator it = lines.Begin();
it != endIt;
++it, ++currentLineIndex)
- {
- LineRun& line = *it;
- bool isLastLine = (currentLineIndex + 1) == numberOfLines;
- lineTop += GetLineHeight(line, isLastLine);
- }
+ {
+ LineRun& line = *it;
+ bool isLastLine = (currentLineIndex + 1) == numberOfLines;
+ lineTop += GetLineHeight(line, isLastLine);
+ }
return lineTop;
}
Rect<float> GetLineBoundingRect(ModelPtr textModel, const uint32_t lineIndex)
{
-
if(textModel->mVisualModel == nullptr)
{
return {0, 0, 0, 0};
return {0, 0, 0, 0};
}
- const Vector<LineRun>& lines = textModel->mVisualModel->mLines;
- const LineRun& lineRun = lines[lineIndex];
- bool isFirstLine = lineIndex == 0;
- bool isLastLine = (lineIndex + 1) == numberOfLines;
+ const Vector<LineRun>& lines = textModel->mVisualModel->mLines;
+ const LineRun& lineRun = lines[lineIndex];
+ bool isFirstLine = lineIndex == 0;
+ bool isLastLine = (lineIndex + 1) == numberOfLines;
// Calculate the Left(lineX) = X position.
float lineX = GetLineLeft(lineRun) + textModel->mScrollPosition.x;
const GlyphIndex glyphIndex = visualModel->mCharactersToGlyph[charIndex]; //took its glyphs
const Vector2& characterPosition = glyphPositions[glyphIndex];
- const GlyphInfo& glyphInfo = glyphs[glyphIndex];
+ const GlyphInfo& glyphInfo = glyphs[glyphIndex];
// GetLineOfCharacter function returns 0 if the lines are empty
const int lineIndex = visualModel->GetLineOfCharacter(charIndex);
return {characterX, characterY, characterWidth, characterHeight};
}
+int GetCharIndexAtPosition(ModelPtr textModel, float visualX, float visualY)
+{
+ if(textModel == nullptr)
+ {
+ return -1;
+ }
+
+ VisualModelPtr& visualModel = textModel->mVisualModel;
+
+ const int totalNumberOfGlyphs = visualModel->mGlyphs.Count();
+ const int totalNumberOfLines = visualModel->mLines.Count();
+
+ if((0 == totalNumberOfGlyphs) ||
+ (0 == totalNumberOfLines))
+ {
+ return -1;
+ }
+
+ //The top point of the view = 0.
+ if(visualY < 0)
+ {
+ return -1;
+ }
+
+ const Vector<LineRun>& lines = visualModel->mLines;
+
+ float lineTop = 0.f;
+ int lineIndex = 0;
+ int high = totalNumberOfLines;
+ int low = -1;
+ int guess;
+
+ // Searching for the correct line.
+ while(high - low > 1)
+ {
+ guess = (high + low) / 2;
+ Vector<LineRun>::ConstIterator it = lines.Begin() + guess;
+
+ lineTop = GetLineTop(lines, *it);
+
+ if(lineTop > visualY)
+ {
+ high = guess;
+ }
+ else
+ {
+ low = guess;
+ }
+ }
+
+ if(low < 0)
+ {
+ lineIndex = 0;
+ }
+ else
+ {
+ lineIndex = low;
+ }
+
+ bool isLastLine = lineIndex + 1 == totalNumberOfLines;
+
+ if(isLastLine)
+ {
+ const LineRun& line = *(visualModel->mLines.Begin() + lineIndex);
+ float lineHeight = GetLineHeight(line, isLastLine);
+
+ // If the visualY is placed after the last line.
+ if(visualY > lineTop + lineHeight)
+ {
+ return -1;
+ }
+ }
+
+ // Start searching for the visualX
+ const LineRun& line = *(visualModel->mLines.Begin() + lineIndex);
+
+ visualX -= line.alignmentOffset;
+
+ // Positions of the glyphs
+ const Vector2* const positionsBuffer = visualModel->mGlyphPositions.Begin();
+
+ const CharacterIndex startCharacter = line.characterRun.characterIndex;
+ const CharacterIndex endCharacter = line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1;
+
+ CharacterIndex characterIndexAtPosition = -1;
+ CharacterIndex characterIndex = startCharacter;
+ float characterPosition;
+ float rightMostCharacterPosition;
+
+ for(; characterIndex != endCharacter; characterIndex++)
+ {
+ characterPosition = positionsBuffer[characterIndex].x;
+ rightMostCharacterPosition = positionsBuffer[characterIndex+1].x;
+
+ if(visualX < rightMostCharacterPosition && visualX >= characterPosition)
+ {
+ characterIndexAtPosition = characterIndex;
+ break;
+ }
+ }
+
+ if(characterIndex == endCharacter)
+ {
+ // If the visualX is within the last character position or it comes after the last character; we return the last character.
+ rightMostCharacterPosition = positionsBuffer[endCharacter].x + GetCharacterWidth(visualModel->mGlyphs[endCharacter]);
+
+ if(visualX >= positionsBuffer[endCharacter].x && visualX < rightMostCharacterPosition)
+ {
+ characterIndexAtPosition = endCharacter;
+ }
+ }
+
+ return characterIndexAtPosition;
+}
} // namespace Text
} // namespace Toolkit