From 7917dce180896ccef9e6c5252dfcbf5ce817a847 Mon Sep 17 00:00:00 2001 From: Bowon Ryu Date: Tue, 18 Jun 2024 11:18:50 +0900 Subject: [PATCH] Add cutout to async text Change-Id: I20b52cdd4b20580e4b1bcde4dea778a2439f1012 Signed-off-by: Bowon Ryu --- .../controls/text-controls/text-label-impl.cpp | 3 + .../text/async-text/async-text-loader-impl.cpp | 83 +++++++++++++++++----- .../internal/text/async-text/async-text-loader.h | 13 +++- dali-toolkit/internal/visuals/text/text-visual.cpp | 25 +++++-- 4 files changed, 97 insertions(+), 27 deletions(-) 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 64b4cb2..8acea27 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -1383,6 +1383,9 @@ AsyncTextParameters TextLabel::GetAsyncTextParameters(const Vector2& contentSize parameters.autoScrollLoopDelay = mTextScroller->GetLoopDelay(); parameters.autoScrollGap = mTextScroller->GetGap(); } + parameters.cutout = mController->IsTextCutout(); + parameters.backgroundWithCutoutEnabled = mController->IsBackgroundWithCutoutEnabled(); + parameters.backgroundColorWithCutout = mController->GetBackgroundColorWithCutout(); return parameters; } 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 101ad73..9bf9f69 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 @@ -42,6 +42,12 @@ namespace Toolkit namespace { constexpr uint32_t MAX_UINT32 = std::numeric_limits::max(); +const float VERTICAL_ALIGNMENT_TABLE[Text::VerticalAlignment::BOTTOM + 1] = +{ + 0.0f, // VerticalAlignment::TOP + 0.5f, // VerticalAlignment::CENTER + 1.0f // VerticalAlignment::BOTTOM +}; } // namespace namespace Text @@ -387,6 +393,10 @@ void AsyncTextLoader::Update(AsyncTextParameters& parameters) mTextModel->mVisualModel->SetOutlineOffset(parameters.outlineOffset); } + mTextModel->mVisualModel->SetCutoutEnabled(parameters.cutout); + mTextModel->mVisualModel->SetBackgroundWithCutoutEnabled(parameters.backgroundWithCutoutEnabled); + mTextModel->mVisualModel->SetBackgroundColorWithCutout(parameters.backgroundColorWithCutout); + mTextModel->mRemoveFrontInset = parameters.removeFrontInset; mTextModel->mRemoveBackInset = parameters.removeBackInset; @@ -969,19 +979,21 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters) shadowEnabled = true; } - const bool outlineEnabled = mTextModel->GetOutlineWidth() > Math::MACHINE_EPSILON_1; - const bool backgroundEnabled = mTextModel->IsBackgroundEnabled(); - const bool markupOrSpannedText = parameters.enableMarkup || mTextModel->IsSpannedTextPlaced(); - const bool markupUnderlineEnabled = markupOrSpannedText && mTextModel->IsMarkupUnderlineSet(); - const bool markupStrikethroughEnabled = markupOrSpannedText && mTextModel->IsMarkupStrikethroughSet(); - const bool underlineEnabled = mTextModel->IsUnderlineEnabled() || markupUnderlineEnabled; - const bool strikethroughEnabled = mTextModel->IsStrikethroughEnabled() || markupStrikethroughEnabled; - const bool backgroundMarkupSet = mTextModel->IsMarkupBackgroundColorSet(); - const bool styleEnabled = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet); - const bool isOverlayStyle = underlineEnabled || strikethroughEnabled; + const bool outlineEnabled = mTextModel->GetOutlineWidth() > Math::MACHINE_EPSILON_1; + const bool backgroundEnabled = mTextModel->IsBackgroundEnabled(); + const bool markupOrSpannedText = parameters.enableMarkup || mTextModel->IsSpannedTextPlaced(); + const bool markupUnderlineEnabled = markupOrSpannedText && mTextModel->IsMarkupUnderlineSet(); + const bool markupStrikethroughEnabled = markupOrSpannedText && mTextModel->IsMarkupStrikethroughSet(); + const bool underlineEnabled = mTextModel->IsUnderlineEnabled() || markupUnderlineEnabled; + const bool strikethroughEnabled = mTextModel->IsStrikethroughEnabled() || markupStrikethroughEnabled; + const bool backgroundMarkupSet = mTextModel->IsMarkupBackgroundColorSet(); + const bool cutoutEnabled = mTextModel->IsCutoutEnabled(); + const bool backgroundWithCutoutEnabled = mTextModel->IsBackgroundWithCutoutEnabled(); + const bool styleEnabled = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet || cutoutEnabled || backgroundWithCutoutEnabled); + const bool isOverlayStyle = underlineEnabled || strikethroughEnabled; // Create RGBA texture if the text contains emojis or multiple text colors, otherwise L8 texture - Pixel::Format textPixelFormat = (containsColorGlyph || hasMultipleTextColors) ? Pixel::RGBA8888 : Pixel::L8; + Pixel::Format textPixelFormat = (containsColorGlyph || hasMultipleTextColors || cutoutEnabled) ? Pixel::RGBA8888 : Pixel::L8; // 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. @@ -997,29 +1009,62 @@ AsyncTextRenderInfo AsyncTextLoader::Render(AsyncTextParameters& parameters) layoutSize.y += outlineWidth * 2.0f; layoutSize.y = std::min(layoutSize.y, static_cast(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]); + 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); + } + 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); // Check the text direction Toolkit::DevelText::TextDirection::Type textDirection = mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT; - // Create a pixel data for the text without any styles - PixelData data = mTypesetter->Render(layoutSize, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat); - // Set information for creating pixel datas. AsyncTextRenderInfo renderInfo; renderInfo.width = static_cast(layoutSize.x); renderInfo.height = static_cast(layoutSize.y); - // Get the pixel data of text. - renderInfo.textPixelData = data; - // Set the direction of text. renderInfo.isTextDirectionRTL = mIsTextDirectionRTL; + Devel::PixelBuffer cutoutData; + if(cutoutEnabled) + { + cutoutData = mTypesetter->RenderWithPixelBuffer(layoutSize, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat); + + // Make transparent buffer. + // If the cutout is enabled, a separate texture is not used for the text. + Devel::PixelBuffer buffer = mTypesetter->CreateFullBackgroundBuffer(1, 1, Color::TRANSPARENT); + renderInfo.textPixelData = Devel::PixelBuffer::Convert(buffer); + + // Set the flag of cutout. + renderInfo.isCutout = cutoutEnabled && (cutoutData != nullptr); + } + else + { + // Create a pixel data for the text without any styles + renderInfo.textPixelData = mTypesetter->Render(layoutSize, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat); + } + if(styleEnabled) { - // Create RGBA pixel data for all the text styles (without the text itself) - renderInfo.stylePixelData = mTypesetter->Render(layoutSize, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888); + if(renderInfo.isCutout) + { + float cutoutAlpha = mTextModel->GetDefaultColor().a; + renderInfo.stylePixelData = mTypesetter->RenderWithCutout(layoutSize, textDirection, cutoutData, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888, cutoutAlpha); + } + else + { + // Create RGBA pixel data for all the text styles (without the text itself) + renderInfo.stylePixelData = mTypesetter->Render(layoutSize, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888); + } } if(isOverlayStyle) { 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 6a363c9..992c3c2 100644 --- a/dali-toolkit/internal/text/async-text/async-text-loader.h +++ b/dali-toolkit/internal/text/async-text/async-text-loader.h @@ -102,7 +102,10 @@ struct AsyncTextParameters autoScrollLoopCount{1}, autoScrollLoopDelay{0.0f}, autoScrollGap{0}, - isAutoScrollMaxTextureExceeded{false} + isAutoScrollMaxTextureExceeded{false}, + cutout{false}, + backgroundWithCutoutEnabled{false}, + backgroundColorWithCutout{Color::TRANSPARENT} { } @@ -181,6 +184,10 @@ struct AsyncTextParameters float autoScrollLoopDelay; int autoScrollGap; bool isAutoScrollMaxTextureExceeded : 1; + + bool cutout : 1; ///< Cutout enabled flag + bool backgroundWithCutoutEnabled : 1; ///< Background with cutout enabled flag. + Vector4 backgroundColorWithCutout; ///< Background color with cutout. }; struct AsyncTextRenderInfo @@ -199,7 +206,8 @@ struct AsyncTextRenderInfo containsColorGlyph(false), styleEnabled(false), isOverlayStyle(false), - isTextDirectionRTL(false) + isTextDirectionRTL(false), + isCutout(false) { } @@ -221,6 +229,7 @@ struct AsyncTextRenderInfo bool styleEnabled; bool isOverlayStyle; bool isTextDirectionRTL; + bool isCutout; }; /** diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index cd5a27c..219b18c 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -738,15 +738,28 @@ void TextVisual::LoadComplete(bool loadingSuccess, TextInformation textInformati alignmentOffset.x = 0.0f; alignmentOffset.y = (static_cast(parameters.textHeight) - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[parameters.verticalAlignment]; - // This affects font rendering quality. - // It need to be integerized. - Vector2 visualTransformOffset; - visualTransformOffset.x = roundf(parameters.padding.start + alignmentOffset.x); - visualTransformOffset.y = roundf(parameters.padding.top + alignmentOffset.y); - // 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 visualTransformOffset; + if(renderInfo.isCutout) + { + // When Cutout Enabled, the current visual must draw the entire control. + // so set the size to controlSize and offset to 0. + visualTransformOffset.x = 0.0f; + visualTransformOffset.y = 0.0f; + + // The layout size is set to the text control size including padding. + layoutSize = textControlSize; + } + else + { + // This affects font rendering quality. + // It need to be integerized. + visualTransformOffset.x = roundf(parameters.padding.start + alignmentOffset.x); + visualTransformOffset.y = roundf(parameters.padding.top + alignmentOffset.y); + } + // Transform offset is used for subpixel data upload in text tiling. // We should set the transform before creating a tiling texture. Property::Map visualTransform; -- 2.7.4