[dali_2.1.31] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-selection-handle-controller.cpp
index b082510..fef3baa 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.
@@ -23,7 +23,9 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h>
 
 using namespace Dali;
 
@@ -103,10 +105,16 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
   }
 
   // Get the indices to the first and last selected glyphs.
-  const CharacterIndex selectionEndMinusOne = selectionEnd - 1u;
-  const GlyphIndex     glyphStart           = *(charactersToGlyphBuffer + selectionStart);
-  const Length         numberOfGlyphs       = *(glyphsPerCharacterBuffer + selectionEndMinusOne);
-  const GlyphIndex     glyphEnd             = *(charactersToGlyphBuffer + selectionEndMinusOne) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
+  const CharacterIndex    selectionEndMinusOne      = selectionEnd - 1u;
+  const GlyphIndex        glyphStart                = *(charactersToGlyphBuffer + selectionStart);
+  const Length            numberOfGlyphs            = *(glyphsPerCharacterBuffer + selectionEndMinusOne);
+  const GlyphIndex        glyphEnd                  = *(charactersToGlyphBuffer + selectionEndMinusOne) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
+  const float             modelCharacterSpacing     = visualModel->GetCharacterSpacing();
+  Vector<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
+  const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
 
   // Get the lines where the glyphs are laid-out.
   const LineRun* lineRun = visualModel->mLines.Begin();
@@ -144,7 +152,9 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
 
   lineRun += firstLineIndex;
 
-  selectionBoxInfo->lineHeight = GetLineHeight(*lineRun);
+  // 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 selection height.
+  selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender;
 
   GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
 
@@ -163,18 +173,21 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
   // Count the actual number of quads.
   unsigned int actualNumberOfQuads = 0u;
   Vector4      quad;
+  float        calculatedAdvance = 0.f;
 
   // Traverse the glyphs.
   for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index)
   {
-    const GlyphInfo& glyph    = *(glyphsBuffer + index);
-    const Vector2&   position = *(positionsBuffer + index);
+    const float      characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing);
+    const GlyphInfo& glyph            = *(glyphsBuffer + index);
+    const Vector2&   position         = *(positionsBuffer + index);
+    calculatedAdvance                 = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance);
 
     if(splitStartGlyph)
     {
       // If the first glyph is a ligature that must be broken it may be needed to add only part of the glyph to the highlight box.
 
-      const float          glyphAdvance    = glyph.advance / static_cast<float>(numberOfCharactersStart);
+      const float          glyphAdvance    = calculatedAdvance / static_cast<float>(numberOfCharactersStart);
       const CharacterIndex interGlyphIndex = selectionStart - *(glyphToCharacterBuffer + glyphStart);
       // Get the direction of the character.
       CharacterDirection isCurrentRightToLeft = false;
@@ -207,7 +220,7 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
     {
       // Equally, if the last glyph is a ligature that must be broken it may be needed to add only part of the glyph to the highlight box.
 
-      const float          glyphAdvance    = glyph.advance / static_cast<float>(numberOfCharactersEnd);
+      const float          glyphAdvance    = calculatedAdvance / static_cast<float>(numberOfCharactersEnd);
       const CharacterIndex interGlyphIndex = selectionEnd - *(glyphToCharacterBuffer + glyphEnd);
       // Get the direction of the character.
       CharacterDirection isCurrentRightToLeft = false;
@@ -237,7 +250,7 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
 
     quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + model->mScrollPosition.x;
     quad.y = selectionBoxInfo->lineOffset;
-    quad.z = quad.x + glyph.advance;
+    quad.z = quad.x + calculatedAdvance;
     quad.w = quad.y + selectionBoxInfo->lineHeight;
 
     // Store the min and max 'x' for each line.
@@ -254,6 +267,8 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
       ++lineIndex;
       if(lineIndex < firstLineIndex + numberOfLines)
       {
+        float currentLineSpacing = lineRun->lineSpacing;
+
         // Retrieve the next line.
         ++lineRun;
 
@@ -271,9 +286,16 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
         selectionBoxInfo->maxX = MIN_FLOAT;
 
         // Update the line's vertical offset.
-        selectionBoxInfo->lineOffset = currentLineOffset + currentLineHeight;
+        selectionBoxInfo->lineOffset = currentLineOffset + currentLineHeight + currentLineSpacing;
 
-        selectionBoxInfo->lineHeight = GetLineHeight(*lineRun);
+        // 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 selection height.
+        selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender;
+
+        if(lineRun->lineSpacing > 0)
+        {
+          selectionBoxInfo->lineHeight += lineRun->lineSpacing;
+        }
       }
     }
   }
@@ -491,6 +513,9 @@ void SelectionHandleController::Reposition(Controller::Impl& impl, float visualX
 
   if(characterHit || (Controller::NoTextTap::HIGHLIGHT == action))
   {
+    uint32_t oldStart = eventData->mLeftSelectionPosition;
+    uint32_t oldEnd   = eventData->mRightSelectionPosition;
+
     impl.ChangeState(EventData::SELECTING);
 
     eventData->mLeftSelectionPosition  = selectionStart;
@@ -510,6 +535,11 @@ void SelectionHandleController::Reposition(Controller::Impl& impl, float visualX
 
     // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
     eventData->mPrimaryCursorPosition = std::max(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition);
+
+    if(impl.mSelectableControlInterface != nullptr)
+    {
+      impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition);
+    }
   }
   else if(Controller::NoTextTap::SHOW_SELECTION_POPUP == action)
   {