[dali_2.1.7] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / cursor-helper-functions.cpp
index 1df142c..c70d530 100644 (file)
@@ -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.
@@ -155,9 +155,7 @@ LineIndex GetClosestLine(VisualModelPtr visualModel,
   {
     const LineRun& lineRun = *it;
 
-    // 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.
-    totalHeight += lineRun.ascender - lineRun.descender;
+    totalHeight += GetLineHeight(lineRun);
 
     if(visualY < totalHeight)
     {
@@ -186,9 +184,7 @@ float CalculateLineOffset(const Vector<LineRun>& lines,
   {
     const LineRun& lineRun = *it;
 
-    // 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.
-    offset += lineRun.ascender - lineRun.descender;
+    offset += GetLineHeight(lineRun);
   }
 
   return offset;
@@ -216,6 +212,7 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
   {
     return logicalIndex;
   }
+  const float characterSpacing = visualModel->GetCharacterSpacing();
 
   // Whether there is a hit on a line.
   bool matchedLine = false;
@@ -266,8 +263,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<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
+  const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
   for(; visualIndex < endCharacter; ++visualIndex)
   {
     // The character in logical order.
@@ -287,11 +287,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);
@@ -462,6 +464,7 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
 }
 
 void GetCursorPosition(GetCursorPositionParameters& parameters,
+                       float                        defaultFontLineHeight,
                        CursorInfo&                  cursorInfo)
 {
   const LineRun* const modelLines = parameters.visualModel->mLines.Begin();
@@ -483,6 +486,12 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
   const LineIndex lineIndex = parameters.visualModel->GetLineOfCharacter(characterOfLine);
   const LineRun&  line      = *(modelLines + lineIndex);
 
+  CharacterIndex index;
+  GlyphMetrics   glyphMetrics;
+  MetricsPtr&    metrics        = parameters.metrics;
+  GlyphIndex     glyphIndex     = 0u;
+  Length         numberOfGlyphs = 0u;
+
   if(isLastNewParagraph)
   {
     // The cursor is in a new line with no characters. Place the cursor in that line.
@@ -495,12 +504,20 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
     cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines,
                                                 newLineIndex);
 
-    // 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.
-    cursorInfo.lineHeight = newLine.ascender - newLine.descender;
+    cursorInfo.lineHeight = GetLineHeight(newLine);
+
+    index                                = 0u;
+    const Length totalNumberOfCharacters = parameters.logicalModel->mText.Count();
+    if(totalNumberOfCharacters > 0u)
+    {
+      index = totalNumberOfCharacters - 1u;
+    }
+
+    GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
 
     // Set the primary cursor's height.
-    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
+    // 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.
+    cursorInfo.primaryCursorHeight = (totalNumberOfCharacters > 0) ? (cursorInfo.isSecondaryCursor ? 0.5f * glyphMetrics.fontHeight : glyphMetrics.fontHeight) : defaultFontLineHeight;
 
     // Set the primary cursor's position.
     cursorInfo.primaryPosition.x = (LTR == line.direction) ? newLine.alignmentOffset : parameters.visualModel->mControlSize.width - newLine.alignmentOffset;
@@ -543,13 +560,11 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
     cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines,
                                                 lineIndex);
 
-    // 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.
-    cursorInfo.lineHeight = line.ascender - line.descender;
+    cursorInfo.lineHeight = GetLineHeight(line);
 
     // Calculate the primary cursor.
 
-    CharacterIndex index = characterIndex;
+    index = characterIndex;
     if(cursorInfo.isSecondaryCursor)
     {
       // If there is a secondary position, the primary cursor may be in a different place than the logical index.
@@ -582,26 +597,18 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
       }
     }
 
-    const GlyphIndex* const     charactersToGlyphBuffer  = parameters.visualModel->mCharactersToGlyph.Begin();
-    const Length* const         glyphsPerCharacterBuffer = parameters.visualModel->mGlyphsPerCharacter.Begin();
     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 GlyphInfo* const      glyphInfoBuffer          = parameters.visualModel->mGlyphs.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);
 
     // Convert the cursor position into the glyph position.
-    const GlyphIndex primaryGlyphIndex         = *(charactersToGlyphBuffer + index);
-    const Length     primaryNumberOfGlyphs     = *(glyphsPerCharacterBuffer + index);
+    const GlyphIndex primaryGlyphIndex         = glyphIndex;
     const Length     primaryNumberOfCharacters = *(charactersPerGlyphBuffer + primaryGlyphIndex);
 
-    // Get the metrics for the group of glyphs.
-    GlyphMetrics glyphMetrics;
-    GetGlyphsMetrics(primaryGlyphIndex,
-                     primaryNumberOfGlyphs,
-                     glyphMetrics,
-                     glyphInfoBuffer,
-                     parameters.metrics);
-
     // Whether to add the glyph's advance to the cursor position.
     // i.e if the paragraph is left to right and the logical cursor is zero, the position is the position of the first glyph and the advance is not added,
     //     if the logical cursor is one, the position is the position of the first glyph and the advance is added.
@@ -636,7 +643,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))
@@ -655,7 +662,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
         numberOfGlyphAdvance = primaryNumberOfCharacters - numberOfGlyphAdvance;
       }
 
-      glyphAdvance = static_cast<float>(numberOfGlyphAdvance) * glyphMetrics.advance / static_cast<float>(primaryNumberOfCharacters);
+      glyphAdvance = static_cast<float>(numberOfGlyphAdvance) * (glyphMetrics.advance) / static_cast<float>(primaryNumberOfCharacters);
     }
 
     // Get the glyph position and x bearing (in the line's coords).
@@ -684,16 +691,10 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
         index = (isRightToLeftParagraph == isCurrentRightToLeft) ? nextCharacterIndex : characterIndex;
       }
 
-      const GlyphIndex secondaryGlyphIndex     = *(charactersToGlyphBuffer + index);
-      const Length     secondaryNumberOfGlyphs = *(glyphsPerCharacterBuffer + index);
+      GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
 
-      const Vector2& secondaryPosition = *(glyphPositionsBuffer + secondaryGlyphIndex);
-
-      GetGlyphsMetrics(secondaryGlyphIndex,
-                       secondaryNumberOfGlyphs,
-                       glyphMetrics,
-                       glyphInfoBuffer,
-                       parameters.metrics);
+      const GlyphIndex secondaryGlyphIndex = glyphIndex;
+      const Vector2&   secondaryPosition   = *(glyphPositionsBuffer + secondaryGlyphIndex);
 
       // Set the secondary cursor's position.
 
@@ -716,7 +717,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.