Merge "Support the underline and its attributes in span tag" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Mon, 7 Mar 2022 10:53:08 +0000 (10:53 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 7 Mar 2022 10:53:08 +0000 (10:53 +0000)
27 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/devel-api/controls/control-accessible.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/line-run.h
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-geometry.cpp
dali-toolkit/internal/text/text-selection-handle-controller.cpp
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 1ed53dc..f75d224 100644 (file)
@@ -267,13 +267,13 @@ int UtcDaliControlAccessibilityHighlightable(void)
   ToolkitTestApplication application;
   auto control = Control::New();
 
-  auto noneset = control.GetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE );
-  DALI_TEST_EQUALS( Property::NONE, noneset.GetType(), TEST_LOCATION );
+  auto highlightable = control.GetProperty<bool>(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
+  DALI_TEST_EQUALS(highlightable, false, TEST_LOCATION);
 
    // negative testcase - trying to set unconvertible value
-  control.SetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, "deadbeef" );
-  noneset = control.GetProperty( DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE );
-  DALI_TEST_EQUALS( Property::NONE, noneset.GetType(), TEST_LOCATION );
+  control.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, "deadbeef");
+  highlightable = control.GetProperty<bool>(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
+  DALI_TEST_EQUALS(highlightable, false, TEST_LOCATION);
 
   auto q = Dali::Accessibility::Accessible::Get( control );
 
index e610f2f..df21268 100644 (file)
@@ -36,7 +36,7 @@ int UtcDaliControlPropertyAccessibilityTranslationDomain(void)
   auto control = Control::New();
 
   auto accessibility_translation_domain = DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN;
-  DALI_TEST_EQUALS( Property::NONE , control.GetProperty( accessibility_translation_domain ).GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS("", control.GetProperty<std::string>(accessibility_translation_domain), TEST_LOCATION);
 
   control.SetProperty( accessibility_translation_domain, "translation_domain_test_1" );
   DALI_TEST_EQUALS( "translation_domain_test_1" , control.GetProperty( accessibility_translation_domain ).Get<  std::string  >(), TEST_LOCATION );
index 537207c..0524d55 100644 (file)
@@ -4516,6 +4516,45 @@ int UtcDaliTextEditorLineSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextEditorSelectionWithLineSpacing(void)
+{
+  //Only for test coverage
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorSelectionWithLineSpacing ");
+
+  TextEditor textEditor = TextEditor::New();
+  textEditor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.f));
+  application.GetScene().Add(textEditor);
+  application.SendNotification();
+  application.Render();
+
+  textEditor.SetProperty(TextEditor::Property::TEXT, "Line #1\nLine #2\nLine #3");
+  textEditor.SetProperty(DevelTextEditor::Property::LINE_SPACING, -20);
+
+  application.SendNotification();
+  application.Render();
+
+  DevelTextEditor::SelectWholeText(textEditor);
+
+  application.SendNotification();
+  application.Render();
+
+  DevelTextEditor::SelectNone(textEditor);
+  textEditor.SetProperty(DevelTextEditor::Property::LINE_SPACING, 20);
+
+  application.SendNotification();
+  application.Render();
+
+  DevelTextEditor::SelectWholeText(textEditor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(textEditor.GetProperty<float>(DevelTextEditor::Property::LINE_SPACING), 20.0f, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliTextEditorMinLineSize(void)
 {
   ToolkitTestApplication application;
@@ -5726,6 +5765,42 @@ int UtcDaliToolkitTextEditorUnderlineTypesGeneration3(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextEditorRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextEditorRelativeLineHeight");
+
+  TextEditor editor = TextEditor::New();
+  editor.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+  editor.SetProperty(TextEditor::Property::TEXT, "Hello\nWorld");
+
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize = editor.GetNaturalSize();
+
+  editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 0.5f);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 relativeNaturalSize = editor.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y, relativeNaturalSize.y, TEST_LOCATION);
+
+  editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 2.0f);
+
+  application.SendNotification();
+  application.Render();
+
+  relativeNaturalSize = editor.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y * 2, relativeNaturalSize.y, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliTextEditorCharacterSpacing(void)
 {
   ToolkitTestApplication application;
@@ -5749,6 +5824,39 @@ int UtcDaliTextEditorCharacterSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextEditorTextSizeNegativeLineSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextEditorTextSizeNegativeLineSpacing");
+
+  TextEditor editor = TextEditor::New();
+
+  float lineSpacing = -20.f;
+
+  editor.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f));
+  editor.SetProperty(TextEditor::Property::POINT_SIZE, 10.f);
+  editor.SetProperty(DevelTextEditor::Property::LINE_SPACING, lineSpacing);
+  editor.SetProperty(TextEditor::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, 0, 123);
+  Vector<Vector2> sizeList      = DevelTextEditor::GetTextSize(editor, 0, 123);
+
+  Vector2 lastLinePos  = positionsList[positionsList.Size() - 1];
+  Vector2 lastLineSize = sizeList[sizeList.Size() - 1];
+
+  DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTexteditorParagraphTag(void)
 {
   ToolkitTestApplication application;
index ecc5f67..e12ce04 100644 (file)
@@ -2632,6 +2632,42 @@ int UtcDaliToolkitTextLabelStrikethroughGeneration(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextLabelRelativeLineHeight(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelRelativeLineHeight");
+
+  TextLabel label = TextLabel::New();
+  label.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+  label.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+  label.SetProperty(TextLabel::Property::TEXT, "Hello\nWorld");
+
+  application.GetScene().Add(label);
+  application.SendNotification();
+  application.Render();
+
+  Vector3 naturalSize = label.GetNaturalSize();
+
+  label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 0.5f);
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 relativeNaturalSize = label.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y, relativeNaturalSize.y, TEST_LOCATION);
+
+  label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 2.0f);
+
+  application.SendNotification();
+  application.Render();
+
+  relativeNaturalSize = label.GetNaturalSize();
+
+  DALI_TEST_EQUALS(naturalSize.y * 2, relativeNaturalSize.y, TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliTextLabelCharacterSpacing(void)
 {
   ToolkitTestApplication application;
@@ -2655,6 +2691,40 @@ int UtcDaliTextLabelCharacterSpacing(void)
   END_TEST;
 }
 
+int UtcDaliTextTextLabelSizeNegativeLineSpacing(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextTextLabelSizeNegativeLineSpacing");
+
+  TextLabel label = TextLabel::New();
+
+  float lineSpacing = -20.f;
+
+  label.SetProperty(Actor::Property::SIZE, Vector2(450.0f, 300.f));
+  label.SetProperty(TextLabel::Property::POINT_SIZE, 10.f);
+  label.SetProperty(DevelTextLabel::Property::LINE_SPACING, lineSpacing);
+  label.SetProperty(TextLabel::Property::MULTI_LINE, true);
+  label.SetProperty(TextLabel::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+
+  application.GetScene().Add(label);
+  application.SendNotification();
+  application.Render();
+
+  Vector<Vector2> positionsList = DevelTextLabel::GetTextPosition(label, 0, 123);
+  Vector<Vector2> sizeList      = DevelTextLabel::GetTextSize(label, 0, 123);
+
+  Vector2 lastLinePos  = positionsList[positionsList.Size() - 1];
+  Vector2 lastLineSize = sizeList[sizeList.Size() - 1];
+
+  DALI_TEST_EQUALS(sizeList[0].y * (sizeList.Size() - 1), lastLinePos.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(sizeList[0].y - lineSpacing, lastLineSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
 int UtcDaliToolkitTextlabelParagraphTag(void)
 {
   ToolkitTestApplication application;
index 21fc8e2..ae7eff0 100644 (file)
@@ -85,7 +85,7 @@ ControlAccessible::ControlAccessible(Dali::Actor self, Dali::Accessibility::Role
       return;
     }
 
-    if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
+    if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && controlImpl.mAccessibilityName.empty()))
     {
       if(controlImpl.mAccessibilityGetNameSignal.Empty())
       {
@@ -93,7 +93,7 @@ ControlAccessible::ControlAccessible(Dali::Actor self, Dali::Accessibility::Role
       }
     }
 
-    if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
+    if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && controlImpl.mAccessibilityDescription.empty()))
     {
       if(controlImpl.mAccessibilityGetDescriptionSignal.Empty())
       {
@@ -115,7 +115,7 @@ std::string ControlAccessible::GetName() const
   {
     controlImpl.mAccessibilityGetNameSignal.Emit(name);
   }
-  else if(controlImpl.mAccessibilityNameSet)
+  else if(!controlImpl.mAccessibilityName.empty())
   {
     name = controlImpl.mAccessibilityName;
   }
@@ -128,7 +128,7 @@ std::string ControlAccessible::GetName() const
     name = Self().GetProperty<std::string>(Actor::Property::NAME);
   }
 
-  if(controlImpl.mAccessibilityTranslationDomainSet)
+  if(!controlImpl.mAccessibilityTranslationDomain.empty())
   {
     return GetLocaleText(name, controlImpl.mAccessibilityTranslationDomain.c_str());
   }
@@ -153,7 +153,7 @@ std::string ControlAccessible::GetDescription() const
   {
     controlImpl.mAccessibilityGetDescriptionSignal.Emit(description);
   }
-  else if(controlImpl.mAccessibilityDescriptionSet)
+  else if(!controlImpl.mAccessibilityDescription.empty())
   {
     description = controlImpl.mAccessibilityDescription;
   }
@@ -161,7 +161,8 @@ std::string ControlAccessible::GetDescription() const
   {
     description = GetDescriptionRaw();
   }
-  if(controlImpl.mAccessibilityTranslationDomainSet)
+
+  if(!controlImpl.mAccessibilityTranslationDomain.empty())
   {
     return GetLocaleText(description, controlImpl.mAccessibilityTranslationDomain.c_str());
   }
index 8ca9648..b990dc7 100644 (file)
@@ -303,6 +303,13 @@ enum Type
   *   The default value is 0.f which does nothing.
   */
   CHARACTER_SPACING,
+
+  /**
+   * @brief the relative height of the line (a factor that will be multiplied by text height).
+   * @details Name "relativeLineSize", type Property::FLOAT.
+   * @note If the value is less than 1, the lines could to be overlapped.
+   */
+  RELATIVE_LINE_SIZE,
 };
 
 } // namespace Property
index 205950c..326d8d0 100644 (file)
@@ -194,6 +194,13 @@ enum Type
   *   The default value is 0.f which does nothing.
   */
   CHARACTER_SPACING,
+
+  /**
+   * @brief the relative height of the line (a factor that will be multiplied by text height).
+   * @details Name "relativeLineSize", type Property::FLOAT.
+   * @note If the value is less than 1, the lines could to be overlapped.
+   */
+  RELATIVE_LINE_SIZE,
 };
 
 } // namespace Property
index 81b82d8..7b5e36e 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
@@ -40,7 +41,6 @@
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-model.h>
-#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 
 namespace Dali
 {
@@ -835,7 +835,7 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
     {
       Length finalNumberOfGlyphs = 0u;
 
-      if((GetLineHeight(line)) > textLayoutArea.height)
+      if((GetLineHeight(line, (lines.Size() == 1))) > textLayoutArea.height)
       {
         // The height of the line is bigger than the height of the text area.
         // Show the ellipsis glyph even if it doesn't fit in the text area.
@@ -1528,12 +1528,14 @@ Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters)
   float            penY               = 0.f;
   float            lineSize           = internalData.layoutEngine.GetDefaultLineSize();
   float            lineOffset         = 0.f;
+  bool             isLastLine;
   for(unsigned int index = 0u; index < numberOfLines; ++index)
   {
     const LineRun& line = *(lines.Begin() + index);
     numberOfCharacters += line.characterRun.numberOfCharacters;
+    isLastLine = (index == numberOfLines - 1);
 
-    lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line);
+    lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line, isLastLine);
     penY += lineOffset;
     if((penY + lineOffset) > boundingBox)
     {
index bfe280a..3d71f4d 100644 (file)
@@ -1286,45 +1286,30 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string name;
         if(value.Get(name))
         {
-          controlImpl.mImpl->mAccessibilityName    = name;
-          controlImpl.mImpl->mAccessibilityNameSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityNameSet = false;
+          controlImpl.mImpl->mAccessibilityName = name;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
       {
         std::string text;
         if(value.Get(text))
         {
-          controlImpl.mImpl->mAccessibilityDescription    = text;
-          controlImpl.mImpl->mAccessibilityDescriptionSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityDescriptionSet = false;
+          controlImpl.mImpl->mAccessibilityDescription = text;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
       {
         std::string text;
         if(value.Get(text))
         {
-          controlImpl.mImpl->mAccessibilityTranslationDomain    = text;
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
+          controlImpl.mImpl->mAccessibilityTranslationDomain = text;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
       {
@@ -1333,23 +1318,18 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         {
           controlImpl.mImpl->mAccessibilityRole = role;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
       {
         bool highlightable;
         if(value.Get(highlightable))
         {
-          controlImpl.mImpl->mAccessibilityHighlightable    = highlightable;
-          controlImpl.mImpl->mAccessibilityHighlightableSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityHighlightableSet = false;
+          controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
         }
+        break;
       }
-      break;
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
@@ -1502,28 +1482,19 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
       {
-        if(controlImpl.mImpl->mAccessibilityNameSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityName;
-        }
+        value = controlImpl.mImpl->mAccessibilityName;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
       {
-        if(controlImpl.mImpl->mAccessibilityDescriptionSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityDescription;
-        }
+        value = controlImpl.mImpl->mAccessibilityDescription;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
       {
-        if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityTranslationDomain;
-        }
+        value = controlImpl.mImpl->mAccessibilityTranslationDomain;
         break;
       }
 
@@ -1535,10 +1506,7 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
       {
-        if(controlImpl.mImpl->mAccessibilityHighlightableSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityHighlightable;
-        }
+        value = controlImpl.mImpl->mAccessibilityHighlightable;
         break;
       }
 
index a227648..1321a10 100644 (file)
@@ -539,14 +539,9 @@ public:
   std::string mAccessibilityName;
   std::string mAccessibilityDescription;
   std::string mAccessibilityTranslationDomain;
-  bool        mAccessibilityNameSet              = false;
-  bool        mAccessibilityDescriptionSet       = false;
-  bool        mAccessibilityTranslationDomainSet = false;
 
-  bool mAccessibilityHighlightable    = false;
-  bool mAccessibilityHighlightableSet = false;
-
-  bool mAccessibilityHidden = false;
+  bool mAccessibilityHighlightable = false;
+  bool mAccessibilityHidden        = false;
 
   Dali::Accessibility::Role mAccessibilityRole = Dali::Accessibility::Role::UNKNOWN;
 
index 40fdcad..6fc1a3d 100644 (file)
@@ -158,6 +158,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "minLineSize",
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "strikethrough",                        MAP,       STRIKETHROUGH                       )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "inputStrikethrough",                   MAP,       INPUT_STRIKETHROUGH                 )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "characterSpacing",                     FLOAT,     CHARACTER_SPACING                   )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "relativeLineSize",                     FLOAT,     RELATIVE_LINE_SIZE                  )
 
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged",           SIGNAL_TEXT_CHANGED           )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged",     SIGNAL_INPUT_STYLE_CHANGED    )
index 3cb9df0..5ea2cf1 100644 (file)
@@ -723,6 +723,15 @@ void TextEditor::PropertyHandler::SetProperty(Toolkit::TextEditor textEditor, Pr
       impl.mRenderer.Reset();
       break;
     }
+    case Toolkit::DevelTextEditor::Property::RELATIVE_LINE_SIZE:
+    {
+      const float relativeLineSize = value.Get<float>();
+      DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor %p RELATIVE_LINE_SIZE %f\n", impl.mController.Get(), relativeLineSize);
+
+      impl.mController->SetRelativeLineSize(relativeLineSize);
+      impl.mRenderer.Reset();
+      break;
+    }
   }
 }
 
@@ -1130,6 +1139,11 @@ Property::Value TextEditor::PropertyHandler::GetProperty(Toolkit::TextEditor tex
       value = impl.mController->GetCharacterSpacing();
       break;
     }
+    case Toolkit::DevelTextEditor::Property::RELATIVE_LINE_SIZE:
+    {
+      value = impl.mController->GetRelativeLineSize();
+      break;
+    }
   } //switch
   return value;
 }
index 49a9af8..10b05a0 100644 (file)
@@ -140,6 +140,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "enableFontSizeSc
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "ellipsisPosition",             INTEGER, ELLIPSIS_POSITION              )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "strikethrough",                MAP,     STRIKETHROUGH                  )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "characterSpacing",             FLOAT,   CHARACTER_SPACING              )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "relativeLineSize",             FLOAT,   RELATIVE_LINE_SIZE             )
 
 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, TextLabel, "textColor",      Color::BLACK,     TEXT_COLOR   )
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION(Toolkit,    TextLabel, "textColorRed",   TEXT_COLOR_RED,   TEXT_COLOR, 0)
@@ -541,6 +542,14 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
         impl.mController->SetCharacterSpacing(characterSpacing);
         break;
       }
