fix issue with text size with negative line spacing 83/271783/2
authorabdullah <abdullahhasan10@gmail.com>
Mon, 28 Feb 2022 14:50:04 +0000 (17:50 +0300)
committerabdullah <abdullahhasan10@gmail.com>
Tue, 1 Mar 2022 14:25:07 +0000 (17:25 +0300)
Change-Id: If19a05e9b037bcf4076bc1761bab9976d652e6f3

automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/line-run.h
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
dali-toolkit/internal/text/text-geometry.cpp
dali-toolkit/internal/text/text-view.cpp

index 0c3ab82..7c391b5 100644 (file)
@@ -5788,6 +5788,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..b4d943d 100644 (file)
@@ -2655,6 +2655,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 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 9137a2f..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;
index c8addcc..a85f5f6 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
@@ -1257,7 +1264,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;
@@ -1364,7 +1371,7 @@ struct Engine::Impl
       layoutSize.width = lineRun.width;
     }
 
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, isLastLine);
   }
 
   /**
@@ -1415,7 +1422,7 @@ struct Engine::Impl
 
     lineRun.lineSpacing += mDefaultLineSpacing;
 
-    layoutSize.height += GetLineHeight(lineRun);
+    layoutSize.height += GetLineHeight(lineRun, true);
   }
 
   /**
@@ -1432,14 +1439,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);
     }
   }
 
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 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 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;