#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
#include <dali-toolkit/internal/text/rendering/view-model.h>
#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
using namespace Dali;
using namespace Toolkit;
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 );
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 );
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 );
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
+}
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
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 );
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(),
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.
// 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() )
{
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 )
{
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 ) )
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 );
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();
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 );
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();
// Sets the horizontal offset of the line.
glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast<int>( line.alignmentOffset );
+ glyphData.horizontalOffset += horizontalOffset;
// Increases the vertical offset with the line's ascender.
glyphData.verticalOffset += static_cast<int>( line.ascender );
#include <dali/public-api/images/pixel-data.h>
#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
namespace Dali
{
* - 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:
/**
* @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.
const float outlineWidth = static_cast<float>( 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(),
#include <dali-toolkit/internal/text/text-effects-style.h>
#include <dali-toolkit/internal/text/script-run.h>
#include <dali-toolkit/internal/text/text-enumerations-impl.h>
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
namespace Dali
{
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 );
// 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.
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(),
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(),