+      case Toolkit::DevelTextLabel::Property::RELATIVE_LINE_SIZE:
+      {
+        const float relativeLineSize = value.Get<float>();
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextLabel %p RELATIVE_LINE_SIZE %f\n", impl.mController.Get(), relativeLineSize);
+
+        impl.mController->SetRelativeLineSize(relativeLineSize);
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -799,6 +808,11 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index
         value = impl.mController->GetCharacterSpacing();
         break;
       }
+      case Toolkit::DevelTextLabel::Property::RELATIVE_LINE_SIZE:
+      {
+        value = impl.mController->GetRelativeLineSize();
+        break;
+      }
     }
   }
 
index c70d530..3bfc059 100644 (file)
@@ -153,9 +153,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 +183,10 @@ float CalculateLineOffset(const Vector<LineRun>& 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;
@@ -504,7 +506,9 @@ 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();
@@ -560,7 +564,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.
 
index c8addcc..53030e2 100644 (file)
@@ -37,11 +37,18 @@ namespace Toolkit
 {
 namespace Text
 {
-float GetLineHeight(const LineRun lineRun)
+float GetLineHeight(const LineRun lineRun, bool isLastLine)
 {
   // The line height is the addition of the line ascender, the line descender and the line spacing.
   // However, the line descender has a negative value, hence the subtraction.
-  return lineRun.ascender - lineRun.descender + lineRun.lineSpacing;
+  // In case this is the only/last line then line spacing should be ignored.
+  float lineHeight = lineRun.ascender - lineRun.descender;
+
+  if(!isLastLine || lineRun.lineSpacing > 0)
+  {
+    lineHeight += lineRun.lineSpacing;
+  }
+  return lineHeight;
 }
 
 namespace Layout
@@ -52,12 +59,13 @@ namespace
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_LAYOUT");
 #endif
 
-const float              MAX_FLOAT      = std::numeric_limits<float>::max();
-const CharacterDirection LTR            = false;
-const CharacterDirection RTL            = !LTR;
-const float              LINE_SPACING   = 0.f;
-const float              MIN_LINE_SIZE  = 0.f;
-const Character          HYPHEN_UNICODE = 0x002D;
+const float              MAX_FLOAT          = std::numeric_limits<float>::max();
+const CharacterDirection LTR                = false;
+const CharacterDirection RTL                = !LTR;
+const float              LINE_SPACING       = 0.f;
+const float              MIN_LINE_SIZE      = 0.f;
+const Character          HYPHEN_UNICODE     = 0x002D;
+const float              RELATIVE_LINE_SIZE = 1.f;
 
 inline bool isEmptyLineAtLast(const Vector<LineRun>& lines, const Vector<LineRun>::Iterator& line)
 {
@@ -155,8 +163,52 @@ struct Engine::Impl
   : mLayout{Layout::Engine::SINGLE_LINE_BOX},
     mCursorWidth{0.f},
     mDefaultLineSpacing{LINE_SPACING},
-    mDefaultLineSize{MIN_LINE_SIZE}
+    mDefaultLineSize{MIN_LINE_SIZE},
+    mRelativeLineSize{RELATIVE_LINE_SIZE}
+  {
+  }
+
+  /**
+   * @brief get the line spacing.
+   *
+   * @param[in] textSize The text size.
+   * @return the line spacing value.
+   */
+  float GetLineSpacing(float textSize)
   {
+    float lineSpacing;
+    float relTextSize;
+
+    // Sets the line size
+    lineSpacing = mDefaultLineSize - textSize;
+    lineSpacing = lineSpacing < 0.f ? 0.f : lineSpacing;
+
+    // Add the line spacing
+    lineSpacing += mDefaultLineSpacing;
+
+    //subtract line spcaing if relativeLineSize < 1 & larger than min height
+    relTextSize = textSize * mRelativeLineSize;
+    if(relTextSize > mDefaultLineSize)
+    {
+      if(mRelativeLineSize < 1)
+      {
+        //subtract the difference (always will be positive)
+        lineSpacing -= (textSize - relTextSize);
+      }
+      else
+      {
+        //reverse the addition in the top.
+        if(mDefaultLineSize > textSize)
+        {
+          lineSpacing -= mDefaultLineSize - textSize;
+        }
+
+        //add difference instead
+        lineSpacing += relTextSize - textSize;
+      }
+    }
+
+    return lineSpacing;
   }
 
   /**
@@ -187,12 +239,7 @@ struct Engine::Impl
     // Sets the minimum descender.
     lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender);
 
-    // Sets the line size
-    lineLayout.lineSpacing = mDefaultLineSize - (lineLayout.ascender + -lineLayout.descender);
-    lineLayout.lineSpacing = lineLayout.lineSpacing < 0.f ? 0.f : lineLayout.lineSpacing;
-
-    // Add the line spacing
-    lineLayout.lineSpacing += mDefaultLineSpacing;
+    lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender);
   }
 
   /**
@@ -1257,7 +1304,7 @@ struct Engine::Impl
       layoutSize.width = layoutParameters.boundingBox.width;
       if(layoutSize.height < Math::MACHINE_EPSILON_1000)
       {
-        layoutSize.height += GetLineHeight(*lineRun);
+        layoutSize.height += GetLineHeight(*lineRun, true);
       }
 
       const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
@@ -1353,10 +1400,7 @@ struct Engine::Impl
     lineRun.direction = layout.direction;
     lineRun.ellipsis  = false;
 
-    lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
-    lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
-
-    lineRun.lineSpacing += mDefaultLineSpacing;
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
 
     // Update the actual size.
     if(lineRun.width > layoutSize.width)
@@ -1364,7 +1408,7 @@ struct Engine::Impl
       layoutSize.width = lineRun.width;
     }
 
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, isLastLine);
   }
 
   /**
@@ -1410,12 +1454,9 @@ struct Engine::Impl
     lineRun.direction                       = LTR;
     lineRun.ellipsis                        = false;
 
-    lineRun.lineSpacing = mDefaultLineSize - (lineRun.ascender + -lineRun.descender);
-    lineRun.lineSpacing = lineRun.lineSpacing < 0.f ? 0.f : lineRun.lineSpacing;
+    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
 
-    lineRun.lineSpacing += mDefaultLineSpacing;
-
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, true);
   }
 
   /**
@@ -1432,14 +1473,15 @@ struct Engine::Impl
         it != endIt;
         ++it)
     {
-      const LineRun& line = *it;
+      const LineRun& line       = *it;
+      bool           isLastLine = (it + 1 == endIt);
 
       if(line.width > layoutSize.width)
       {
         layoutSize.width = line.width;
       }
 
-      layoutSize.height += GetLineHeight(line);
+      layoutSize.height += GetLineHeight(line, isLastLine);
     }
   }
 
@@ -1811,14 +1853,7 @@ struct Engine::Impl
         }
 
         // Updates the vertical pen's position.
-        penY += -layout.descender + layout.lineSpacing + mDefaultLineSpacing;
-        // If there is a defaultLineSize, updates the pen's position.
-        if(mDefaultLineSize > 0.f)
-        {
-          float lineSpacing = mDefaultLineSize - (layout.ascender + -layout.descender);
-          lineSpacing       = lineSpacing < 0.f ? 0.f : lineSpacing;
-          penY += lineSpacing;
-        }
+        penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender);
 
         // Increase the glyph index.
         index = nextIndex;
@@ -2077,6 +2112,7 @@ struct Engine::Impl
   float mDefaultLineSize;
 
   IntrusivePtr<Metrics> mMetrics;
+  float                 mRelativeLineSize;
 };
 
 Engine::Engine()
@@ -2168,6 +2204,16 @@ float Engine::GetDefaultLineSize() const
   return mImpl->mDefaultLineSize;
 }
 
+void Engine::SetRelativeLineSize(float relativeLineSize)
+{
+  mImpl->mRelativeLineSize = relativeLineSize;
+}
+
+float Engine::GetRelativeLineSize() const
+{
+  return mImpl->mRelativeLineSize;
+}
+
 } // namespace Layout
 
 } // namespace Text
index e11c549..6b78e87 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H
 
 /*
- * 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.
@@ -166,6 +166,20 @@ public:
    */
   float GetDefaultLineSize() const;
 
+  /**
+   * @brief Sets relative line size to the original line size.
+   *
+   * @param[in] relativeLineSize The relative line size.
+   */
+  void SetRelativeLineSize(float relativeLineSize);
+
+  /**
+   * @brief Retrieves the relative line size.
+   *
+   * @return The relative line size.
+   */
+  float GetRelativeLineSize() const;
+
 private:
   // Undefined
   Engine(const Engine& handle);
index 52c47a1..c0bb095 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_LINE_RUN_H
 
 /*
- * 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.
@@ -52,8 +52,9 @@ struct LineRun
  * @brief Get the line height for the specified line run.
  *
  * @param[in] lineRun The line runs to get the height for.
+ * @param[in] isLastLine whether this is the last line in the text.
  */
-float GetLineHeight(const LineRun lineRun);
+float GetLineHeight(const LineRun lineRun, bool isLastLine);
 
 } // namespace Text
 
index 290c229..cee6a88 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.
@@ -334,6 +334,8 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
 
     const LineIndex lineIndex         = visualModel->GetLineOfCharacter(characterIndex);
     const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex);
+    const LineIndex lastLineIndex     = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+    const bool      isLastLine        = (previousLineIndex == lastLineIndex);
 
     // Retrieve the cursor position info.
     CursorInfo cursorInfo;
@@ -344,7 +346,7 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
     const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex);
 
     // Get the next hit 'y' point.
-    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line);
+    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line, isLastLine);
 
     // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
     bool matchedCharacter = false;
