Merge "fix issue in negative line spacing with key arrow down" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / text / text-utils-devel.cpp
index 97a1b57..c9ab7b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
 #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>
 #include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
@@ -172,7 +174,13 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti
 
   MarkupProcessData markupProcessData(colorRuns,
                                       fontDescriptionRuns,
-                                      textModel->mLogicalModel->mEmbeddedItems);
+                                      textModel->mLogicalModel->mEmbeddedItems,
+                                      textModel->mLogicalModel->mAnchors,
+                                      textModel->mLogicalModel->mUnderlinedCharacterRuns,
+                                      textModel->mLogicalModel->mBackgroundColorRuns,
+                                      textModel->mLogicalModel->mStrikethroughCharacterRuns,
+                                      textModel->mLogicalModel->mBoundedParagraphRuns,
+                                      textModel->mLogicalModel->mCharacterSpacingCharacterRuns);
 
   if(textParameters.markupEnabled)
   {
@@ -810,9 +818,17 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
   Text::ModelPtr& textModel  = internalDataModel.textModel;
   FontClient&     fontClient = internalDataModel.fontClient;
 
-  Vector<LineRun>& lines          = textModel->mVisualModel->mLines; // The laid out lines.
-  Vector<bool>&    isEmoji        = internalDataModel.isEmoji;
-  const Size       textLayoutArea = internalDataModel.textLayoutArea;
+  Vector<LineRun>&        lines                     = textModel->mVisualModel->mLines; // The laid out lines.
+  Vector<bool>&           isEmoji                   = internalDataModel.isEmoji;
+  const Size              textLayoutArea            = internalDataModel.textLayoutArea;
+  const float             modelCharacterSpacing     = textModel->mVisualModel->GetCharacterSpacing();
+  float                   calculatedAdvance         = 0.f;
+  Vector<CharacterIndex>& glyphToCharacterMap       = textModel->mVisualModel->mGlyphsToCharacters;
+  const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+
+  // Get the character-spacing runs.
+  const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
+
   ////////////////////////////////////////////////////////////////////////////////
   // Ellipsis the text.
   ////////////////////////////////////////////////////////////////////////////////
@@ -825,7 +841,7 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
     {
       Length finalNumberOfGlyphs = 0u;
 
-      if((line.ascender - line.descender) > 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.
@@ -898,7 +914,9 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen
                 firstPenSet = true;
               }
 
-              removedGlypsWidth += std::min(glyphToRemove.advance, (glyphToRemove.xBearing + glyphToRemove.width));
+              const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing);
+              calculatedAdvance            = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance);
+              removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width));
 
               // Calculate the width of the ellipsis glyph and check if it fits.
               const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
@@ -975,6 +993,7 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   const bool               isTextMirrored          = internalDataModel.isTextMirrored;
   const Vector<Character>& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters;
   const Length             numberOfCharacters      = internalDataModel.numberOfCharacters;
+  const auto               ellipsisPosition        = textModel->mEllipsisPosition;
 
   Layout::Type layout = Layout::SINGLELINE;
 
@@ -1012,8 +1031,12 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   const unsigned int radius = textParameters.radius - static_cast<unsigned int>(maxAscenderDescender);
 
   // Set the layout parameters.
-  internalDataModel.textLayoutArea = Size(static_cast<float>(textParameters.textWidth),
-                                          static_cast<float>(textParameters.textHeight));
+  Size textLayoutArea = Size(static_cast<float>(textParameters.textWidth),
+                             static_cast<float>(textParameters.textHeight));
+
+  // padding
+  Extents padding                  = textParameters.padding;
+  internalDataModel.textLayoutArea = Size(textLayoutArea.x - (padding.start + padding.end), textLayoutArea.y - (padding.top + padding.bottom));
 
   if(isCircularTextLayout)
   {
@@ -1024,9 +1047,8 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   // Resize the vector of positions to have the same size than the vector of glyphs.
   rendererParameters.positions.Resize(numberOfGlyphs);
 
-  textModel->mLineWrapMode                 = LineWrap::WORD;
-  textModel->mIgnoreSpacesAfterText        = false;
-  textModel->mMatchSystemLanguageDirection = false;
+  textModel->mLineWrapMode          = Text::LineWrap::WORD;
+  textModel->mIgnoreSpacesAfterText = false;
   Text::Layout::Parameters layoutParameters(internalDataModel.textLayoutArea,
                                             textModel);
 
@@ -1047,7 +1069,8 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   layoutEngine.LayoutText(layoutParameters,
                           newLayoutSize,
                           textParameters.ellipsisEnabled,
-                          isAutoScrollEnabled);
+                          isAutoScrollEnabled,
+                          ellipsisPosition);
 
   return newLayoutSize;
 }
@@ -1380,7 +1403,8 @@ void UpdateBuffer(Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x
   }
 
   const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(pixelFormat);
-  if(bytesPerPixel == 0u || bytesPerPixel == 12u || bytesPerPixel == 24u)
+  // Ignore when pixelFormat is invalid or contain float
+  if(bytesPerPixel == 0u || bytesPerPixel == 6u || bytesPerPixel == 12u)
   {
     return;
   }
@@ -1498,7 +1522,7 @@ Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters)
   ////////////////////////////////////////////////////////////////////////////////
   // Layout the text
   ////////////////////////////////////////////////////////////////////////////////
-  int boundingBox           = textParameters.textHeight;
+  int boundingBox           = textParameters.textHeight - (textParameters.padding.top + textParameters.padding.bottom);
   textParameters.textHeight = MAX_INT; // layout for the entire area.
   LayoutText(textParameters, rendererParameters, embeddedItemLayout, internalData);
 
@@ -1511,12 +1535,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 : (line.ascender + -line.descender);
+    lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line, isLastLine);
     penY += lineOffset;
     if((penY + lineOffset) > boundingBox)
     {