Merge "fix issue with text size with negative line spacing" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Fri, 4 Mar 2022 03:02:45 +0000 (03:02 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 4 Mar 2022 03:02:45 +0000 (03:02 +0000)
1  2 
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp

@@@ -5765,42 -5765,6 +5765,42 @@@ int UtcDaliToolkitTextEditorUnderlineTy
    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 * 2, 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;
    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;
@@@ -2632,42 -2632,6 +2632,42 @@@ int UtcDaliToolkitTextLabelStrikethroug
    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 * 2, 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;
    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;
@@@ -37,11 -37,18 +37,18 @@@ namespace Toolki
  {
  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,13 -59,12 +59,13 @@@ namespac
  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)
  {
@@@ -156,55 -162,11 +163,55 @@@ struct Engine::Imp
    : 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;
 +  }
 +
 +  /**
     * @brief Updates the line ascender and descender with the metrics of a new font.
     *
     * @param[in] glyphMetrics The metrics of the new font.
      // 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);
    }
  
    /**
        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;
      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)
        layoutSize.width = lineRun.width;
      }
  
-     layoutSize.height += GetLineHeight(lineRun);
+     layoutSize.height += GetLineHeight(lineRun, isLastLine);
    }
  
    /**
      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 += mDefaultLineSpacing;
 +    lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
  
-     layoutSize.height += GetLineHeight(lineRun);
+     layoutSize.height += GetLineHeight(lineRun, true);
    }
  
    /**
          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);
      }
    }
  
          }
  
          // 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;
    float mDefaultLineSize;
  
    IntrusivePtr<Metrics> mMetrics;
 +  float                 mRelativeLineSize;
  };
  
  Engine::Engine()
@@@ -2196,16 -2176,6 +2204,16 @@@ float Engine::GetDefaultLineSize() cons
    return mImpl->mDefaultLineSize;
  }
  
 +void Engine::SetRelativeLineSize(float relativeLineSize)
 +{
 +  mImpl->mRelativeLineSize = relativeLineSize;
 +}
 +
 +float Engine::GetRelativeLineSize() const
 +{
 +  return mImpl->mRelativeLineSize;
 +}
 +
  } // namespace Layout
  
  } // namespace Text