@@ -379,8 +381,12 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const
       // Get the line below.
       const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u);
 
+      // Get last line index
+      const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+      const bool      isLastLine    = (lineIndex + 1u == lastLineIndex);
+
       // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line);
+      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line, isLastLine);
 
       // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
       bool matchedCharacter = false;
index 294b534..3850f12 100644 (file)
@@ -712,6 +712,23 @@ bool Controller::Impl::SetDefaultLineSize(float lineSize)
   return false;
 }
 
+bool Controller::Impl::SetRelativeLineSize(float relativeLineSize)
+{
+  if(std::fabs(relativeLineSize - GetRelativeLineSize()) > Math::MACHINE_EPSILON_1000)
+  {
+    mLayoutEngine.SetRelativeLineSize(relativeLineSize);
+
+    RelayoutAllCharacters();
+    return true;
+  }
+  return false;
+}
+
+float Controller::Impl::GetRelativeLineSize()
+{
+  return mLayoutEngine.GetRelativeLineSize();
+}
+
 string Controller::Impl::GetSelectedText()
 {
   string text;
index 4b1db94..0757bc0 100644 (file)
@@ -627,6 +627,16 @@ struct Controller::Impl
   bool SetDefaultLineSize(float lineSize);
 
   /**
+   * @copydoc Controller::SetRelativeLineSize
+   */
+  bool SetRelativeLineSize(float relativeLineSize);
+
+  /**
+   * @copydoc Controller::GetRelativeLineSize
+   */
+  float GetRelativeLineSize();
+
+  /**
    * @copydoc Text::Controller::GetPrimaryCursorPosition()
    */
   CharacterIndex GetPrimaryCursorPosition() const;
index 9ea1e60..9de7dba 100644 (file)
@@ -948,6 +948,16 @@ float Controller::GetDefaultLineSize() const
   return mImpl->mLayoutEngine.GetDefaultLineSize();
 }
 
