From 187db0585af795771c19e64354a3590abae3e71d Mon Sep 17 00:00:00 2001 From: Bowon Ryu Date: Wed, 10 Jul 2024 16:24:59 +0900 Subject: [PATCH] Add heightConstraint to async text method heightConstraint is the maximum available height of text to render. By setting the maximum available value, we can determine size within one task. Change-Id: I845cae451c7c0e7026ed0edaf95208dd56c3e7c2 Signed-off-by: Bowon Ryu --- .../controls/text-controls/text-label-devel.cpp | 8 +-- .../controls/text-controls/text-label-devel.h | 8 ++- .../controls/text-controls/text-label-impl.cpp | 14 ++-- .../controls/text-controls/text-label-impl.h | 7 +- .../text/async-text/async-text-loader-impl.cpp | 79 +++++++++++++--------- .../internal/text/async-text/async-text-loader.h | 8 +-- dali-toolkit/internal/visuals/text/text-visual.cpp | 10 +-- 7 files changed, 79 insertions(+), 55 deletions(-) diff --git a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp index 5dbbd79..6e2e741 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp @@ -95,14 +95,14 @@ void RequestAsyncRenderWithFixedSize(TextLabel textLabel, float width, float hei GetImpl(textLabel).RequestAsyncRenderWithFixedSize(width, height); } -void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width) +void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width, float heightConstraint) { - GetImpl(textLabel).RequestAsyncRenderWithFixedWidth(width); + GetImpl(textLabel).RequestAsyncRenderWithFixedWidth(width, heightConstraint); } -void RequestAsyncRenderWithConstraint(TextLabel textLabel, float widthConstraint) +void RequestAsyncRenderWithConstraint(TextLabel textLabel, float widthConstraint, float heightConstraint) { - GetImpl(textLabel).RequestAsyncRenderWithConstraint(widthConstraint); + GetImpl(textLabel).RequestAsyncRenderWithConstraint(widthConstraint, heightConstraint); } } // namespace DevelTextLabel diff --git a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h index bb2cc64..30ff3a1 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h @@ -394,11 +394,13 @@ DALI_TOOLKIT_API void RequestAsyncRenderWithFixedSize(TextLabel textLabel, float * @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. + * If the heightConstraint is given, the maximum height will be the heightConstraint. * * @param[in] textLabel The instance of TextLabel. * @param[in] width The width of text to render. + * @param[in] heightConstraint The maximum available height of text to render. */ -DALI_TOOLKIT_API void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width); +DALI_TOOLKIT_API void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, float width, float heightConstraint); /** * @brief Requests asynchronous rendering with the maximum available width using the given widthConstraint. @@ -407,11 +409,13 @@ DALI_TOOLKIT_API void RequestAsyncRenderWithFixedWidth(TextLabel textLabel, floa * If the width of the text content is larger than the widthConstraint, the width will be determined by the widthConstraint. * The height is determined by the content of the text when rendered with the given width. * In this case, the result will be the same as the height returned by GetHeightForWidth. + * If the heightConstraint is given, the maximum height will be the heightConstraint. * * @param[in] textLabel The instance of TextLabel. * @param[in] widthConstraint The maximum available width of text to render. + * @param[in] heightConstraint The maximum available height of text to render. */ -DALI_TOOLKIT_API void RequestAsyncRenderWithConstraint(TextLabel textLabel, float widthConstraint); +DALI_TOOLKIT_API void RequestAsyncRenderWithConstraint(TextLabel textLabel, float widthConstraint, float heightConstraint); /** * @brief Anchor clicked signal type. diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index fd2ea64..f0a5b11 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -1423,8 +1423,8 @@ AsyncTextParameters TextLabel::GetAsyncTextParameters(const Vector2& contentSize parameters.relativeLineSize = mController->GetRelativeLineSize(); parameters.characterSpacing = mController->GetCharacterSpacing(); parameters.fontSizeScale = mController->IsFontSizeScaleEnabled() ? mController->GetFontSizeScale() : 1.f; - parameters.textWidth = static_cast(contentSize.x); - parameters.textHeight = static_cast(contentSize.y); + parameters.textWidth = contentSize.width; + parameters.textHeight = contentSize.height; parameters.padding = padding; parameters.horizontalAlignment = mController->GetHorizontalAlignment(); parameters.verticalAlignment = mController->GetVerticalAlignment(); @@ -1774,9 +1774,9 @@ void TextLabel::RequestAsyncRenderWithFixedSize(float width, float height) mIsPropertyUpdated = false; } -void TextLabel::RequestAsyncRenderWithFixedWidth(float width) +void TextLabel::RequestAsyncRenderWithFixedWidth(float width, float heightConstraint) { - DALI_LOG_RELEASE_INFO("Request width : %f\n", width); + DALI_LOG_RELEASE_INFO("Request width : %f, height constraint : %f\n", width, heightConstraint); if(!mController->IsAsyncTextLoadEnabled()) { @@ -1789,7 +1789,7 @@ void TextLabel::RequestAsyncRenderWithFixedWidth(float width) Extents padding; padding = self.GetProperty(Toolkit::Control::Property::PADDING); - Vector2 contentSize(width - (padding.start + padding.end), 0.0f); + Vector2 contentSize(width - (padding.start + padding.end), heightConstraint - (padding.top + padding.bottom)); // Support Right-To-Left Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self); @@ -1808,7 +1808,7 @@ void TextLabel::RequestAsyncRenderWithFixedWidth(float width) mIsPropertyUpdated = false; } -void TextLabel::RequestAsyncRenderWithConstraint(float widthConstraint) +void TextLabel::RequestAsyncRenderWithConstraint(float widthConstraint, float heightConstraint) { DALI_LOG_RELEASE_INFO("Request width constraint : %f\n", widthConstraint); @@ -1823,7 +1823,7 @@ void TextLabel::RequestAsyncRenderWithConstraint(float widthConstraint) Extents padding; padding = self.GetProperty(Toolkit::Control::Property::PADDING); - Vector2 contentSize(widthConstraint - (padding.start + padding.end), 0.0f); + Vector2 contentSize(widthConstraint - (padding.start + padding.end), heightConstraint - (padding.top + padding.bottom)); // Support Right-To-Left Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self); diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index d94c49e..8911dfb 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -251,10 +251,12 @@ public: * @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. + * If the heightConstraint is given, the maximum height will be the heightConstraint. * * @param[in] width The width of text to render. + * @param[in] heightConstraint The maximum available height of text to render. */ - void RequestAsyncRenderWithFixedWidth(float width); + void RequestAsyncRenderWithFixedWidth(float width, float heightConstraint); /** * @brief Requests asynchronous rendering with the maximum available width using the given widthConstraint. @@ -263,10 +265,11 @@ public: * If the width of the text content is larger than the widthConstraint, the width will be determined by the widthConstraint. * The height is determined by the content of the text when rendered with the given width. * In this case, the result will be the same as the height returned by GetHeightForWidth. + * If the heightConstraint is given, the maximum height will be the heightConstraint. * * @param[in] widthConstraint The maximum available width of text to render. */ - void RequestAsyncRenderWithConstraint(float widthConstraint); + void RequestAsyncRenderWithConstraint(float widthConstraint, float heightConstraint); private: // From Control diff --git a/dali-toolkit/internal/text/async-text/async-text-loader-impl.cpp b/dali-toolkit/internal/text/async-text/async-text-loader-impl.cpp index 52ba9db..f81d1b9 100644 --- a/dali-toolkit/internal/text/async-text/async-text-loader-impl.cpp +++ b/dali-toolkit/internal/text/async-text/async-text-loader-impl.cpp @@ -41,7 +41,8 @@ namespace Toolkit { namespace { -constexpr uint32_t MAX_UINT32 = std::numeric_limits::max(); +constexpr float MAX_FLOAT = std::numeric_limits::max(); + const float VERTICAL_ALIGNMENT_TABLE[Text::VerticalAlignment::BOTTOM + 1] = { 0.0f, // VerticalAlignment::TOP @@ -177,7 +178,7 @@ void PrintParameters(AsyncTextParameters& parameters) DALI_LOG_RELEASE_INFO("--- minLineSize : %f, lineSpacing : %f, relativeLineSize : %f\n", parameters.minLineSize, parameters.lineSpacing, parameters.relativeLineSize); DALI_LOG_RELEASE_INFO("--- charSpacing : %f\n", parameters.characterSpacing); DALI_LOG_RELEASE_INFO("--- fontSizeScale : %f\n", parameters.fontSizeScale); - DALI_LOG_RELEASE_INFO("--- size : %u, %u\n", parameters.textWidth, parameters.textHeight); + DALI_LOG_RELEASE_INFO("--- size : %f, %f\n", parameters.textWidth, parameters.textHeight); DALI_LOG_RELEASE_INFO("--- padding : %.2f, %.2f, %.2f, %.2f\n", parameters.padding.start, parameters.padding.end, parameters.padding.top, parameters.padding.bottom); DALI_LOG_RELEASE_INFO("--- alignment : %d, %d, verticalLine : %d\n", parameters.horizontalAlignment, parameters.verticalAlignment, parameters.verticalLineAlignment); DALI_LOG_RELEASE_INFO("--- lineWrapMode : %d\n", parameters.lineWrapMode); @@ -802,7 +803,7 @@ Size AsyncTextLoader::Layout(AsyncTextParameters& parameters, bool& updated) mTextModel->mVisualModel->SetCharacterSpacing(parameters.characterSpacing); // Set the layout parameters. - Size textLayoutArea(static_cast(parameters.textWidth), static_cast(parameters.textHeight)); + Size textLayoutArea(parameters.textWidth, parameters.textHeight); mTextModel->mLineWrapMode = parameters.lineWrapMode; mTextModel->mIgnoreSpacesAfterText = false; @@ -964,7 +965,7 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters) // The width is the control's width, height is the minimum height of the text. // This calculated layout size determines the size of the pixel data buffer. Size layoutSize = mTextModel->mVisualModel->GetLayoutSize(); - layoutSize.x = static_cast(parameters.textWidth); + layoutSize.x = parameters.textWidth; if(shadowOffset.y > Math::MACHINE_EPSILON_1) { @@ -973,21 +974,21 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters) float outlineWidth = mTextModel->GetOutlineWidth(); layoutSize.y += outlineWidth * 2.0f; - layoutSize.y = std::min(layoutSize.y, static_cast(parameters.textHeight)); + layoutSize.y = std::min(layoutSize.y, parameters.textHeight); if(cutoutEnabled) { // We need to store the offset including padding and vertical alignment. float xOffset = parameters.padding.start; - float yOffset = parameters.padding.top + std::round((static_cast(parameters.textHeight) - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[parameters.verticalAlignment]); + float yOffset = parameters.padding.top + std::round((parameters.textHeight - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[parameters.verticalAlignment]); mTextModel->mVisualModel->SetOffsetWithCutout(Vector2(xOffset, yOffset)); // The layout size is set to the text control size including padding. - layoutSize.x = static_cast(parameters.textWidth) + (parameters.padding.start + parameters.padding.end); - layoutSize.y = static_cast(parameters.textHeight) + (parameters.padding.top + parameters.padding.bottom); + layoutSize.x = parameters.textWidth + (parameters.padding.start + parameters.padding.end); + layoutSize.y = parameters.textHeight + (parameters.padding.top + parameters.padding.bottom); } - DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::Render ControlSize : %f, %f, LayoutSize : %f, %f\n", static_cast(parameters.textWidth), static_cast(parameters.textHeight), layoutSize.x, layoutSize.y); + DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::Render ControlSize : %f, %f, LayoutSize : %f, %f\n", parameters.textWidth, parameters.textHeight, layoutSize.x, layoutSize.y); // Check the text direction Toolkit::DevelText::TextDirection::Type textDirection = mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT; @@ -1059,7 +1060,7 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters) } else { - renderInfo.renderedSize = Size(static_cast(parameters.textWidth), static_cast(parameters.textHeight)); + renderInfo.renderedSize = Size(parameters.textWidth, parameters.textHeight); } return renderInfo; @@ -1075,14 +1076,26 @@ AsyncTextRenderInfo AsyncTextLoader::RenderText(AsyncTextParameters& parameters) // textWidth is widthConstraint if(parameters.textWidth > textNaturalSize.width) { - parameters.textWidth = static_cast(textNaturalSize.width); + parameters.textWidth = textNaturalSize.width; } } if(parameters.renderType == AsyncTextParameters::FIXED_WIDTH || parameters.renderType == AsyncTextParameters::CONSTRAINT) { uint32_t height = ComputeHeightForWidth(parameters, parameters.textWidth); - parameters.textHeight = height; + + // textHeight is heightConstraint + if(parameters.textHeight < height) + { + bool layoutUpdated = false; + // Re-layout is required to apply new height. + Layout(parameters, layoutUpdated); + } + else + { + parameters.textHeight = height; + } + mTextModel->mVisualModel->mControlSize = Size(parameters.textWidth, parameters.textHeight); } else @@ -1100,11 +1113,11 @@ uint32_t AsyncTextLoader::ComputeHeightForWidth(AsyncTextParameters& parameters, { DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::ComputeHeightForWidth\n"); - uint32_t actualWidth = parameters.textWidth; - uint32_t actualHeight = parameters.textHeight; + float actualWidth = parameters.textWidth; + float actualHeight = parameters.textHeight; parameters.textWidth = width; - parameters.textHeight = MAX_UINT32; + parameters.textHeight = MAX_FLOAT; Initialize(); Update(parameters); @@ -1124,12 +1137,12 @@ Size AsyncTextLoader::ComputeNaturalSize(AsyncTextParameters& parameters) { DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::ComputeNaturalSize\n"); - uint32_t actualWidth = parameters.textWidth; - uint32_t actualHeight = parameters.textHeight; + float actualWidth = parameters.textWidth; + float actualHeight = parameters.textHeight; // To measure natural size, set the size of the control to the maximum. - parameters.textWidth = MAX_UINT32; - parameters.textHeight = MAX_UINT32; + parameters.textWidth = MAX_FLOAT; + parameters.textHeight = MAX_FLOAT; Initialize(); Update(parameters); @@ -1149,7 +1162,7 @@ AsyncTextRenderInfo AsyncTextLoader::RenderAutoScroll(AsyncTextParameters& param { DALI_LOG_RELEASE_INFO("-->AsyncTextLoader::RenderAutoScroll\n"); - Size controlSize(static_cast(parameters.textWidth), static_cast(parameters.textHeight)); + Size controlSize(parameters.textWidth, 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 = ComputeNaturalSize(parameters); @@ -1158,10 +1171,9 @@ AsyncTextRenderInfo AsyncTextLoader::RenderAutoScroll(AsyncTextParameters& param if(parameters.renderType == AsyncTextParameters::FIXED_WIDTH || parameters.renderType == AsyncTextParameters::CONSTRAINT) { - // In case of a fixed width, textHeight is zero. - // The height calculated during layout should be set. - parameters.textHeight = static_cast(textNaturalSize.height) - static_cast(parameters.padding.top + parameters.padding.bottom); - controlSize.height = static_cast(parameters.textHeight); + // The real height calculated during layout should be set. + parameters.textHeight = textNaturalSize.height - (parameters.padding.top + parameters.padding.bottom); + controlSize.height = parameters.textHeight; mTextModel->mVisualModel->mControlSize = Size(parameters.textWidth, parameters.textHeight); } @@ -1182,8 +1194,8 @@ AsyncTextRenderInfo AsyncTextLoader::RenderAutoScroll(AsyncTextParameters& param verifiedSize.width = maxTextureSize; if(textNaturalSize.width > maxTextureSize) { - uint32_t actualWidth = parameters.textWidth; - uint32_t actualHeight = parameters.textHeight; + float actualWidth = parameters.textWidth; + float actualHeight = parameters.textHeight; parameters.textWidth = verifiedSize.width; parameters.textHeight = textNaturalSize.height; @@ -1201,7 +1213,7 @@ AsyncTextRenderInfo AsyncTextLoader::RenderAutoScroll(AsyncTextParameters& param } uint32_t actualWidth = parameters.textWidth; - parameters.textWidth = static_cast(verifiedSize.width); + parameters.textWidth = verifiedSize.width; AsyncTextRenderInfo renderInfo = Render(parameters); @@ -1240,14 +1252,19 @@ AsyncTextRenderInfo AsyncTextLoader::RenderTextFit(AsyncTextParameters& paramete // textWidth is widthConstraint if(parameters.textWidth > textNaturalSize.width) { - parameters.textWidth = static_cast(textNaturalSize.width); + parameters.textWidth = textNaturalSize.width; } } if(parameters.renderType == AsyncTextParameters::FIXED_WIDTH || parameters.renderType == AsyncTextParameters::CONSTRAINT) { uint32_t height = ComputeHeightForWidth(parameters, parameters.textWidth); - parameters.textHeight = height; + + // textHeight is heightConstraint + if(parameters.textHeight > height) + { + parameters.textHeight = height; + } } if(parameters.isTextFitArrayEnabled) @@ -1266,7 +1283,7 @@ AsyncTextRenderInfo AsyncTextLoader::RenderTextFit(AsyncTextParameters& paramete mFitActualEllipsis = parameters.ellipsis; parameters.ellipsis = false; - Size allowedSize(static_cast(parameters.textWidth), static_cast(parameters.textHeight)); + Size allowedSize(parameters.textWidth, parameters.textHeight); // Sort in ascending order by PointSize. std::sort(fitOptions.begin(), fitOptions.end(), compareByPointSize); @@ -1367,7 +1384,7 @@ AsyncTextRenderInfo AsyncTextLoader::RenderTextFit(AsyncTextParameters& paramete parameters.ellipsis = false; float bestPointSize = minPointSize; - Size allowedSize(static_cast(parameters.textWidth), static_cast(parameters.textHeight)); + Size allowedSize(parameters.textWidth, parameters.textHeight); // check zero value if(pointInterval < 1.f) diff --git a/dali-toolkit/internal/text/async-text/async-text-loader.h b/dali-toolkit/internal/text/async-text/async-text-loader.h index 9603dc0..cf87b5e 100644 --- a/dali-toolkit/internal/text/async-text/async-text-loader.h +++ b/dali-toolkit/internal/text/async-text/async-text-loader.h @@ -72,8 +72,8 @@ struct AsyncTextParameters relativeLineSize{1.f}, characterSpacing{0.f}, fontSizeScale{1.f}, - textWidth{0u}, - textHeight{0u}, + textWidth{0.f}, + textHeight{0.f}, padding{0u, 0u, 0u, 0u}, horizontalAlignment{Text::HorizontalAlignment::BEGIN}, verticalAlignment{Text::VerticalAlignment::TOP}, @@ -147,8 +147,8 @@ struct AsyncTextParameters float characterSpacing; ///< The space between characters. float fontSizeScale; ///< The font's size scale. - uint32_t textWidth; ///< The width in pixels of the boundaries where the text is going to be laid-out. - uint32_t textHeight; ///< The height in pixels of the boundaries where the text is going to be laid-out. + float textWidth; ///< The width in pixels of the boundaries where the text is going to be laid-out. + float textHeight; ///< The height in pixels of the boundaries where the text is going to be laid-out. Extents padding; ///< The padding of the boundaries where the text is going to be laid-out. Text::HorizontalAlignment::Type horizontalAlignment; ///< The horizontal alignment: one of {BEGIN, CENTER, END}. diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index ccb02c6..d4c8268 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -736,10 +736,10 @@ void TextVisual::LoadComplete(bool loadingSuccess, TextInformation textInformati // Calculate the offset for vertical alignment only, as the layout engine will do the horizontal alignment. Vector2 alignmentOffset; alignmentOffset.x = 0.0f; - alignmentOffset.y = (static_cast(parameters.textHeight) - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[parameters.verticalAlignment]; + alignmentOffset.y = (parameters.textHeight - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[parameters.verticalAlignment]; // Size of the text control including padding. - Vector2 textControlSize(static_cast(parameters.textWidth) + (parameters.padding.start + parameters.padding.end), static_cast(parameters.textHeight) + (parameters.padding.top + parameters.padding.bottom)); + Vector2 textControlSize(parameters.textWidth + (parameters.padding.start + parameters.padding.end), parameters.textHeight + (parameters.padding.top + parameters.padding.bottom)); if(parameters.isAutoScrollEnabled) { @@ -992,10 +992,10 @@ void TextVisual::UpdateAsyncRenderer(Text::AsyncTextParameters& parameters) // Get the maximum texture size. const int maxTextureSize = Dali::GetMaxTextureSize(); - if(parameters.textWidth > static_cast(maxTextureSize)) + if(parameters.textWidth > maxTextureSize) { - DALI_LOG_WARNING("layoutSize(%u) > maxTextureSize(%d): To guarantee the behavior of Texture::New, layoutSize must not be bigger than maxTextureSize\n", parameters.textWidth, maxTextureSize); - parameters.textWidth = static_cast(maxTextureSize); + DALI_LOG_WARNING("layoutSize(%f) > maxTextureSize(%d): To guarantee the behavior of Texture::New, layoutSize must not be bigger than maxTextureSize\n", parameters.textWidth, maxTextureSize); + parameters.textWidth = maxTextureSize; } // This does not mean whether task is actually running or waiting. -- 2.7.4