Add RequestAsyncRenderWithFixedWidth to label
authorBowon Ryu <bowon.ryu@samsung.com>
Wed, 10 Jul 2024 01:24:29 +0000 (10:24 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Wed, 10 Jul 2024 01:24:29 +0000 (10:24 +0900)
Requests asynchronous text rendering with a fixed width.
The height is determined by the content of the text when rendered with the given width.
The result will be the same as the height returned by GetHeightForWidth.

Change-Id: I60b3d5355089aaaa1fb438ee963ade26ee8c050a
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/text/async-text/async-text-loader-impl.cpp
dali-toolkit/internal/text/async-text/async-text-loader-impl.h
dali-toolkit/internal/text/async-text/async-text-loader.h
dali-toolkit/internal/visuals/text/text-visual.cpp

index 79c44d08b5cbcdd52573214d14ccf90dc962a2b6..1e0032538b5ad5c0248acb127111d1fef167ab3f 100644 (file)
@@ -95,6 +95,11 @@ void RequestAsyncRenderWithFixedSize(TextLabel textLabel, float width, float hei
   GetImpl(textLabel).RequestAsyncRenderWithFixedSize(width, height);
 }
 
+void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width)
+{
+  GetImpl(textLabel).RequestAsyncRenderWithFixedWidth(width);
+}
+
 } // namespace DevelTextLabel
 
 } // namespace Toolkit
index df8d7f42dbc85ff7a69b73fb2db06989df686ff5..e71ab825ba759401bbe0d70e488c32b703090087 100644 (file)
@@ -390,6 +390,16 @@ DALI_TOOLKIT_API bool IsRemoveBackInset(TextLabel textLabel);
  */
 DALI_TOOLKIT_API void RequestAsyncRenderWithFixedSize(TextLabel textLabel, float width, float height);
 
+/**
+ * @brief Requests asynchronous text rendering with a fixed width.
+ * The height is determined by the content of the text when rendered with the given width.
+ * The result will be the same as the height returned by GetHeightForWidth.
+ *
+ * @param[in] textLabel The instance of TextLabel.
+ * @param[in] width The width of text to render.
+ */
+DALI_TOOLKIT_API void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width);
+
 /**
  * @brief Anchor clicked signal type.
  *
index 8df21c7a3ca102cb56774c7bfc31f88d27cc793b..e50212d5db8f4217a921bb4cb07b5e3f085cf359 100644 (file)
@@ -1595,7 +1595,12 @@ void TextLabel::AsyncLoadComplete(Text::AsyncTextRenderInfo renderInfo)
   // To avoid flickering issues, enable/disable the background visual when async load is completed.
   EnableControlBackground(!mController->IsTextCutout());
 
-  EmitAsyncTextRenderedSignal(renderInfo.renderedSize.width, renderInfo.renderedSize.height);
+  Actor self = Self();
+
+  Extents padding;
+  padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+  EmitAsyncTextRenderedSignal(renderInfo.renderedSize.width + (padding.start + padding.end), renderInfo.renderedSize.height + (padding.top + padding.bottom));
 }
 
 void TextLabel::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
@@ -1737,35 +1742,69 @@ void TextLabel::EnableControlBackground(const bool enable)
 
 void TextLabel::RequestAsyncRenderWithFixedSize(float width, float height)
 {
-  if(mController->IsAsyncTextLoadEnabled())
-  {
-    DALI_LOG_RELEASE_INFO("Request size : %f, %f\n", width, height);
+  DALI_LOG_RELEASE_INFO("Request size : %f, %f\n", width, height);
 
-    Actor self = Self();
+  if(!mController->IsAsyncTextLoadEnabled())
+  {
+    DALI_LOG_WARNING("IsAsyncTextLoadEnabled is false\n");
+    return;
+  }
 
-    Extents padding;
-    padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+  Actor self = Self();
 
-    Vector2 contentSize(width - (padding.start + padding.end), height - (padding.top + padding.bottom));
+  Extents padding;
+  padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
 
-    // Support Right-To-Left
-    Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+  Vector2 contentSize(width - (padding.start + padding.end), height - (padding.top + padding.bottom));
 
-    // Support Right-To-Left of padding
-    if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
-    {
-      std::swap(padding.start, padding.end);
-    }
+  // Support Right-To-Left
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
 
-    AsyncTextParameters parameters = GetAsyncTextParameters(contentSize, padding, layoutDirection);
-    TextVisual::UpdateAsyncRenderer(mVisual, parameters);
-    mTextUpdateNeeded = false;
-    mIsPropertyUpdated = false;
+  // Support Right-To-Left of padding
+  if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+  {
+    std::swap(padding.start, padding.end);
   }
-  else
+
+  AsyncTextParameters parameters = GetAsyncTextParameters(contentSize, padding, layoutDirection);
+  TextVisual::UpdateAsyncRenderer(mVisual, parameters);
+  mTextUpdateNeeded = false;
+  mIsPropertyUpdated = false;
+}
+
+void TextLabel::RequestAsyncRenderWithFixedWidth(float width)
+{
+  DALI_LOG_RELEASE_INFO("Request width : %f\n", width);
+
+  if(!mController->IsAsyncTextLoadEnabled())
   {
     DALI_LOG_WARNING("IsAsyncTextLoadEnabled is false\n");
+    return;
   }
+
+  Actor self = Self();
+
+  Extents padding;
+  padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+  Vector2 contentSize(width - (padding.start + padding.end), 0.0f);
+
+  // Support Right-To-Left
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+
+  // Support Right-To-Left of padding
+  if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+  {
+    std::swap(padding.start, padding.end);
+  }
+
+  AsyncTextParameters parameters = GetAsyncTextParameters(contentSize, padding, layoutDirection);
+  parameters.isFixedSize = false;
+  parameters.isFixedWidth = true;
+
+  TextVisual::UpdateAsyncRenderer(mVisual, parameters);
+  mTextUpdateNeeded = false;
+  mIsPropertyUpdated = false;
 }
 
 std::string TextLabel::TextLabelAccessible::GetNameRaw() const
index 8c1a19800db4f6958a3bc4f1a2feec17d86d98ff..efcf2e7463f09a133c42ba97514ba40a0ccc00a6 100644 (file)
@@ -247,6 +247,14 @@ public:
    */
   void RequestAsyncRenderWithFixedSize(float width, float height);
 
+/**
+ * @brief Requests asynchronous text rendering with a fixed width.
+ * The height is determined by the content of the text when rendered with the given width.
+ * The result will be the same as the height returned by GetHeightForWidth.
+ *
+ * @param[in] width The width of text to render.
+ */
+  void RequestAsyncRenderWithFixedWidth(float width);
 
 private: // From Control
   /**
index 0090d1bbb751b1dfd1a20e4afcccc5bd15a3d008..7f1423beb6822202e068d9789c827a2a59455ca0 100644 (file)
@@ -1053,7 +1053,11 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters)
   renderInfo.styleEnabled          = styleEnabled;
   renderInfo.isOverlayStyle        = isOverlayStyle;
 
-  if(parameters.isFixedSize)
+  if(cutoutEnabled)
+  {
+    renderInfo.renderedSize = Size(static_cast<float>(renderInfo.width), static_cast<float>(renderInfo.height));
+  }
+  else if(parameters.isFixedSize || parameters.isFixedWidth)
   {
     renderInfo.renderedSize = Size(static_cast<float>(parameters.textWidth), static_cast<float>(parameters.textHeight));
   }
@@ -1065,19 +1069,50 @@ AsyncTextRenderInfo AsyncTextLoader::RenderText(AsyncTextParameters& parameters)
 {
   DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::RenderText\n");
 
-  Initialize();
+  if(parameters.isFixedWidth)
+  {
+    uint32_t height = ComputeHeightForWidth(parameters, parameters.textWidth);
+    parameters.textHeight = height;
+    mTextModel->mVisualModel->mControlSize = Size(parameters.textWidth, parameters.textHeight);
+  }
+  else
+  {
+    Initialize();
+    Update(parameters);
+    bool layoutUpdated = false;
+    Layout(parameters, layoutUpdated);
+  }
 
-  Update(parameters);
+  return Render(parameters);
+}
+
+uint32_t AsyncTextLoader::ComputeHeightForWidth(AsyncTextParameters& parameters, uint32_t width)
+{
+  DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::ComputeHeightForWidth\n");
 
+  uint32_t actualWidth  = parameters.textWidth;
+  uint32_t actualHeight = parameters.textHeight;
+
+  parameters.textWidth  = width;
+  parameters.textHeight = MAX_UINT32;
+
+  Initialize();
+  Update(parameters);
   bool layoutUpdated = false;
-  Layout(parameters, layoutUpdated);
 
-  return Render(parameters);
+  Size layoutSize = Layout(parameters, layoutUpdated);
+
+  // Restore actual size.
+  parameters.textWidth  = actualWidth;
+  parameters.textHeight = actualHeight;
+  mTextModel->mVisualModel->mControlSize = Size(parameters.textWidth, parameters.textHeight);
+
+  return layoutSize.height;
 }
 
-Size AsyncTextLoader::CalculateNaturalSize(AsyncTextParameters& parameters)
+Size AsyncTextLoader::ComputeNaturalSize(AsyncTextParameters& parameters)
 {
-  DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::CalculateNaturalSize\n");
+  DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::ComputeNaturalSize\n");
 
   uint32_t actualWidth  = parameters.textWidth;
   uint32_t actualHeight = parameters.textHeight;
@@ -1104,13 +1139,22 @@ AsyncTextRenderInfo AsyncTextLoader::RenderAutoScroll(AsyncTextParameters& param
 {
   DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::RenderAutoScroll\n");
 
-  const Size controlSize(static_cast<float>(parameters.textWidth), static_cast<float>(parameters.textHeight));
+  Size controlSize(static_cast<float>(parameters.textWidth), static_cast<float>(parameters.textHeight));
 
   // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only.
-  Size textNaturalSize = CalculateNaturalSize(parameters);
+  Size textNaturalSize = ComputeNaturalSize(parameters);
   textNaturalSize.width += (parameters.padding.start + parameters.padding.end);
   textNaturalSize.height += (parameters.padding.top + parameters.padding.bottom);
 
+  if(parameters.isFixedWidth)
+  {
+    // In case of a fixed width, textHeight is zero.
+    // The height calculated during layout should be set.
+    parameters.textHeight = static_cast<uint32_t>(textNaturalSize.height) - static_cast<uint32_t>(parameters.padding.top + parameters.padding.bottom);
+    controlSize.height = static_cast<float>(parameters.textHeight);
+    mTextModel->mVisualModel->mControlSize = Size(parameters.textWidth, parameters.textHeight);
+  }
+
   DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::RenderAutoScroll natural size : %f, %f, control size : %f, %f \n", textNaturalSize.x, textNaturalSize.y, controlSize.x, controlSize.y);
 
   // Calculate the actual gap before scrolling wraps.
@@ -1180,6 +1224,12 @@ bool AsyncTextLoader::CheckForTextFit(AsyncTextParameters& parameters, float poi
 
 AsyncTextRenderInfo AsyncTextLoader::RenderTextFit(AsyncTextParameters& parameters)
 {
+  if(parameters.isFixedWidth)
+  {
+    uint32_t height = ComputeHeightForWidth(parameters, parameters.textWidth);
+    parameters.textHeight = height;
+  }
+
   if(parameters.isTextFitArrayEnabled)
   {
     DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::RenderTextFit -> TextFitArray\n");
index b72ec83c37513b5ae3b7a6f39af7278218e39509..f7d80d99f6ea620948379bf78f93fffc091fc945 100644 (file)
@@ -128,13 +128,23 @@ private:
   AsyncTextRenderInfo Render(AsyncTextParameters& parameters);
 
   /**
-   * @brief Calculate natural size of text.
+   * @brief Compute natural size of text.
    *
-   * @param[in] parameters All options required to calculate size of text.
+   * @param[in] parameters All options required to compute size of text.
    *
    * @return The natural size of text.
    */
-  Size CalculateNaturalSize(AsyncTextParameters& parameters);
+  Size ComputeNaturalSize(AsyncTextParameters& parameters);
+
+  /**
+   * @brief Compute height for width of text.
+   *
+   * @param[in] parameters All options required to compute height of text.
+   * @param[in] width The width of text to compute.
+   *
+   * @return The height for width of text.
+   */
+  uint32_t ComputeHeightForWidth(AsyncTextParameters& parameters, uint32_t width);
 
   /**
    * @brief Check if the text fits.
index 578fca541a1be42f4b930aebbc64a701eaacfacf..86cb2fdec570bf3f18592d613d40b08f959ea033 100644 (file)
@@ -47,6 +47,7 @@ struct AsyncTextParameters
 {
   AsyncTextParameters()
   : isFixedSize{true},
+    isFixedWidth{false},
     maxTextureSize{0},
     text{},
     fontSize{0.f},
@@ -115,6 +116,7 @@ struct AsyncTextParameters
   }
 
   bool isFixedSize;
+  bool isFixedWidth;
 
   int maxTextureSize;     ///< The maximum size of texture.
 
index dc29820c0df0e091cd99762147d91d86be6674d5..6643be1173489ae2e12b49b5fb4bae87b4dc033e 100644 (file)
@@ -945,6 +945,7 @@ void TextVisual::LoadComplete(bool loadingSuccess, TextInformation textInformati
     {
       mAsyncTextInterface->AsyncLoadComplete(renderInfo);
     }
+
   }
   else
   {
@@ -970,7 +971,7 @@ void TextVisual::UpdateAsyncRenderer(Text::AsyncTextParameters& parameters)
     return;
   }
 
-  if((fabsf(parameters.textWidth) < Math::MACHINE_EPSILON_1000) || (fabsf(parameters.textHeight) < Math::MACHINE_EPSILON_1000) || parameters.text.empty())
+  if(!parameters.isFixedWidth && ((fabsf(parameters.textWidth) < Math::MACHINE_EPSILON_1000) || (fabsf(parameters.textHeight) < Math::MACHINE_EPSILON_1000) || parameters.text.empty()))
   {
     // Remove the texture set and any renderer previously set.
     RemoveRenderer(control, true);