X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-geometry.cpp;h=8992c6de41be6c1e43b650962cfda439288befbf;hb=e4025736c4d5e85ab7408f9d6932cc7b3e9c9fef;hp=09d2c92a71189b0fa53f40ca6c758a282971b05f;hpb=4b79dd131ba61d94518e4ab89d41eaf634d305c6;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-geometry.cpp b/dali-toolkit/internal/text/text-geometry.cpp index 09d2c92..8992c6d 100644 --- a/dali-toolkit/internal/text/text-geometry.cpp +++ b/dali-toolkit/internal/text/text-geometry.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace Dali; @@ -333,6 +334,193 @@ Rect GetLineBoundingRect(ModelPtr textModel, const uint32_t lineIndex) return {lineX, lineY, lineWidth, lineHeight}; } +float GetCharacterLeft(const GlyphInfo& glyph, const Vector2& characterPosition) +{ + return characterPosition.x - glyph.xBearing; +} + +float GetCharacterTop(const float& yPosition) +{ + return (-1 * yPosition); +} + +float GetCharacterHeight(const GlyphInfo& glyph) +{ + return glyph.height; +} + +float GetCharacterWidth(const GlyphInfo& glyph) +{ + return glyph.advance; +} + +Rect<> GetCharacterBoundingRect(ModelPtr textModel, const uint32_t charIndex) +{ + if(textModel->mVisualModel == nullptr) + { + return {0, 0, 0, 0}; + } + + VisualModelPtr& visualModel = textModel->mVisualModel; + LogicalModelPtr& logicalModel = textModel->mLogicalModel; + + if(charIndex >= logicalModel->mText.Count() || visualModel->mLines.Empty()) + { + return {0, 0, 0, 0}; + } + + const Vector& glyphPositions = visualModel->mGlyphPositions; + const Vector& glyphs = visualModel->mGlyphs; + const Vector& lines = visualModel->mLines; + + //For each character, the index of the first glyph. + const GlyphIndex glyphIndex = visualModel->mCharactersToGlyph[charIndex]; //took its glyphs + + const Vector2& characterPosition = glyphPositions[glyphIndex]; + const GlyphInfo& glyphInfo = glyphs[glyphIndex]; + + // GetLineOfCharacter function returns 0 if the lines are empty + const int lineIndex = visualModel->GetLineOfCharacter(charIndex); + const LineRun& lineRun = lines[lineIndex]; + + //Calculate the left: x position of the glyph + alignmentOffset of the line + mScrollPosition.x. + float characterX = lineRun.alignmentOffset + GetCharacterLeft(glyphInfo, characterPosition) + textModel->mScrollPosition.x; + + //Calculate the Top(characterY): position.Y + previouse lines height + mScrollPosition.y. + bool isFirstLine = lineIndex == 0; + + //If the line is the first line of the text; its top = 0. + float lineY = (isFirstLine ? 0 : GetLineTop(lines, lineRun)); + + float characterY = lineY + GetCharacterTop(characterPosition.y) + textModel->mScrollPosition.y; + + //The rectangle contains the width and height: + float characterWidth = GetCharacterWidth(glyphInfo); + float characterHeight = GetCharacterHeight(glyphInfo); + + 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& lines = visualModel->mLines; + + float lineTop = 0.f; + int lineIndex = -1; + int high = totalNumberOfLines; + int low = -1; + int guess; + + // Searching for the correct line. + while(high - low > 1) + { + guess = (high + low) / 2; + Vector::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; + } + } + + // Check if a line is not found; return -1. + if(lineIndex == -1) + { + 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