+bool Controller::SetRelativeLineSize(float relativeLineSize)
+{
+  return mImpl->SetRelativeLineSize(relativeLineSize);
+}
+
+float Controller::GetRelativeLineSize() const
+{
+  return mImpl->GetRelativeLineSize();
+}
+
 void Controller::SetInputColor(const Vector4& color)
 {
   InputProperties::SetInputColor(*this, color);
index f461058..2a37c3b 100644 (file)
@@ -1262,6 +1262,22 @@ public: // Default style & Input style
   float GetDefaultLineSize() const;
 
   /**
+   * @brief Sets the relative line size to the original line size.
+   *
+   * @param[in] relativeLineSize The relativeline size.
+   *
+   * @return True if relativeLineSize has been updated, false otherwise
+   */
+  bool SetRelativeLineSize(float lineSize);
+
+  /**
+   * @brief Retrieves the relative line size.
+   *
+   * @return The relative line size.
+   */
+  float GetRelativeLineSize() const;
+
+  /**
    * @brief Sets the input text's color.
    *
    * @param[in] color The input text's color.
index 9fa5ad1..bde5517 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.
@@ -32,13 +32,14 @@ namespace Toolkit
 {
 namespace Text
 {
-bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines)
+bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines, bool& isLastLine)
 {
   if(index == lastGlyphOfLine)
   {
     ++lineIndex;
     if(lineIndex < numberOfLines)
     {
+      isLastLine = (lineIndex + 1 == numberOfLines);
       ++lineRun;
       return true;
     }
@@ -47,11 +48,11 @@ bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, Glyp
   return false;
 }
 
-void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine)
+void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine, bool isLastLine)
 {
   lastGlyphOfLine   = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
   currentLineOffset = currentLineOffset + currentLineHeight;
-  currentLineHeight = GetLineHeight(*lineRun);
+  currentLineHeight = GetLineHeight(*lineRun, isLastLine);
 }
 
 void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector<Vector2>& sizesList, Vector<Vector2>& positionsList)
@@ -100,6 +101,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
   GlyphIndex   glyphEnd       = *(charactersToGlyphBuffer + endIndex) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
   LineIndex    lineIndex      = visualModel->GetLineOfCharacter(startIndex);
   Length       numberOfLines  = visualModel->GetTotalNumberOfLines();
+  bool         isLastLine     = lineIndex + 1 == numberOfLines;
 
   LineIndex firstLineIndex = lineIndex;
   Size      textInLineSize;
@@ -109,7 +111,7 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
 
   //get the first line and its vertical offset
   float      currentLineOffset = CalculateLineOffset(visualModel->mLines, firstLineIndex);
-  float      currentLineHeight = GetLineHeight(*lineRun);
+  float      currentLineHeight = GetLineHeight(*lineRun, isLastLine);
   GlyphIndex lastGlyphOfLine   = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1;
 
   // Check if the first/last glyph is a ligature that needs be splitted like English fi or Arabic ﻻ.
@@ -148,9 +150,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
             positionsList.PushBack(blockPos);
           }
 
-          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
           {
-            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
           }
           // Ignore any glyph that was removed
           continue;
@@ -165,9 +167,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
         }
         else if((ellipsisPosition == DevelText::EllipsisPosition::START) && (index <= startIndexOfGlyphs))
         {
-          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+          if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
           {
-            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+            UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
           }
 
           continue;
@@ -214,9 +216,9 @@ void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterInd
       currentSize.y     = currentLineHeight;
 
       // if there is next line to retrieve.
-      if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+      if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines, isLastLine))
       {
-        UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+        UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine, isLastLine);
       }
     }
 
index 8e43a87..a36f81f 100644 (file)
@@ -148,7 +148,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;
 
@@ -260,6 +262,8 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
       ++lineIndex;
       if(lineIndex < firstLineIndex + numberOfLines)
       {
+        float currentLineSpacing = lineRun->lineSpacing;
+
         // Retrieve the next line.
         ++lineRun;
 
@@ -279,7 +283,19 @@ void SelectionHandleController::Reposition(Controller::Impl& impl)
         // Update the line's vertical offset.
         selectionBoxInfo->lineOffset = currentLineOffset + currentLineHeight;
 
-        selectionBoxInfo->lineHeight = GetLineHeight(*lineRun);
+        if(currentLineSpacing < 0)
+        {
+          selectionBoxInfo->lineOffset += currentLineSpacing;
+        }
+
+        // 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;
+        }
       }
     }
   }
index ed64520..fdccbe1 100644 (file)
@@ -279,7 +279,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
           const LineRun& elidedLine = *ellipsisLine;
 
           if((1u == numberOfLines) &&
-             (GetLineHeight(elidedLine) > mImpl->mVisualModel->mControlSize.height))
+             (GetLineHeight(elidedLine, true) > mImpl->mVisualModel->mControlSize.height))
           {
             // Replace the first glyph with ellipsis glyph
             auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;
index 7dd847e..e381294 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 11;
+const unsigned int TOOLKIT_MICRO_VERSION = 12;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index fba8567..f1eae32 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.1.11
+Version:    2.1.12
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT