X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fcursor-helper-functions.cpp;h=d8954187e1ee6c4be518b873a131d6771d044db1;hp=7b08c47eee53e94a045ad3d5588c15a906777547;hb=5d397f414305c86782668ecd154d8967ee8396b0;hpb=7956f5a39044145c9f6af24fa6d291a9943800cf diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index 7b08c47..d895418 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ #include // INTERNAL INCLUDES +#include +#include #include namespace @@ -153,9 +155,10 @@ LineIndex GetClosestLine(VisualModelPtr visualModel, it != endIt; ++it, ++lineIndex) { - const LineRun& lineRun = *it; + const LineRun& lineRun = *it; + bool isLastLine = (it + 1 == endIt); - totalHeight += GetLineHeight(lineRun); + totalHeight += GetLineHeight(lineRun, isLastLine); if(visualY < totalHeight) { @@ -182,9 +185,10 @@ float CalculateLineOffset(const Vector& lines, it != endIt; ++it) { - const LineRun& lineRun = *it; + const LineRun& lineRun = *it; + bool isLastLine = (it + 1 == lines.End()); - offset += GetLineHeight(lineRun); + offset += GetLineHeight(lineRun, isLastLine); } return offset; @@ -212,6 +216,7 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, { return logicalIndex; } + const float characterSpacing = visualModel->GetCharacterSpacing(); // Whether there is a hit on a line. bool matchedLine = false; @@ -262,8 +267,11 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, bool isBeforeFirstGlyph = false; // Traverses glyphs in visual order. To do that use the visual to logical conversion table. - CharacterIndex visualIndex = startCharacter; - Length numberOfVisualCharacters = 0; + CharacterIndex visualIndex = startCharacter; + Length numberOfVisualCharacters = 0; + float calculatedAdvance = 0.f; + Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; + const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); for(; visualIndex < endCharacter; ++visualIndex) { // The character in logical order. @@ -283,11 +291,13 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, // Get the metrics for the group of glyphs. GlyphMetrics glyphMetrics; + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance); GetGlyphsMetrics(firstLogicalGlyphIndex, numberOfGlyphs, glyphMetrics, glyphInfoBuffer, - metrics); + metrics, + calculatedAdvance); // Get the position of the first glyph. const Vector2& position = *(positionsBuffer + firstLogicalGlyphIndex); @@ -450,6 +460,19 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, logicalIndex = (bidiLineFetched ? logicalModel->GetLogicalCursorIndex(visualIndex) : visualIndex); + // Handle Emoji clustering for cursor handling: + // Fixing this case: + // - When there is Emoji contains multi unicodes and it is layoutted at the end of line (LineWrap case , is not new line case) + // - Try to click at the center or at the end of Emoji then the cursor appears inside Emoji + // - Example:"FamilyManWomanGirlBoy 👨‍👩‍👧‍👦" + const Script script = logicalModel->GetScript(logicalIndex); + if(IsOneOfEmojiScripts(script)) + { + //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts. + CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, logicalIndex); + logicalIndex = emojiClusteredCharacters.characterIndex; + } + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "closest visualIndex %d logicalIndex %d\n", visualIndex, logicalIndex); DALI_ASSERT_DEBUG((logicalIndex <= logicalModel->mText.Count() && logicalIndex >= 0) && "GetClosestCursorIndex - Out of bounds index"); @@ -480,14 +503,11 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const LineIndex lineIndex = parameters.visualModel->GetLineOfCharacter(characterOfLine); const LineRun& line = *(modelLines + lineIndex); - const GlyphIndex* const charactersToGlyphBuffer = parameters.visualModel->mCharactersToGlyph.Begin(); - const Length* const glyphsPerCharacterBuffer = parameters.visualModel->mGlyphsPerCharacter.Begin(); - const GlyphInfo* const glyphInfoBuffer = parameters.visualModel->mGlyphs.Begin(); - CharacterIndex index; - GlyphMetrics glyphMetrics; - MetricsPtr& metrics = parameters.metrics; - GlyphIndex glyphIndex = 0u; - Length numberOfGlyphs = 0u; + CharacterIndex index; + GlyphMetrics glyphMetrics; + MetricsPtr& metrics = parameters.metrics; + GlyphIndex glyphIndex = 0u; + Length numberOfGlyphs = 0u; if(isLastNewParagraph) { @@ -501,12 +521,18 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines, newLineIndex); - cursorInfo.lineHeight = GetLineHeight(newLine); + // The line height is the addition of the line ascender and the line descender. + // However, the line descender has a negative value, hence the subtraction also line spacing should not be included in cursor height. + cursorInfo.lineHeight = newLine.ascender - newLine.descender; + index = 0u; const Length totalNumberOfCharacters = parameters.logicalModel->mText.Count(); - index = totalNumberOfCharacters - 1; + if(totalNumberOfCharacters > 0u) + { + index = totalNumberOfCharacters - 1u; + } - GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); + GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); // Set the primary cursor's height. // The primary cursor height will take the font height of the last character and if there are no characters, it'll take the default font line height. @@ -553,7 +579,9 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines, lineIndex); - cursorInfo.lineHeight = GetLineHeight(line); + // The line height is the addition of the line ascender and the line descender. + // However, the line descender has a negative value, hence the subtraction also line spacing should not be included in cursor height. + cursorInfo.lineHeight = line.ascender - line.descender; // Calculate the primary cursor. @@ -593,8 +621,12 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const Length* const charactersPerGlyphBuffer = parameters.visualModel->mCharactersPerGlyph.Begin(); const CharacterIndex* const glyphsToCharactersBuffer = parameters.visualModel->mGlyphsToCharacters.Begin(); const Vector2* const glyphPositionsBuffer = parameters.visualModel->mGlyphPositions.Begin(); + const float characterSpacing = parameters.visualModel->GetCharacterSpacing(); + + // Get the metrics for the group of glyphs. + GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); - GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); + // Convert the cursor position into the glyph position. const GlyphIndex primaryGlyphIndex = glyphIndex; const Length primaryNumberOfCharacters = *(charactersPerGlyphBuffer + primaryGlyphIndex); @@ -632,7 +664,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, (isFirstPositionOfLine && isRightToLeftParagraph) || (!isFirstPositionOfLine && !isLastPosition && !isCurrentRightToLeft)); - float glyphAdvance = addGlyphAdvance ? glyphMetrics.advance : 0.f; + float glyphAdvance = addGlyphAdvance ? (glyphMetrics.advance) : 0.f; if(!isLastPositionOfLine && (primaryNumberOfCharacters > 1u)) @@ -651,7 +683,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, numberOfGlyphAdvance = primaryNumberOfCharacters - numberOfGlyphAdvance; } - glyphAdvance = static_cast(numberOfGlyphAdvance) * glyphMetrics.advance / static_cast(primaryNumberOfCharacters); + glyphAdvance = static_cast(numberOfGlyphAdvance) * (glyphMetrics.advance) / static_cast(primaryNumberOfCharacters); } // Get the glyph position and x bearing (in the line's coords). @@ -680,7 +712,8 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, index = (isRightToLeftParagraph == isCurrentRightToLeft) ? nextCharacterIndex : characterIndex; } - GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); + GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); + const GlyphIndex secondaryGlyphIndex = glyphIndex; const Vector2& secondaryPosition = *(glyphPositionsBuffer + secondaryGlyphIndex); @@ -705,7 +738,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const bool addGlyphAdvance = ((!isFirstPositionOfLine && !isCurrentRightToLeft) || (isFirstPositionOfLine && !isRightToLeftParagraph)); - cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + (addGlyphAdvance ? glyphMetrics.advance : 0.f); + cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + (addGlyphAdvance ? (glyphMetrics.advance + characterSpacing) : 0.f); cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight; // Transform the cursor info from line's coords to text's coords.