From: Richard Huang Date: Mon, 18 Dec 2017 17:42:14 +0000 (+0000) Subject: Reduce memory consumption of TextLabel by reducing texture size X-Git-Tag: dali_1.3.6~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=cbe6a1281bbd60ad8722af8123451adb591a0a1a Reduce memory consumption of TextLabel by reducing texture size Change-Id: Ia7350a410d8f308b709bda2e4829eab3dc2ceebf --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp index 14f352c..44136a7 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace Dali; using namespace Toolkit; @@ -108,7 +109,7 @@ int UtcDaliTextRenderingControllerRender(void) DALI_TEST_CHECK( renderingController ); // Renders the text and creates the final bitmap. - PixelData bitmap = renderingController->Render( relayoutSize ); + PixelData bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_CHECK( bitmap ); DALI_TEST_EQUALS( 120u, bitmap.GetWidth(), TEST_LOCATION ); @@ -120,7 +121,7 @@ int UtcDaliTextRenderingControllerRender(void) controller->Relayout( relayoutSize ); // Renders the text and creates the final bitmap. - bitmap = renderingController->Render( relayoutSize ); + bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_CHECK( bitmap ); DALI_TEST_EQUALS( 120u, bitmap.GetWidth(), TEST_LOCATION ); @@ -131,7 +132,7 @@ int UtcDaliTextRenderingControllerRender(void) controller->Relayout( relayoutSize ); // Renders the text and creates the final bitmap. - bitmap = renderingController->Render( relayoutSize ); + bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_CHECK( bitmap ); DALI_TEST_EQUALS( 120u, bitmap.GetWidth(), TEST_LOCATION ); @@ -166,32 +167,32 @@ int UtcDaliTextTypesetterVerticalLineAlignment(void) DALI_TEST_CHECK( renderingController ); { - controller->SetVerticalLineAlignment(Dali::Toolkit::DevelText::VerticalLineAlignment::TOP); - controller->Relayout(relayoutSize); + controller->SetVerticalLineAlignment( Dali::Toolkit::DevelText::VerticalLineAlignment::TOP ); + controller->Relayout( relayoutSize ); // Renders the text and creates the final bitmap. - auto bitmap = renderingController->Render(relayoutSize); + auto bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_EQUALS( 60u, bitmap.GetHeight(), TEST_LOCATION ); } { - controller->SetVerticalLineAlignment(Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE); - controller->Relayout(relayoutSize); + controller->SetVerticalLineAlignment( Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE ); + controller->Relayout( relayoutSize ); // Renders the text and creates the final bitmap. - auto bitmap = renderingController->Render(relayoutSize); + auto bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_EQUALS( 60u, bitmap.GetHeight(), TEST_LOCATION ); } { - controller->SetVerticalLineAlignment(Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM); - controller->Relayout(relayoutSize); + controller->SetVerticalLineAlignment( Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM ); + controller->Relayout( relayoutSize ); // Renders the text and creates the final bitmap. - auto bitmap = renderingController->Render(relayoutSize); + auto bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); DALI_TEST_EQUALS( 60u, bitmap.GetHeight(), TEST_LOCATION ); } tet_result(TET_PASS); END_TEST; -} \ No newline at end of file +} 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 0cbb799..d1dff13 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -60,6 +60,19 @@ namespace Internal namespace { const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; + + /** + * @brief How the text visual should be aligned vertically inside the control. + * + * 0.0f aligns the text to the top, 0.5f aligns the text to the center, 1.0f aligns the text to the bottom. + * The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations). + */ + const float VERTICAL_ALIGNMENT_TABLE[ Text::VerticalAlignment::BOTTOM + 1 ] = + { + 0.0f, // VerticalAlignment::TOP + 0.5f, // VerticalAlignment::CENTER + 1.0f // VerticalAlignment::BOTTOM + }; } namespace @@ -940,10 +953,29 @@ void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) std::swap( padding.start, padding.end ); } + // Calculate the size of the visual that can fit the text + Size layoutSize = mController->GetTextModel()->GetLayoutSize(); + layoutSize.x = contentSize.x; + + const Vector2& shadowOffset = mController->GetTextModel()->GetShadowOffset(); + if ( shadowOffset.y > Math::MACHINE_EPSILON_1 ) + { + layoutSize.y += shadowOffset.y; + } + + float outlineWidth = mController->GetTextModel()->GetOutlineWidth(); + layoutSize.y += outlineWidth * 2.0f; + layoutSize.y = std::min( layoutSize.y, contentSize.y ); + + // Calculate the offset for vertical alignment only, as the layout engine will do the horizontal alignment. + Vector2 alignmentOffset; + alignmentOffset.x = 0.0f; + alignmentOffset.y = ( contentSize.y - layoutSize.y ) * VERTICAL_ALIGNMENT_TABLE[mController->GetVerticalAlignment()]; + Property::Map visualTransform; - visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, contentSize ) + visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, layoutSize ) .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) - .Add( Toolkit::Visual::Transform::Property::OFFSET, Vector2( padding.start, padding.top ) ) + .Add( Toolkit::Visual::Transform::Property::OFFSET, Vector2( padding.start, padding.top ) + alignmentOffset ) .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) ) .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN ) .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN ); @@ -1003,7 +1035,7 @@ void TextLabel::SetUpAutoScrolling() Text::TypesetterPtr typesetter = Text::Typesetter::New( mController->GetTextModel() ); - PixelData data = typesetter->Render( verifiedSize, Text::Typesetter::RENDER_TEXT_AND_STYLES, true, Pixel::RGBA8888 ); // ignore the horizontal alignment + PixelData data = typesetter->Render( verifiedSize, mController->GetTextDirection(), Text::Typesetter::RENDER_TEXT_AND_STYLES, true, Pixel::RGBA8888 ); // ignore the horizontal alignment Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 314bc63..901c477 100755 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -267,7 +267,7 @@ ViewModel* Typesetter::GetViewModel() return mModel; } -PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat ) +PixelData Typesetter::Render( const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat ) { // @todo. This initial implementation for a TextLabel has only one visible page. @@ -277,8 +277,32 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo // Retrieves the layout size. const Size& layoutSize = mModel->GetLayoutSize(); + const float outlineWidth = mModel->GetOutlineWidth(); + + // Set the offset for the horizontal alignment according to the text direction and outline width. + int penX = 0; + + switch( mModel->GetHorizontalAlignment() ) + { + case HorizontalAlignment::BEGIN: + { + // No offset to add. + break; + } + case HorizontalAlignment::CENTER: + { + penX += ( textDirection == Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ) ? -outlineWidth : outlineWidth; + break; + } + case HorizontalAlignment::END: + { + penX += ( textDirection == Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ) ? -outlineWidth * 2.0f : outlineWidth * 2.0f; + break; + } + } + // Set the offset for the vertical alignment. - int penY = 0u; + int penY = 0; switch( mModel->GetVerticalAlignment() ) { @@ -340,7 +364,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if( RENDER_MASK == behaviour ) { // Generate the image buffer as an alpha mask for color glyphs. - imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1 ); } else if( RENDER_NO_TEXT == behaviour ) { @@ -351,7 +375,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo else { // Generate the image buffer for the text with no style. - imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs -1 ); + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs -1 ); } if ( ( RENDER_NO_STYLES != behaviour ) && ( RENDER_MASK != behaviour ) ) @@ -362,7 +386,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( outlineWidth > Math::MACHINE_EPSILON_1 ) { // Create the image buffer for outline - Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs -1 ); + Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs -1 ); // Combine the two buffers imageBuffer = CombineImageBuffer( imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight ); @@ -375,7 +399,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) { // Create the image buffer for shadow - Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1 ); // Check whether it will be a soft shadow const float& blurRadius = mModel->GetShadowBlurRadius(); @@ -394,7 +418,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( underlineEnabled ) { // Create the image buffer for underline - Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); + Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1 ); // Combine the two buffers imageBuffer = CombineImageBuffer( imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight ); @@ -407,7 +431,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo return pixelData; } -Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex ) +Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex ) { // Retrieve lines, glyphs, positions and colors from the view model. const Length modelNumberOfLines = mModel->GetNumberOfLines(); @@ -451,6 +475,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth // Sets the horizontal offset of the line. glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast( line.alignmentOffset ); + glyphData.horizontalOffset += horizontalOffset; // Increases the vertical offset with the line's ascender. glyphData.verticalOffset += static_cast( line.ascender ); diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.h b/dali-toolkit/internal/text/rendering/text-typesetter.h index 285348e..453541b 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.h +++ b/dali-toolkit/internal/text/rendering/text-typesetter.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace Dali { @@ -102,13 +103,14 @@ public: * - Combines different image buffers to create the pixel data used to generate the final image * * @param[in] size The renderer size. + * @param[in] textDirection The direction of the text. * @param[in] behaviour The behaviour of how to render the text (i.e. whether to render the text only or the styles only or both). * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment (i.e. always render as if HORIZONTAL_ALIGN_BEGIN). * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). * * @return A pixel data with the text rendered. */ - PixelData Render( const Vector2& size, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888 ); + PixelData Render( const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888 ); private: /** @@ -137,13 +139,14 @@ private: * @param[in] style The style of the text. * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment, not ignored by default. * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). + * @param[in] horizontalOffset The horizontal offset to be added to the glyph's position. * @param[in] verticalOffset The vertical offset to be added to the glyph's position. * @param[in] fromGlyphIndex The index of the first glyph within the text to be drawn * @param[in] toGlyphIndex The index of the last glyph within the text to be drawn * * @return An image buffer with the text. */ - Devel::PixelBuffer CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex ); + Devel::PixelBuffer CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex ); /** * @brief Combine the two RGBA image buffers together. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index d454031..98862db 100755 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -3422,7 +3422,8 @@ bool Controller::DoRelayout( const Size& size, const float outlineWidth = static_cast( mImpl->mModel->GetOutlineWidth() ); // Set the layout parameters. - Layout::Parameters layoutParameters( size, + const Vector2 sizeOffset = Vector2(outlineWidth * 2.0f, outlineWidth * 2.0f); // The outline should be fit into the bounding box + Layout::Parameters layoutParameters( size - sizeOffset, textBuffer, lineBreakInfo.Begin(), wordBreakInfo.Begin(), diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index e44b005..e4c62f8 100755 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace Dali { @@ -697,7 +698,7 @@ void TextVisual::UpdateRenderer() const bool styleEnabled = ( shadowEnabled || underlineEnabled || outlineEnabled ); - TextureSet textureSet = GetTextTexture( relayoutSize, hasMultipleTextColors, containsEmoji, styleEnabled ); + TextureSet textureSet = GetTextTexture( mImpl->mTransform.mSize, hasMultipleTextColors, containsEmoji, styleEnabled ); mImpl->mRenderer.SetTextures( textureSet ); Shader shader = GetTextShader( mFactoryCache, hasMultipleTextColors, containsEmoji, styleEnabled ); @@ -752,8 +753,11 @@ TextureSet TextVisual::GetTextTexture( const Vector2& size, bool hasMultipleText // Create RGBA texture if the text contains emojis or multiple text colors, otherwise L8 texture Pixel::Format textPixelFormat = ( containsEmoji || hasMultipleTextColors ) ? Pixel::RGBA8888 : Pixel::L8; + // Check the text direction + Toolkit::DevelText::TextDirection::Type textDirection = mController->GetTextDirection(); + // Create a texture for the text without any styles - PixelData data = mTypesetter->Render( size, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat ); + PixelData data = mTypesetter->Render( size, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat ); // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. // In that case, create a texture. TODO: should tile the text. @@ -771,7 +775,7 @@ TextureSet TextVisual::GetTextTexture( const Vector2& size, bool hasMultipleText if ( styleEnabled ) { // Create RGBA texture for all the text styles (without the text itself) - PixelData styleData = mTypesetter->Render( size, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888 ); + PixelData styleData = mTypesetter->Render( size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888 ); Texture styleTexture = Texture::New( Dali::TextureType::TEXTURE_2D, styleData.GetPixelFormat(), @@ -787,7 +791,7 @@ TextureSet TextVisual::GetTextTexture( const Vector2& size, bool hasMultipleText if ( containsEmoji && !hasMultipleTextColors ) { // Create a L8 texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation - PixelData maskData = mTypesetter->Render( size, Text::Typesetter::RENDER_MASK, false, Pixel::L8 ); + PixelData maskData = mTypesetter->Render( size, textDirection, Text::Typesetter::RENDER_MASK, false, Pixel::L8 ); Texture maskTexture = Texture::New( Dali::TextureType::TEXTURE_2D, maskData.GetPixelFormat(),