X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Fdevel-api%2Ftext%2Ftext-utils-devel.cpp;h=e5ad92571454dda2f06e67d6b6c4509cf33dffb4;hp=c3ca9fb2a91f0910f308eccefb5e47f2565905c1;hb=5178b0e51437699c0e2196c88712a79032a2732b;hpb=3e429d522301e97a4333153145d56b9a127d89e8 diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index c3ca9fb..e5ad925 100755 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,11 @@ #include // EXTERNAL INCLUDES +#include #include -#include #include +#include #include -#include #include #include @@ -43,7 +43,6 @@ namespace Dali { - using namespace TextAbstraction; namespace Toolkit @@ -52,10 +51,8 @@ using namespace Text; namespace DevelText { - namespace Layout { - /** * @brief The text's layout. */ @@ -70,7 +67,6 @@ enum Type namespace CircularAlignment { - /** * @brief The enumerations for the circular alignment. */ @@ -84,57 +80,57 @@ enum Type } // namespace CircularAlignment const float TO_POINT_26_DOT_6 = 64.f; -const float TO_FLOAT = 1.f / 255.f; -const float TO_UCHAR = 255.f; -const bool RTL = true; -const float TWO_PI = 2.f * Dali::Math::PI; ///< 360 degrees in radians -const float RAD_135 = Math::PI_2 + Math::PI_4; ///< 135 degrees in radians; -const float RAD_225 = RAD_135 + Math::PI_2; ///< 225 degrees in radians; -const float RAD_270 = 3.f * Math::PI_2; ///< 270 degrees in radians; -const float RAD_315 = RAD_225 + Math::PI_2; ///< 315 degrees in radians; -const float MAX_INT = std::numeric_limits::max(); - -DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_TYPE ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, SINGLELINE ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, MULTILINE ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, CIRCULAR ) -DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_TYPE ) - -DALI_ENUM_TO_STRING_TABLE_BEGIN( CIRCULAR_ALIGNMENT_TYPE ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, BEGIN ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, CENTER ) -DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, END ) -DALI_ENUM_TO_STRING_TABLE_END( CIRCULAR_ALIGNMENT_TYPE ) +const float TO_FLOAT = 1.f / 255.f; +const float TO_UCHAR = 255.f; +const bool RTL = true; +const float TWO_PI = 2.f * Dali::Math::PI; ///< 360 degrees in radians +const float RAD_135 = Math::PI_2 + Math::PI_4; ///< 135 degrees in radians; +const float RAD_225 = RAD_135 + Math::PI_2; ///< 225 degrees in radians; +const float RAD_270 = 3.f * Math::PI_2; ///< 270 degrees in radians; +const float RAD_315 = RAD_225 + Math::PI_2; ///< 315 degrees in radians; +const float MAX_INT = std::numeric_limits::max(); + +DALI_ENUM_TO_STRING_TABLE_BEGIN(LAYOUT_TYPE) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::Layout, SINGLELINE) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::Layout, MULTILINE) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::Layout, CIRCULAR) +DALI_ENUM_TO_STRING_TABLE_END(LAYOUT_TYPE) + +DALI_ENUM_TO_STRING_TABLE_BEGIN(CIRCULAR_ALIGNMENT_TYPE) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::CircularAlignment, BEGIN) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::CircularAlignment, CENTER) + DALI_ENUM_TO_STRING_WITH_SCOPE(DevelText::CircularAlignment, END) +DALI_ENUM_TO_STRING_TABLE_END(CIRCULAR_ALIGNMENT_TYPE) struct InternalDataModel { - InternalDataModel( FontClient& fontClient, - MetricsPtr metrics, - Text::ModelPtr textModel ) - : fontClient( fontClient ), - metrics( metrics ), - textModel( textModel ), - numberOfCharacters{ 0u }, - isTextMirrored{ false }, - numberOfGlyphs{ 0u } + InternalDataModel(FontClient& fontClient, + MetricsPtr metrics, + Text::ModelPtr textModel) + : fontClient(fontClient), + metrics(metrics), + textModel(textModel), + numberOfCharacters{0u}, + isTextMirrored{false}, + numberOfGlyphs{0u} { - layoutEngine.SetMetrics( metrics ); + layoutEngine.SetMetrics(metrics); } - FontClient& fontClient; - MetricsPtr metrics; - Text::Layout::Engine layoutEngine; ///< The layout engine. - Text::ModelPtr textModel; ///< Pointer to the text's model. - Vector blendingMode; ///< How embedded items and bitmap font glyphs are blended with color text. - Vector isEmoji; ///< Whether the glyph is an emoji. + FontClient& fontClient; + MetricsPtr metrics; + Text::Layout::Engine layoutEngine; ///< The layout engine. + Text::ModelPtr textModel; ///< Pointer to the text's model. + Vector blendingMode; ///< How embedded items and bitmap font glyphs are blended with color text. + Vector isEmoji; ///< Whether the glyph is an emoji. - Vector mirroredUtf32Characters; // The utf32Characters Characters but mirrored if there are RTL text. + Vector mirroredUtf32Characters; // The utf32Characters Characters but mirrored if there are RTL text. - Length numberOfCharacters; // The number of characters (not glyphs!). - bool isTextMirrored ; // Whether the text has been mirrored. + Length numberOfCharacters; // The number of characters (not glyphs!). + bool isTextMirrored; // Whether the text has been mirrored. Length numberOfGlyphs; - Size textLayoutArea; + Size textLayoutArea; }; bool GetLayoutEnumeration(const Property::Value& propertyValue, DevelText::Layout::Type& layout) @@ -147,25 +143,24 @@ bool GetCircularAlignmentEnumeration(const Property::Value& propertyValue, Devel return Scripting::GetEnumerationProperty(propertyValue, CIRCULAR_ALIGNMENT_TYPE_TABLE, CIRCULAR_ALIGNMENT_TYPE_TABLE_COUNT, circularAlignment); } -void ShapeTextPreprocess( const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, InternalDataModel& internalDataModel ) +void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, InternalDataModel& internalDataModel) { - MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); - const uint8_t* utf8 = NULL; // pointer to the first character of the text (encoded in utf8) - Length textSize = 0u; // The length of the utf8 string. + const uint8_t* utf8 = NULL; // pointer to the first character of the text (encoded in utf8) + Length textSize = 0u; // The length of the utf8 string. - Length& numberOfCharacters = internalDataModel.numberOfCharacters; + Length& numberOfCharacters = internalDataModel.numberOfCharacters; Vector& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters; - Text::ModelPtr& textModel = internalDataModel.textModel; + Text::ModelPtr& textModel = internalDataModel.textModel; - Vector& utf32Characters = textModel->mLogicalModel->mText; // Characters encoded in utf32. - Vector& lineBreakInfo = textModel->mLogicalModel->mLineBreakInfo; // The line break info. - Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. - Vector& fontDescriptionRuns = textModel->mLogicalModel->mFontDescriptionRuns; // Desired font descriptions. - Vector& validFonts = textModel->mLogicalModel->mFontRuns; // Validated fonts. - Vector& bidirectionalInfo = textModel->mLogicalModel->mBidirectionalParagraphInfo; // The bidirectional info per paragraph. - Vector& directions = textModel->mLogicalModel->mCharacterDirections; // Character's directions. - Vector& colorRuns = textModel->mLogicalModel->mColorRuns; // colors of the text. + Vector& utf32Characters = textModel->mLogicalModel->mText; // Characters encoded in utf32. + Vector& lineBreakInfo = textModel->mLogicalModel->mLineBreakInfo; // The line break info. + Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. + Vector& fontDescriptionRuns = textModel->mLogicalModel->mFontDescriptionRuns; // Desired font descriptions. + Vector& validFonts = textModel->mLogicalModel->mFontRuns; // Validated fonts. + Vector& bidirectionalInfo = textModel->mLogicalModel->mBidirectionalParagraphInfo; // The bidirectional info per paragraph. + Vector& directions = textModel->mLogicalModel->mCharacterDirections; // Character's directions. + Vector& colorRuns = textModel->mLogicalModel->mColorRuns; // colors of the text. // the default font's description. FontDescription defaultFontDescription; @@ -175,11 +170,11 @@ void ShapeTextPreprocess( const RendererParameters& textParameters, TextAbstract // Process the markup string if the mark-up processor is enabled. //////////////////////////////////////////////////////////////////////////////// - MarkupProcessData markupProcessData( colorRuns, + MarkupProcessData markupProcessData(colorRuns, fontDescriptionRuns, - textModel->mLogicalModel->mEmbeddedItems ); + textModel->mLogicalModel->mEmbeddedItems); - if (textParameters.markupEnabled) + if(textParameters.markupEnabled) { ProcessMarkupString(textParameters.text, markupProcessData); textSize = markupProcessData.markupProcessedText.size(); @@ -203,34 +198,34 @@ void ShapeTextPreprocess( const RendererParameters& textParameters, TextAbstract // Transform a text array encoded in utf8 into an array encoded in utf32. // It returns the actual number of characters. - numberOfCharacters = Utf8ToUtf32( utf8, textSize, utf32Characters.Begin() ); - utf32Characters.Resize( numberOfCharacters ); + numberOfCharacters = Utf8ToUtf32(utf8, textSize, utf32Characters.Begin()); + utf32Characters.Resize(numberOfCharacters); //////////////////////////////////////////////////////////////////////////////// // Retrieve the Line and Word Break Info. //////////////////////////////////////////////////////////////////////////////// - lineBreakInfo.Resize( numberOfCharacters, LINE_NO_BREAK ); + lineBreakInfo.Resize(numberOfCharacters, LINE_NO_BREAK); - SetLineBreakInfo( utf32Characters, - 0u, - numberOfCharacters, - lineBreakInfo ); + SetLineBreakInfo(utf32Characters, + 0u, + numberOfCharacters, + lineBreakInfo); //////////////////////////////////////////////////////////////////////////////// // Retrieve the script runs. //////////////////////////////////////////////////////////////////////////////// - multilanguageSupport.SetScripts( utf32Characters, + multilanguageSupport.SetScripts(utf32Characters, 0u, numberOfCharacters, - scripts ); + scripts); // Check if there are emojis. // If there are an RGBA8888 pixel format is needed. - for( const auto& run : scripts ) + for(const auto& run : scripts) { - if( run.script == TextAbstraction::Script::EMOJI ) + if(run.script == TextAbstraction::Script::EMOJI) { rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888; break; @@ -243,107 +238,107 @@ void ShapeTextPreprocess( const RendererParameters& textParameters, TextAbstract // Set the description font run with the given text parameters. FontDescriptionRun fontDescriptionRun; - fontDescriptionRun.characterRun.characterIndex = 0u; + fontDescriptionRun.characterRun.characterIndex = 0u; fontDescriptionRun.characterRun.numberOfCharacters = numberOfCharacters; - fontDescriptionRun.familyLength = 0u; - fontDescriptionRun.familyName = nullptr; + fontDescriptionRun.familyLength = 0u; + fontDescriptionRun.familyName = nullptr; fontDescriptionRun.familyDefined = !textParameters.fontFamily.empty(); - if( fontDescriptionRun.familyDefined ) + if(fontDescriptionRun.familyDefined) { // The allocated memory will be freed when the logical model is destroyed. fontDescriptionRun.familyLength = textParameters.fontFamily.size(); - fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; - memcpy( fontDescriptionRun.familyName, textParameters.fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy(fontDescriptionRun.familyName, textParameters.fontFamily.c_str(), fontDescriptionRun.familyLength); } fontDescriptionRun.weightDefined = !textParameters.fontWeight.empty(); - if( fontDescriptionRun.weightDefined ) + if(fontDescriptionRun.weightDefined) { - fontDescriptionRun.weight = StringToWeight( textParameters.fontWeight.c_str() ); + fontDescriptionRun.weight = StringToWeight(textParameters.fontWeight.c_str()); } fontDescriptionRun.widthDefined = !textParameters.fontWidth.empty(); - if( fontDescriptionRun.widthDefined ) + if(fontDescriptionRun.widthDefined) { - fontDescriptionRun.width = StringToWidth( textParameters.fontWidth.c_str() ); + fontDescriptionRun.width = StringToWidth(textParameters.fontWidth.c_str()); } fontDescriptionRun.slantDefined = !textParameters.fontSlant.empty(); - if( fontDescriptionRun.slantDefined ) + if(fontDescriptionRun.slantDefined) { - fontDescriptionRun.slant = StringToSlant( textParameters.fontSlant.c_str() ); + fontDescriptionRun.slant = StringToSlant(textParameters.fontSlant.c_str()); } - fontDescriptionRun.sizeDefined = !EqualsZero( textParameters.fontSize ); - if( fontDescriptionRun.sizeDefined ) + fontDescriptionRun.sizeDefined = !EqualsZero(textParameters.fontSize); + if(fontDescriptionRun.sizeDefined) { - fontDescriptionRun.size = static_cast( textParameters.fontSize * TO_POINT_26_DOT_6 ); + fontDescriptionRun.size = static_cast(textParameters.fontSize * TO_POINT_26_DOT_6); } - fontDescriptionRuns.PushBack( fontDescriptionRun ); + fontDescriptionRuns.PushBack(fontDescriptionRun); // Validates the fonts. If there is a character with no assigned font it sets a default one. // After this call, fonts are validated. - multilanguageSupport.ValidateFonts( utf32Characters, - scripts, - fontDescriptionRuns, - defaultFontDescription, - defaultPointSize, - 0u, - numberOfCharacters, - validFonts ); + multilanguageSupport.ValidateFonts(utf32Characters, + scripts, + fontDescriptionRuns, + defaultFontDescription, + defaultPointSize, + 0u, + numberOfCharacters, + validFonts); //////////////////////////////////////////////////////////////////////////////// // Retrieve the Bidirectional info. //////////////////////////////////////////////////////////////////////////////// - bidirectionalInfo.Reserve( 1u ); + bidirectionalInfo.Reserve(1u); - SetBidirectionalInfo( utf32Characters, - scripts, - lineBreakInfo, - 0u, - numberOfCharacters, - bidirectionalInfo ); + SetBidirectionalInfo(utf32Characters, + scripts, + lineBreakInfo, + 0u, + numberOfCharacters, + bidirectionalInfo); const bool hasBidirectionalText = 0u != bidirectionalInfo.Count(); - if( hasBidirectionalText ) + if(hasBidirectionalText) { // Only set the character directions if there is right to left characters. - GetCharactersDirection( bidirectionalInfo, - numberOfCharacters, - 0u, - numberOfCharacters, - directions ); + GetCharactersDirection(bidirectionalInfo, + numberOfCharacters, + 0u, + numberOfCharacters, + directions); // This paragraph has right to left text. Some characters may need to be mirrored. // TODO: consider if the mirrored string can be stored as well. - internalDataModel.isTextMirrored = GetMirroredText( utf32Characters, - directions, - bidirectionalInfo, - 0u, - numberOfCharacters, - mirroredUtf32Characters ); + internalDataModel.isTextMirrored = GetMirroredText(utf32Characters, + directions, + bidirectionalInfo, + 0u, + numberOfCharacters, + mirroredUtf32Characters); } } -void ShapeText( TextAbstraction::TextRenderer::Parameters& rendererParameters, Vector& embeddedItemLayout, InternalDataModel& internalDataModel ) +void ShapeText(TextAbstraction::TextRenderer::Parameters& rendererParameters, Vector& embeddedItemLayout, InternalDataModel& internalDataModel) { - Vector newParagraphGlyphs; // Glyphs for the new paragraph characters. - const Length numberOfCharacters = internalDataModel.numberOfCharacters; - const bool isTextMirrored = internalDataModel.isTextMirrored; - Text::ModelPtr& textModel = internalDataModel.textModel; - const Vector& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters; - FontClient& fontClient = internalDataModel.fontClient; - const Vector& utf32Characters = textModel->mLogicalModel->mText; // Characters encoded in utf32. - const Vector& lineBreakInfo = textModel->mLogicalModel->mLineBreakInfo; // The line break info. - const Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. - const Vector& validFonts = textModel->mLogicalModel->mFontRuns; // Validated fonts. - - Vector& glyphsToCharacters = textModel->mVisualModel->mGlyphsToCharacters; // Glyphs to character map. - Vector& charactersPerGlyph = textModel->mVisualModel->mCharactersPerGlyph; // Number of characters per glyph. + Vector newParagraphGlyphs; // Glyphs for the new paragraph characters. + const Length numberOfCharacters = internalDataModel.numberOfCharacters; + const bool isTextMirrored = internalDataModel.isTextMirrored; + Text::ModelPtr& textModel = internalDataModel.textModel; + const Vector& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters; + FontClient& fontClient = internalDataModel.fontClient; + const Vector& utf32Characters = textModel->mLogicalModel->mText; // Characters encoded in utf32. + const Vector& lineBreakInfo = textModel->mLogicalModel->mLineBreakInfo; // The line break info. + const Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. + const Vector& validFonts = textModel->mLogicalModel->mFontRuns; // Validated fonts. + + Vector& glyphsToCharacters = textModel->mVisualModel->mGlyphsToCharacters; // Glyphs to character map. + Vector& charactersPerGlyph = textModel->mVisualModel->mCharactersPerGlyph; // Number of characters per glyph. //////////////////////////////////////////////////////////////////////////////// // Retrieve the glyphs. Text shaping @@ -351,106 +346,104 @@ void ShapeText( TextAbstraction::TextRenderer::Parameters& rendererParameters, V const Vector& textToShape = isTextMirrored ? mirroredUtf32Characters : utf32Characters; - newParagraphGlyphs.Reserve( 1u ); + newParagraphGlyphs.Reserve(1u); // Shapes the text. - ShapeText( textToShape, - lineBreakInfo, - scripts, - validFonts, - 0u, - 0u, - numberOfCharacters, - rendererParameters.glyphs, - glyphsToCharacters, - charactersPerGlyph, - newParagraphGlyphs ); + ShapeText(textToShape, + lineBreakInfo, + scripts, + validFonts, + 0u, + 0u, + numberOfCharacters, + rendererParameters.glyphs, + glyphsToCharacters, + charactersPerGlyph, + newParagraphGlyphs); // Create the 'number of glyphs' per character and the glyph to character conversion tables. - textModel->mVisualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters ); - textModel->mVisualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters ); + textModel->mVisualModel->CreateGlyphsPerCharacterTable(0u, 0u, numberOfCharacters); + textModel->mVisualModel->CreateCharacterToGlyphTable(0u, 0u, numberOfCharacters); internalDataModel.numberOfGlyphs = rendererParameters.glyphs.Count(); // Once the text has been shaped and the glyphs created it's possible to replace the font id of those glyphs // that represent an image or an item and create the embedded item layout info. // Note: the position of the embedded item can't be set until the text is laid-out. - embeddedItemLayout.Reserve( textModel->mLogicalModel->mEmbeddedItems.Count() ); - for( const auto& item : textModel->mLogicalModel->mEmbeddedItems ) + embeddedItemLayout.Reserve(textModel->mLogicalModel->mEmbeddedItems.Count()); + for(const auto& item : textModel->mLogicalModel->mEmbeddedItems) { // Get the glyph that matches with the character index. const GlyphIndex glyphIndex = textModel->mVisualModel->mCharactersToGlyph[item.characterIndex]; - GlyphInfo& glyph = rendererParameters.glyphs[glyphIndex]; + GlyphInfo& glyph = rendererParameters.glyphs[glyphIndex]; - glyph.fontId = 0u; - Pixel::Format pixelFormat = Pixel::A8; - TextAbstraction::FontClient::EmbeddedItemDescription description = { std::string( item.url, item.urlLength ), item.width, item.height, item.colorBlendingMode }; - glyph.index = fontClient.CreateEmbeddedItem( description, pixelFormat ); // Set here an index to an item. + glyph.fontId = 0u; + Pixel::Format pixelFormat = Pixel::A8; + TextAbstraction::FontClient::EmbeddedItemDescription description = {std::string(item.url, item.urlLength), item.width, item.height, item.colorBlendingMode}; + glyph.index = fontClient.CreateEmbeddedItem(description, pixelFormat); // Set here an index to an item. - if( ( Pixel::RGBA8888 == pixelFormat ) || ( Pixel::BGRA8888 == pixelFormat ) ) + if((Pixel::RGBA8888 == pixelFormat) || (Pixel::BGRA8888 == pixelFormat)) { rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888; } // If the url is empty the item is going to be added after the text is rendered. It's needed to store the layout here. - if( description.url.empty() ) + if(description.url.empty()) { EmbeddedItemInfo embeddedInfo = - { - item.characterIndex, - glyphIndex, - Vector2::ZERO, - Size( static_cast( item.width ), static_cast( item.height ) ), - Size( static_cast( item.width ), static_cast( item.height ) ), - Degree( 0.f ), - item.colorBlendingMode - }; - - embeddedItemLayout.PushBack( embeddedInfo ); + { + item.characterIndex, + glyphIndex, + Vector2::ZERO, + Size(static_cast(item.width), static_cast(item.height)), + Size(static_cast(item.width), static_cast(item.height)), + Degree(0.f), + item.colorBlendingMode}; + + embeddedItemLayout.PushBack(embeddedInfo); } } } -void SetColorSegmentation( const RendererParameters& textParameters, InternalDataModel& internalDataModel ) +void SetColorSegmentation(const RendererParameters& textParameters, InternalDataModel& internalDataModel) { - - Text::ModelPtr& textModel = internalDataModel.textModel; + Text::ModelPtr& textModel = internalDataModel.textModel; Vector& blendingMode = internalDataModel.blendingMode; - Vector& colorRuns = textModel->mLogicalModel->mColorRuns; // colors of the text. + Vector& colorRuns = textModel->mLogicalModel->mColorRuns; // colors of the text. - Vector& charactersToGlyph = textModel->mVisualModel->mCharactersToGlyph; // Characters to glyphs map. - Vector& glyphsPerCharacter = textModel->mVisualModel->mGlyphsPerCharacter; // The number of glyphs that are shaped. + Vector& charactersToGlyph = textModel->mVisualModel->mCharactersToGlyph; // Characters to glyphs map. + Vector& glyphsPerCharacter = textModel->mVisualModel->mGlyphsPerCharacter; // The number of glyphs that are shaped. //////////////////////////////////////////////////////////////////////////////// // Set the color runs in glyphs. //////////////////////////////////////////////////////////////////////////////// - SetColorSegmentationInfo( colorRuns, - charactersToGlyph, - glyphsPerCharacter, - 0u, - 0u, - internalDataModel.numberOfCharacters, - textModel->mVisualModel->mColors, - textModel->mVisualModel->mColorIndices ); + SetColorSegmentationInfo(colorRuns, + charactersToGlyph, + glyphsPerCharacter, + 0u, + 0u, + internalDataModel.numberOfCharacters, + textModel->mVisualModel->mColors, + textModel->mVisualModel->mColorIndices); // Insert the default color at the beginning of the vector. - textModel->mVisualModel->mColors.Insert( textModel->mVisualModel->mColors.Begin(),textParameters.textColor ); + textModel->mVisualModel->mColors.Insert(textModel->mVisualModel->mColors.Begin(), textParameters.textColor); // Set how the embedded items are blended with text color. - blendingMode.Resize( internalDataModel.numberOfGlyphs, textParameters.isTextColorSet ? ColorBlendingMode::MULTIPLY : ColorBlendingMode::NONE ); + blendingMode.Resize(internalDataModel.numberOfGlyphs, textParameters.isTextColorSet ? ColorBlendingMode::MULTIPLY : ColorBlendingMode::NONE); - if( !textParameters.isTextColorSet ) + if(!textParameters.isTextColorSet) { // Traverse the color runs. - for( const auto& run : colorRuns ) + for(const auto& run : colorRuns) { - const GlyphIndex firstGlyph = textModel->mVisualModel->mCharactersToGlyph[run.characterRun.characterIndex]; - const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u; - const GlyphIndex lastGlyphPlusOne = textModel->mVisualModel->mCharactersToGlyph[lastCharacter] + textModel->mVisualModel->mGlyphsPerCharacter[lastCharacter]; + const GlyphIndex firstGlyph = textModel->mVisualModel->mCharactersToGlyph[run.characterRun.characterIndex]; + const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u; + const GlyphIndex lastGlyphPlusOne = textModel->mVisualModel->mCharactersToGlyph[lastCharacter] + textModel->mVisualModel->mGlyphsPerCharacter[lastCharacter]; - for( GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index ) + for(GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index) { blendingMode[index] = ColorBlendingMode::MULTIPLY; } @@ -458,35 +451,35 @@ void SetColorSegmentation( const RendererParameters& textParameters, InternalDat } // Traverse the embedded items and update the blending mode vector. - for( const auto& item : textModel->mLogicalModel->mEmbeddedItems ) + for(const auto& item : textModel->mLogicalModel->mEmbeddedItems) { const GlyphIndex glyphIndex = textModel->mVisualModel->mCharactersToGlyph[item.characterIndex]; - blendingMode[glyphIndex] = item.colorBlendingMode; + blendingMode[glyphIndex] = item.colorBlendingMode; } } -void SetEmojiVector( InternalDataModel& internalDataModel ) +void SetEmojiVector(InternalDataModel& internalDataModel) { - Vector& isEmoji = internalDataModel.isEmoji; - Text::ModelPtr& textModel = internalDataModel.textModel; - const Length numberOfGlyphs = internalDataModel.numberOfGlyphs; + Vector& isEmoji = internalDataModel.isEmoji; + Text::ModelPtr& textModel = internalDataModel.textModel; + const Length numberOfGlyphs = internalDataModel.numberOfGlyphs; - const Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. + const Vector& scripts = textModel->mLogicalModel->mScriptRuns; // Charactes's script. //////////////////////////////////////////////////////////////////////////////// // Set the isEmoji Vector //////////////////////////////////////////////////////////////////////////////// - isEmoji.Resize( numberOfGlyphs, false ); + isEmoji.Resize(numberOfGlyphs, false); - for( const auto& run : scripts ) + for(const auto& run : scripts) { - if( run.script == TextAbstraction::Script::EMOJI ) + if(run.script == TextAbstraction::Script::EMOJI) { - const GlyphIndex firstGlyph = textModel->mVisualModel->mCharactersToGlyph[run.characterRun.characterIndex]; - const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u; - const GlyphIndex lastGlyphPlusOne = textModel->mVisualModel->mCharactersToGlyph[lastCharacter] + textModel->mVisualModel->mGlyphsPerCharacter[lastCharacter]; + const GlyphIndex firstGlyph = textModel->mVisualModel->mCharactersToGlyph[run.characterRun.characterIndex]; + const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u; + const GlyphIndex lastGlyphPlusOne = textModel->mVisualModel->mCharactersToGlyph[lastCharacter] + textModel->mVisualModel->mGlyphsPerCharacter[lastCharacter]; - for( GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index ) + for(GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index) { isEmoji[index] = true; } @@ -494,51 +487,48 @@ void SetEmojiVector( InternalDataModel& internalDataModel ) } } - -void Align( const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, - Vector& embeddedItemLayout, InternalDataModel& internalDataModel, - const Size& newLayoutSize ) +void Align(const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, Vector& embeddedItemLayout, InternalDataModel& internalDataModel, const Size& newLayoutSize) { - Text::Layout::Engine& layoutEngine = internalDataModel.layoutEngine; - Text::ModelPtr& textModel = internalDataModel.textModel; - const Length numberOfCharacters = internalDataModel.numberOfCharacters; - Size& textLayoutArea = internalDataModel.textLayoutArea; + Text::Layout::Engine& layoutEngine = internalDataModel.layoutEngine; + Text::ModelPtr& textModel = internalDataModel.textModel; + const Length numberOfCharacters = internalDataModel.numberOfCharacters; + Size& textLayoutArea = internalDataModel.textLayoutArea; - Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. + Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. //////////////////////////////////////////////////////////////////////////////// // Align the text. //////////////////////////////////////////////////////////////////////////////// - HorizontalAlignment::Type horizontalAlignment = Toolkit::HorizontalAlignment::CENTER; + HorizontalAlignment::Type horizontalAlignment = Toolkit::HorizontalAlignment::CENTER; HorizontalAlignment::Type horizontalCircularAlignment = Toolkit::HorizontalAlignment::CENTER; - VerticalAlignment::Type verticalAlignment = VerticalAlignment::CENTER; - CircularAlignment::Type circularAlignment = CircularAlignment::BEGIN; + VerticalAlignment::Type verticalAlignment = VerticalAlignment::CENTER; + CircularAlignment::Type circularAlignment = CircularAlignment::BEGIN; Layout::Type layout = Layout::SINGLELINE; // Sets the alignment - Property::Value horizontalAlignmentStr( textParameters.horizontalAlignment ); - GetHorizontalAlignmentEnumeration( horizontalAlignmentStr, horizontalAlignment ); + Property::Value horizontalAlignmentStr(textParameters.horizontalAlignment); + GetHorizontalAlignmentEnumeration(horizontalAlignmentStr, horizontalAlignment); horizontalCircularAlignment = horizontalAlignment; - Property::Value verticalAlignmentStr( textParameters.verticalAlignment ); - GetVerticalAlignmentEnumeration( verticalAlignmentStr, verticalAlignment ); + Property::Value verticalAlignmentStr(textParameters.verticalAlignment); + GetVerticalAlignmentEnumeration(verticalAlignmentStr, verticalAlignment); - Property::Value circularAlignmentStr( textParameters.circularAlignment ); - GetCircularAlignmentEnumeration( circularAlignmentStr, circularAlignment ); + Property::Value circularAlignmentStr(textParameters.circularAlignment); + GetCircularAlignmentEnumeration(circularAlignmentStr, circularAlignment); - Property::Value layoutStr( textParameters.layout ); - GetLayoutEnumeration( layoutStr, layout ); + Property::Value layoutStr(textParameters.layout); + GetLayoutEnumeration(layoutStr, layout); // Whether the layout is circular. const bool isCircularTextLayout = (Layout::CIRCULAR == layout); - const bool isClockwise = isCircularTextLayout && ( 0.f < textParameters.incrementAngle ); + const bool isClockwise = isCircularTextLayout && (0.f < textParameters.incrementAngle); // Convert CircularAlignment to HorizontalAlignment. - if( isCircularTextLayout ) + if(isCircularTextLayout) { - switch( circularAlignment ) + switch(circularAlignment) { case CircularAlignment::BEGIN: { @@ -562,7 +552,7 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende // Retrieve the line of text to know the direction and the width. @todo multi-line const LineRun& line = lines[0u]; - if( isCircularTextLayout ) + if(isCircularTextLayout) { // Set the circular alignment. rendererParameters.circularLayout = isClockwise ? TextRenderer::Parameters::CLOCKWISE : TextRenderer::Parameters::COUNTER_CLOCKWISE; @@ -571,11 +561,11 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende textLayoutArea.height = newLayoutSize.height; // Set the size of the text laid out on a straight horizontal line. - rendererParameters.circularWidth = static_cast( newLayoutSize.width ); - rendererParameters.circularHeight = static_cast( newLayoutSize.height ); + rendererParameters.circularWidth = static_cast(newLayoutSize.width); + rendererParameters.circularHeight = static_cast(newLayoutSize.height); // Calculate the center of the circular text according the horizontal and vertical alingments and the radius. - switch( horizontalAlignment ) + switch(horizontalAlignment) { case HorizontalAlignment::BEGIN: { @@ -584,17 +574,17 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende } case HorizontalAlignment::CENTER: { - rendererParameters.centerX = static_cast( textParameters.textWidth / 2u ); + rendererParameters.centerX = static_cast(textParameters.textWidth / 2u); break; } case HorizontalAlignment::END: { - rendererParameters.centerX = static_cast( textParameters.textWidth ) - static_cast(textParameters.radius); + rendererParameters.centerX = static_cast(textParameters.textWidth) - static_cast(textParameters.radius); break; } } - switch( verticalAlignment ) + switch(verticalAlignment) { case VerticalAlignment::TOP: { @@ -603,12 +593,12 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende } case VerticalAlignment::CENTER: { - rendererParameters.centerY = static_cast( textParameters.textHeight / 2u ); + rendererParameters.centerY = static_cast(textParameters.textHeight / 2u); break; } case VerticalAlignment::BOTTOM: { - rendererParameters.centerY = static_cast( textParameters.textHeight ) - static_cast(textParameters.radius); + rendererParameters.centerY = static_cast(textParameters.textHeight) - static_cast(textParameters.radius); break; } } @@ -617,10 +607,10 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende const bool isRTL = RTL == line.direction; CircularAlignment::Type alignment = circularAlignment; - if( isRTL ) + if(isRTL) { // Swap the alignment type if the line is right to left. - switch( alignment ) + switch(alignment) { case CircularAlignment::BEGIN: { @@ -642,7 +632,7 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende float angleOffset = 0.f; - switch( alignment ) + switch(alignment) { case CircularAlignment::BEGIN: { @@ -651,25 +641,25 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende } case CircularAlignment::CENTER: { - const bool isNeg = textParameters.incrementAngle < 0.f; - const float textWidth = static_cast( rendererParameters.circularWidth ); - angleOffset = ( isNeg ? -0.5f : 0.5f ) * ( textLayoutArea.width - textWidth ) / static_cast( rendererParameters.radius ); + const bool isNeg = textParameters.incrementAngle < 0.f; + const float textWidth = static_cast(rendererParameters.circularWidth); + angleOffset = (isNeg ? -0.5f : 0.5f) * (textLayoutArea.width - textWidth) / static_cast(rendererParameters.radius); break; } case CircularAlignment::END: { - const bool isNeg = textParameters.incrementAngle < 0.f; - const float textWidth = static_cast( rendererParameters.circularWidth ); - angleOffset = ( isNeg ? -1.f : 1.f ) * ( textLayoutArea.width - textWidth ) / static_cast( rendererParameters.radius ); + const bool isNeg = textParameters.incrementAngle < 0.f; + const float textWidth = static_cast(rendererParameters.circularWidth); + angleOffset = (isNeg ? -1.f : 1.f) * (textLayoutArea.width - textWidth) / static_cast(rendererParameters.radius); break; } } // Update the beginning angle with the calculated offset. - rendererParameters.beginAngle = Radian( Degree( textParameters.beginAngle ) ) + angleOffset; + rendererParameters.beginAngle = Radian(Degree(textParameters.beginAngle)) + angleOffset; // Set the vertical position of the glyphs. - for( auto& position : rendererParameters.positions ) + for(auto& position : rendererParameters.positions) { position.y = 0.f; } @@ -679,7 +669,7 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende // Calculate the vertical offset according with the given alignment. float penY = 0.f; - switch( verticalAlignment ) + switch(verticalAlignment) { case VerticalAlignment::TOP: { @@ -688,7 +678,7 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende } case VerticalAlignment::CENTER: { - penY = line.ascender + 0.5f * ( textLayoutArea.height - ( line.ascender - line.descender ) ); + penY = line.ascender + 0.5f * (textLayoutArea.height - (line.ascender - line.descender)); break; } case VerticalAlignment::BOTTOM: @@ -700,17 +690,17 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende // Calculate the horizontal offset according with the given alignment. float alignmentOffset = 0.f; - layoutEngine.Align( textLayoutArea, - 0u, - numberOfCharacters, - horizontalAlignment, - lines, - alignmentOffset, - Dali::LayoutDirection::LEFT_TO_RIGHT, - false ); + layoutEngine.Align(textLayoutArea, + 0u, + numberOfCharacters, + horizontalAlignment, + lines, + alignmentOffset, + Dali::LayoutDirection::LEFT_TO_RIGHT, + false); // Update the position of the glyphs with the calculated offsets. - for( auto& position : rendererParameters.positions ) + for(auto& position : rendererParameters.positions) { position.x += line.alignmentOffset; position.y = penY; @@ -720,10 +710,10 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende // Cairo adds the bearing to the position of the glyph // that has already been added by the DALi's layout engine, // so it's needed to be removed here. - for( unsigned int index = 0u; index < rendererParameters.glyphs.Count(); ++index ) + for(unsigned int index = 0u; index < rendererParameters.glyphs.Count(); ++index) { - const GlyphInfo& glyph = rendererParameters.glyphs[index]; - Vector2& position = rendererParameters.positions[index]; + const GlyphInfo& glyph = rendererParameters.glyphs[index]; + Vector2& position = rendererParameters.positions[index]; position.x -= glyph.xBearing; } @@ -731,113 +721,111 @@ void Align( const RendererParameters& textParameters, TextAbstraction::TextRende // Set the position of the embedded items (if there is any). EmbeddedItemInfo* embeddedItemLayoutBuffer = embeddedItemLayout.Begin(); - for( Length index = 0u, endIndex = embeddedItemLayout.Count(); index < endIndex; ++index ) + for(Length index = 0u, endIndex = embeddedItemLayout.Count(); index < endIndex; ++index) { - EmbeddedItemInfo& embeddedItem = *( embeddedItemLayoutBuffer + index ); + EmbeddedItemInfo& embeddedItem = *(embeddedItemLayoutBuffer + index); embeddedItem.position = rendererParameters.positions[embeddedItem.glyphIndex]; - if( isCircularTextLayout ) + if(isCircularTextLayout) { // Calculate the new position of the embedded item in the circular path. // Center of the bitmap. - const float halfWidth = 0.5f * embeddedItem.size.width; + const float halfWidth = 0.5f * embeddedItem.size.width; const float halfHeight = 0.5f * embeddedItem.size.height; - double centerX = static_cast( embeddedItem.position.x + halfWidth ); - double centerY = static_cast(embeddedItem.position.y - halfHeight); + double centerX = static_cast(embeddedItem.position.x + halfWidth); + double centerY = static_cast(embeddedItem.position.y - halfHeight); Dali::TextAbstraction::CircularTextParameters circularTextParameters; - circularTextParameters.radius = static_cast( rendererParameters.radius ); - circularTextParameters.invRadius = 1.0 / circularTextParameters.radius; - circularTextParameters.beginAngle = static_cast( -rendererParameters.beginAngle + Dali::Math::PI_2 ); - circularTextParameters.centerX = 0.5f * static_cast( textParameters.textWidth ); - circularTextParameters.centerY = 0.5f * static_cast( textParameters.textHeight ); + circularTextParameters.radius = static_cast(rendererParameters.radius); + circularTextParameters.invRadius = 1.0 / circularTextParameters.radius; + circularTextParameters.beginAngle = static_cast(-rendererParameters.beginAngle + Dali::Math::PI_2); + circularTextParameters.centerX = 0.5f * static_cast(textParameters.textWidth); + circularTextParameters.centerY = 0.5f * static_cast(textParameters.textHeight); // Calculate the rotation angle. float radians = rendererParameters.beginAngle; - if( isClockwise ) + if(isClockwise) { - radians += static_cast( circularTextParameters.invRadius * centerX ); + radians += static_cast(circularTextParameters.invRadius * centerX); radians = -radians; } else { - radians -= static_cast( circularTextParameters.invRadius * centerX ); + radians -= static_cast(circularTextParameters.invRadius * centerX); radians = -radians + Dali::Math::PI; } - embeddedItem.angle = Degree( Radian( radians ) ); + embeddedItem.angle = Degree(Radian(radians)); - Dali::TextAbstraction::TransformToArc( circularTextParameters, centerX, centerY ); + Dali::TextAbstraction::TransformToArc(circularTextParameters, centerX, centerY); // Recalculate the size of the embedded item after the rotation to position it correctly. - float width = embeddedItem.size.width; + float width = embeddedItem.size.width; float height = embeddedItem.size.height; // Transform the input angle into the range [0..2PI] - radians = fmod( radians, TWO_PI ); - radians += ( radians < 0.f ) ? TWO_PI : 0.f; + radians = fmod(radians, TWO_PI); + radians += (radians < 0.f) ? TWO_PI : 0.f; // Does the same operations than rotate by shear. - if( ( radians > Math::PI_4 ) && ( radians <= RAD_135 ) ) + if((radians > Math::PI_4) && (radians <= RAD_135)) { - std::swap( width, height ); + std::swap(width, height); radians -= Math::PI_2; } - else if( ( radians > RAD_135 ) && ( radians <= RAD_225 ) ) + else if((radians > RAD_135) && (radians <= RAD_225)) { radians -= Math::PI; } - else if( ( radians > RAD_225 ) && ( radians <= RAD_315 ) ) + else if((radians > RAD_225) && (radians <= RAD_315)) { - std::swap( width, height ); + std::swap(width, height); radians -= RAD_270; } - if( fabs( radians ) > Dali::Math::MACHINE_EPSILON_10 ) + if(fabs(radians) > Dali::Math::MACHINE_EPSILON_10) { - const float angleSinus = fabs( sin( radians ) ); - const float angleCosinus = cos( radians ); + const float angleSinus = fabs(sin(radians)); + const float angleCosinus = cos(radians); // Calculate the rotated image dimensions. embeddedItem.rotatedSize.height = width * angleSinus + height * angleCosinus; - embeddedItem.rotatedSize.width = height * angleSinus + width * angleCosinus + 1.f; + embeddedItem.rotatedSize.width = height * angleSinus + width * angleCosinus + 1.f; } - embeddedItem.position.x = floor( static_cast( centerX ) - 0.5f * embeddedItem.rotatedSize.width ); - embeddedItem.position.y = floor( static_cast( centerY ) - 0.5f * embeddedItem.rotatedSize.height ); + embeddedItem.position.x = floor(static_cast(centerX) - 0.5f * embeddedItem.rotatedSize.width); + embeddedItem.position.y = floor(static_cast(centerY) - 0.5f * embeddedItem.rotatedSize.height); } else { embeddedItem.position.y -= embeddedItem.size.height; } } - } -void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, - Vector& embeddedItemLayout, InternalDataModel& internalDataModel ) +void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, Vector& embeddedItemLayout, InternalDataModel& internalDataModel) { - Text::ModelPtr& textModel = internalDataModel.textModel; - FontClient& fontClient = internalDataModel.fontClient; + Text::ModelPtr& textModel = internalDataModel.textModel; + FontClient& fontClient = internalDataModel.fontClient; - Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. - Vector& isEmoji = internalDataModel.isEmoji; - const Size textLayoutArea = internalDataModel.textLayoutArea; + Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. + Vector& isEmoji = internalDataModel.isEmoji; + const Size textLayoutArea = internalDataModel.textLayoutArea; //////////////////////////////////////////////////////////////////////////////// // Ellipsis the text. //////////////////////////////////////////////////////////////////////////////// - if( textParameters.ellipsisEnabled ) + if(textParameters.ellipsisEnabled) { const LineRun& line = lines[0u]; // TODO: multi-line - if( line.ellipsis ) + if(line.ellipsis) { Length finalNumberOfGlyphs = 0u; - if( ( line.ascender - line.descender ) > textLayoutArea.height ) + if((line.ascender - line.descender) > textLayoutArea.height) { // The height of the line is bigger than the height of the text area. // Show the ellipsis glyph even if it doesn't fit in the text area. @@ -845,13 +833,13 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR // until is find out that the text area is too small. // Get the first glyph which is going to be replaced and the ellipsis glyph. - GlyphInfo& glyphInfo = rendererParameters.glyphs[0u]; - const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph( fontClient.GetPointSize( glyphInfo.fontId ) ); + GlyphInfo& glyphInfo = rendererParameters.glyphs[0u]; + const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphInfo.fontId)); // Change the 'x' and 'y' position of the ellipsis glyph. Vector2& position = rendererParameters.positions[0u]; - position.x = ellipsisGlyph.xBearing; - position.y = textLayoutArea.height - ellipsisGlyph.yBearing; + position.x = ellipsisGlyph.xBearing; + position.y = textLayoutArea.height - ellipsisGlyph.yBearing; // Replace the glyph by the ellipsis glyph. glyphInfo = ellipsisGlyph; @@ -861,46 +849,45 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR } else { - // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed. - float firstPenX = 0.f; // Used if rtl text is elided. - bool firstPenSet = false; + float firstPenX = 0.f; // Used if rtl text is elided. + bool firstPenSet = false; // Add the ellipsis glyph. - bool inserted = false; - float removedGlypsWidth = 0.f; + bool inserted = false; + float removedGlypsWidth = 0.f; Length numberOfRemovedGlyphs = 0u; - if (line.glyphRun.numberOfGlyphs > 0u) + if(line.glyphRun.numberOfGlyphs > 0u) { GlyphIndex index = line.glyphRun.numberOfGlyphs - 1u; - GlyphInfo* glyphs = rendererParameters.glyphs.Begin(); - Vector2* glyphPositions = rendererParameters.positions.Begin(); + GlyphInfo* glyphs = rendererParameters.glyphs.Begin(); + Vector2* glyphPositions = rendererParameters.positions.Begin(); float penY = 0.f; // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed. - while( !inserted ) + while(!inserted) { - const GlyphInfo& glyphToRemove = *( glyphs + index ); + const GlyphInfo& glyphToRemove = *(glyphs + index); - if( 0u != glyphToRemove.fontId ) + if(0u != glyphToRemove.fontId) { // i.e. The font id of the glyph shaped from the '\n' character is zero. // Need to reshape the glyph as the font may be different in size. - const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph( fontClient.GetPointSize( glyphToRemove.fontId ) ); + const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId)); - if( !firstPenSet ) + if(!firstPenSet) { - const Vector2& position = *( glyphPositions + index ); + const Vector2& position = *(glyphPositions + index); // Calculates the penY of the current line. It will be used to position the ellipsis glyph. penY = position.y; // Calculates the first penX which will be used if rtl text is elided. firstPenX = position.x - glyphToRemove.xBearing; - if( firstPenX < -ellipsisGlyph.xBearing ) + if(firstPenX < -ellipsisGlyph.xBearing) { // Avoids to exceed the bounding box when rtl text is elided. firstPenX = -ellipsisGlyph.xBearing; @@ -911,15 +898,15 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR firstPenSet = true; } - removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) ); + removedGlypsWidth += std::min(glyphToRemove.advance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing; - if( ellipsisGlyphWidth < removedGlypsWidth ) + if(ellipsisGlyphWidth < removedGlypsWidth) { - GlyphInfo& glyphInfo = *( glyphs + index ); - Vector2& position = *( glyphPositions + index ); - position.x -= ( 0.f > glyphInfo.xBearing ) ? glyphInfo.xBearing : 0.f; + GlyphInfo& glyphInfo = *(glyphs + index); + Vector2& position = *(glyphPositions + index); + position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f; // Replace the glyph by the ellipsis glyph. glyphInfo = ellipsisGlyph; @@ -929,7 +916,7 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR // Change the 'x' and 'y' position of the ellipsis glyph. - if( position.x > firstPenX ) + if(position.x > firstPenX) { position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth; } @@ -941,9 +928,9 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR } } - if( !inserted ) + if(!inserted) { - if( index > 0u ) + if(index > 0u) { --index; } @@ -961,139 +948,138 @@ void Ellipsis( const RendererParameters& textParameters, TextAbstraction::TextR } // Resize the number of glyphs/positions - rendererParameters.glyphs.Resize( finalNumberOfGlyphs ); - rendererParameters.positions.Resize( finalNumberOfGlyphs ); + rendererParameters.glyphs.Resize(finalNumberOfGlyphs); + rendererParameters.positions.Resize(finalNumberOfGlyphs); // Remove from the embedded items those exceding the last laid out glyph. - embeddedItemLayout.Erase( std::remove_if( embeddedItemLayout.Begin(), - embeddedItemLayout.End(), - [finalNumberOfGlyphs]( const EmbeddedItemInfo& item ) - { - return item.glyphIndex >= finalNumberOfGlyphs; - } ), - embeddedItemLayout.End() ); + embeddedItemLayout.Erase(std::remove_if(embeddedItemLayout.Begin(), + embeddedItemLayout.End(), + [finalNumberOfGlyphs](const EmbeddedItemInfo& item) { + return item.glyphIndex >= finalNumberOfGlyphs; + }), + embeddedItemLayout.End()); } } } } -Size LayoutText( const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, - Vector& embeddedItemLayout, InternalDataModel& internalDataModel ) +Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters, Vector& embeddedItemLayout, InternalDataModel& internalDataModel) { //////////////////////////////////////////////////////////////////////////////// // Layout the text. //////////////////////////////////////////////////////////////////////////////// - Text::ModelPtr& textModel = internalDataModel.textModel; - Text::Layout::Engine& layoutEngine = internalDataModel.layoutEngine; - FontClient& fontClient = internalDataModel.fontClient; - const Length numberOfGlyphs = internalDataModel.numberOfGlyphs; - const bool isTextMirrored = internalDataModel.isTextMirrored; + Text::ModelPtr& textModel = internalDataModel.textModel; + Text::Layout::Engine& layoutEngine = internalDataModel.layoutEngine; + FontClient& fontClient = internalDataModel.fontClient; + const Length numberOfGlyphs = internalDataModel.numberOfGlyphs; + const bool isTextMirrored = internalDataModel.isTextMirrored; const Vector& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters; - const Length numberOfCharacters = internalDataModel.numberOfCharacters; + const Length numberOfCharacters = internalDataModel.numberOfCharacters; Layout::Type layout = Layout::SINGLELINE; - Property::Value layoutStr( textParameters.layout ); - GetLayoutEnumeration( layoutStr, layout ); + Property::Value layoutStr(textParameters.layout); + GetLayoutEnumeration(layoutStr, layout); // Whether the layout is multi-line. - const Text::Layout::Engine::Type horizontalLayout = ( Layout::MULTILINE == layout ) ? Text::Layout::Engine::MULTI_LINE_BOX : Text::Layout::Engine::SINGLE_LINE_BOX; - layoutEngine.SetLayout( horizontalLayout ); // TODO: multi-line. + const Text::Layout::Engine::Type horizontalLayout = (Layout::MULTILINE == layout) ? Text::Layout::Engine::MULTI_LINE_BOX : Text::Layout::Engine::SINGLE_LINE_BOX; + layoutEngine.SetLayout(horizontalLayout); // TODO: multi-line. // Set minimun line size - layoutEngine.SetDefaultLineSize( textParameters.minLineSize ); + layoutEngine.SetDefaultLineSize(textParameters.minLineSize); // Whether the layout is circular. const bool isCircularTextLayout = (Layout::CIRCULAR == layout); - const bool isClockwise = isCircularTextLayout && ( 0.f < textParameters.incrementAngle ); + const bool isClockwise = isCircularTextLayout && (0.f < textParameters.incrementAngle); // Calculates the max ascender or the max descender. // Is used to calculate the radius of the base line of the text. float maxAscenderDescender = 0.f; - if( isCircularTextLayout ) + if(isCircularTextLayout) { FontId currentFontId = 0u; - for( const auto& glyph : rendererParameters.glyphs ) + for(const auto& glyph : rendererParameters.glyphs) { - if( currentFontId != glyph.fontId ) + if(currentFontId != glyph.fontId) { currentFontId = glyph.fontId; FontMetrics metrics; fontClient.GetFontMetrics(currentFontId, metrics); - maxAscenderDescender = std::max( maxAscenderDescender, isClockwise ? metrics.ascender : metrics.descender ); + maxAscenderDescender = std::max(maxAscenderDescender, isClockwise ? metrics.ascender : metrics.descender); } } } - const unsigned int radius = textParameters.radius - static_cast( maxAscenderDescender ); + const unsigned int radius = textParameters.radius - static_cast(maxAscenderDescender); // Set the layout parameters. - internalDataModel.textLayoutArea = Size( static_cast( textParameters.textWidth ), - static_cast( textParameters.textHeight ) ); + Size textLayoutArea = Size(static_cast(textParameters.textWidth), + static_cast(textParameters.textHeight)); - if( isCircularTextLayout ) + // padding + Extents padding = textParameters.padding; + internalDataModel.textLayoutArea = Size(textLayoutArea.x - ( padding.start + padding.end ), textLayoutArea.y - ( padding.top + padding.bottom ) ); + + + if(isCircularTextLayout) { // In a circular layout, the length of the text area depends on the radius. - rendererParameters.radius = radius; - internalDataModel.textLayoutArea.width = fabs( Radian( Degree( textParameters.incrementAngle ) ) * static_cast( rendererParameters.radius ) ); + rendererParameters.radius = radius; + internalDataModel.textLayoutArea.width = fabs(Radian(Degree(textParameters.incrementAngle)) * static_cast(rendererParameters.radius)); } // Resize the vector of positions to have the same size than the vector of glyphs. - rendererParameters.positions.Resize( numberOfGlyphs ); + rendererParameters.positions.Resize(numberOfGlyphs); - textModel->mLineWrapMode = LineWrap::WORD; - textModel->mIgnoreSpacesAfterText = false; + textModel->mLineWrapMode = LineWrap::WORD; + textModel->mIgnoreSpacesAfterText = false; textModel->mMatchSystemLanguageDirection = false; - Text::Layout::Parameters layoutParameters( internalDataModel.textLayoutArea, - textModel ); - + Text::Layout::Parameters layoutParameters(internalDataModel.textLayoutArea, + textModel); // Whether the last character is a new paragraph character. const Vector& textToShape = isTextMirrored ? mirroredUtf32Characters : textModel->mLogicalModel->mText; - layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( textToShape[numberOfCharacters - 1u] ); + layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph(textToShape[numberOfCharacters - 1u]); // The initial glyph and the number of glyphs to layout. - layoutParameters.startGlyphIndex = 0u; - layoutParameters.numberOfGlyphs = numberOfGlyphs; - layoutParameters.startLineIndex = 0u; + layoutParameters.startGlyphIndex = 0u; + layoutParameters.numberOfGlyphs = numberOfGlyphs; + layoutParameters.startLineIndex = 0u; layoutParameters.estimatedNumberOfLines = 1u; layoutParameters.interGlyphExtraAdvance = 0.f; // Update the visual model. Size newLayoutSize; bool isAutoScrollEnabled = false; - layoutEngine.LayoutText( layoutParameters, - newLayoutSize, - textParameters.ellipsisEnabled, - isAutoScrollEnabled ); + layoutEngine.LayoutText(layoutParameters, + newLayoutSize, + textParameters.ellipsisEnabled, + isAutoScrollEnabled); return newLayoutSize; - } - -Devel::PixelBuffer RenderText( const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters ) +Devel::PixelBuffer RenderText(const RendererParameters& textParameters, TextAbstraction::TextRenderer::Parameters& rendererParameters) { //////////////////////////////////////////////////////////////////////////////// // Render the text. //////////////////////////////////////////////////////////////////////////////// - rendererParameters.width = textParameters.textWidth; + rendererParameters.width = textParameters.textWidth; rendererParameters.height = textParameters.textHeight; TextAbstraction::TextRenderer renderer = TextAbstraction::TextRenderer::Get(); - return renderer.Render( rendererParameters ); + return renderer.Render(rendererParameters); } - -Devel::PixelBuffer Render( const RendererParameters& textParameters, Vector& embeddedItemLayout ) +Devel::PixelBuffer Render(const RendererParameters& textParameters, Vector& embeddedItemLayout) { - if( textParameters.text.empty() ) + if(textParameters.text.empty()) { - Dali::Devel::PixelBuffer pixelBuffer = Dali::Devel::PixelBuffer::New( textParameters.textWidth, - textParameters.textHeight, - Dali::Pixel::RGBA8888 ); + Dali::Devel::PixelBuffer pixelBuffer = Dali::Devel::PixelBuffer::New(textParameters.textWidth, + textParameters.textHeight, + Dali::Pixel::RGBA8888); const unsigned int bufferSize = textParameters.textWidth * textParameters.textHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888); - unsigned char* buffer = pixelBuffer.GetBuffer(); + unsigned char* buffer = pixelBuffer.GetBuffer(); memset(buffer, 0, bufferSize); return pixelBuffer; @@ -1102,89 +1088,83 @@ Devel::PixelBuffer Render( const RendererParameters& textParameters, VectormVisualModel->mGlyphs, - internalData.textModel->mVisualModel->mGlyphPositions, - internalData.textModel->mVisualModel->mColors, - internalData.textModel->mVisualModel->mColorIndices, - internalData.blendingMode, - internalData.isEmoji ); + Text::ModelPtr textModel = Text::Model::New(); + InternalDataModel internalData(fontClient, metrics, textModel); + TextAbstraction::TextRenderer::Parameters rendererParameters(internalData.textModel->mVisualModel->mGlyphs, + internalData.textModel->mVisualModel->mGlyphPositions, + internalData.textModel->mVisualModel->mColors, + internalData.textModel->mVisualModel->mColorIndices, + internalData.blendingMode, + internalData.isEmoji); - rendererParameters.width = textParameters.textWidth; - rendererParameters.height = textParameters.textHeight; + rendererParameters.width = textParameters.textWidth; + rendererParameters.height = textParameters.textHeight; rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888; // @note: At the moment all textures are generated RGBA8888 - //////////////////////////////////////////////////////////////////////////////// // Process the markup string if the mark-up processor is enabled. //////////////////////////////////////////////////////////////////////////////// - ShapeTextPreprocess( textParameters, rendererParameters, internalData ); + ShapeTextPreprocess(textParameters, rendererParameters, internalData); //////////////////////////////////////////////////////////////////////////////// // Retrieve the glyphs. Text shaping //////////////////////////////////////////////////////////////////////////////// - ShapeText( rendererParameters, embeddedItemLayout, internalData ); - + ShapeText(rendererParameters, embeddedItemLayout, internalData); //////////////////////////////////////////////////////////////////////////////// // Retrieve the glyph's metrics. //////////////////////////////////////////////////////////////////////////////// - metrics->GetGlyphMetrics( rendererParameters.glyphs.Begin(), internalData.numberOfGlyphs ); + metrics->GetGlyphMetrics(rendererParameters.glyphs.Begin(), internalData.numberOfGlyphs); //////////////////////////////////////////////////////////////////////////////// // Set the color runs in glyphs. //////////////////////////////////////////////////////////////////////////////// - SetColorSegmentation( textParameters, internalData ); - + SetColorSegmentation(textParameters, internalData); //////////////////////////////////////////////////////////////////////////////// // Set the isEmoji Vector //////////////////////////////////////////////////////////////////////////////// - SetEmojiVector( internalData ); + SetEmojiVector(internalData); //////////////////////////////////////////////////////////////////////////////// // Layout the text //////////////////////////////////////////////////////////////////////////////// - Size newLayoutSize = LayoutText( textParameters, rendererParameters, embeddedItemLayout, internalData ); + Size newLayoutSize = LayoutText(textParameters, rendererParameters, embeddedItemLayout, internalData); //////////////////////////////////////////////////////////////////////////////// // Align the text. //////////////////////////////////////////////////////////////////////////////// - Align( textParameters, rendererParameters, embeddedItemLayout, internalData, newLayoutSize ); - + Align(textParameters, rendererParameters, embeddedItemLayout, internalData, newLayoutSize); //////////////////////////////////////////////////////////////////////////////// // Ellipsis the text. //////////////////////////////////////////////////////////////////////////////// - Ellipsis( textParameters, rendererParameters, embeddedItemLayout, internalData ); + Ellipsis(textParameters, rendererParameters, embeddedItemLayout, internalData); //////////////////////////////////////////////////////////////////////////////// // Render the text. //////////////////////////////////////////////////////////////////////////////// - return RenderText( textParameters, rendererParameters ); + return RenderText(textParameters, rendererParameters); } - -Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) +Devel::PixelBuffer CreateShadow(const ShadowParameters& shadowParameters) { // The size of the pixel data. - const int width = static_cast(shadowParameters.input.GetWidth()); + const int width = static_cast(shadowParameters.input.GetWidth()); const int height = static_cast(shadowParameters.input.GetHeight()); // The shadow's offset. - const int xOffset = static_cast( shadowParameters.offset.x ); - const int yOffset = static_cast( shadowParameters.offset.y ); + const int xOffset = static_cast(shadowParameters.offset.x); + const int yOffset = static_cast(shadowParameters.offset.y); // The size in bytes of the pixel of the input's buffer. - const Pixel::Format inputFormat = shadowParameters.input.GetPixelFormat(); - const unsigned int inputPixelSize = Pixel::GetBytesPerPixel( inputFormat ); - const bool isA8 = Pixel::A8 == inputFormat; + const Pixel::Format inputFormat = shadowParameters.input.GetPixelFormat(); + const unsigned int inputPixelSize = Pixel::GetBytesPerPixel(inputFormat); + const bool isA8 = Pixel::A8 == inputFormat; // Creates the output pixel buffer. Devel::PixelBuffer outputPixelBuffer = Devel::PixelBuffer::New(width, height, Pixel::RGBA8888); @@ -1197,35 +1177,35 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) const unsigned char* const inputPixelBuffer = shadowParameters.input.GetBuffer(); float textColor[4u]; - if (isA8) + if(isA8) { memcpy(textColor, shadowParameters.textColor.AsFloat(), 4u * sizeof(float)); } const float* const shadowColor = shadowParameters.color.AsFloat(); // Traverse the input pixel buffer and write the text on the foreground and the shadow on the background. - for (int rowIndex = 0; rowIndex < height; ++rowIndex) + for(int rowIndex = 0; rowIndex < height; ++rowIndex) { // Calculates the rowIndex to the input pixel buffer for the shadow and whether it's within the boundaries. - const int yOffsetIndex = rowIndex - yOffset; + const int yOffsetIndex = rowIndex - yOffset; const bool isValidRowIndex = ((yOffsetIndex >= 0) && (yOffsetIndex < height)); - const int rows = rowIndex * width; + const int rows = rowIndex * width; const int offsetRows = yOffsetIndex * width; - for (int columnIndex = 0; columnIndex < width; ++columnIndex) + for(int columnIndex = 0; columnIndex < width; ++columnIndex) { // Index to the input buffer to retrieve the alpha value of the foreground text. const unsigned int index = inputPixelSize * static_cast(rows + columnIndex); // Build the index to the input buffer to retrieve the alpha value of the background shadow. - unsigned int shadowIndex = 0u; - bool isValidShadowIndex = false; - if (isValidRowIndex) + unsigned int shadowIndex = 0u; + bool isValidShadowIndex = false; + if(isValidRowIndex) { const int xOffsetIndex = columnIndex - xOffset; - isValidShadowIndex = ((xOffsetIndex >= 0) && (xOffsetIndex < width)); + isValidShadowIndex = ((xOffsetIndex >= 0) && (xOffsetIndex < width)); - if (isValidShadowIndex) + if(isValidShadowIndex) { shadowIndex = inputPixelSize * static_cast(offsetRows + xOffsetIndex); } @@ -1234,8 +1214,8 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) // If the input buffer is an alpha mask, retrieve the values for the foreground text and the background shadow. // If not retrieve the color. float inputShadowOffsetAlphaValue = 1.f; - float inputAlphaValue = 1.f; - if (isA8) + float inputAlphaValue = 1.f; + if(isA8) { // Retrieve the alpha value for the shadow. inputShadowOffsetAlphaValue = isValidShadowIndex ? (static_cast(*(inputPixelBuffer + shadowIndex)) / 255.f) : 0.f; @@ -1246,59 +1226,59 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) else { // The input buffer is not an alpha mask. Retrieve the color. - textColor[0u] = TO_FLOAT * static_cast( *(inputPixelBuffer + index + 0u) ); - textColor[1u] = TO_FLOAT * static_cast( *(inputPixelBuffer + index + 1u) ); - textColor[2u] = TO_FLOAT * static_cast( *(inputPixelBuffer + index + 2u) ); - textColor[3u] = TO_FLOAT * static_cast( *(inputPixelBuffer + index + 3u) ); - inputAlphaValue = textColor[3u]; - inputShadowOffsetAlphaValue = isValidShadowIndex ? TO_FLOAT * static_cast( *(inputPixelBuffer + shadowIndex + 3u) ) : 0.f; + textColor[0u] = TO_FLOAT * static_cast(*(inputPixelBuffer + index + 0u)); + textColor[1u] = TO_FLOAT * static_cast(*(inputPixelBuffer + index + 1u)); + textColor[2u] = TO_FLOAT * static_cast(*(inputPixelBuffer + index + 2u)); + textColor[3u] = TO_FLOAT * static_cast(*(inputPixelBuffer + index + 3u)); + inputAlphaValue = textColor[3u]; + inputShadowOffsetAlphaValue = isValidShadowIndex ? TO_FLOAT * static_cast(*(inputPixelBuffer + shadowIndex + 3u)) : 0.f; } // Build the output color. float outputColor[4u]; - if( shadowParameters.blendShadow ) + if(shadowParameters.blendShadow) { // Blend the shadow's color with the text's color on top - const float textAlpha = textColor[3u] * inputAlphaValue; + const float textAlpha = textColor[3u] * inputAlphaValue; const float shadowAlpha = shadowColor[3u] * inputShadowOffsetAlphaValue; // Blends the alpha. - outputColor[3u] = 1.f - ((1.f - textAlpha) * (1.f - shadowAlpha)); + outputColor[3u] = 1.f - ((1.f - textAlpha) * (1.f - shadowAlpha)); const bool isOutputAlphaZero = outputColor[3u] < Dali::Math::MACHINE_EPSILON_1000; - if( isOutputAlphaZero ) + if(isOutputAlphaZero) { - std::fill( outputColor, outputColor + 4u, 0.f ); + std::fill(outputColor, outputColor + 4u, 0.f); } else { // Blends the RGB components. float shadowComponent = 0.f; - float textComponent = 0.f; + float textComponent = 0.f; shadowComponent = shadowColor[0u] * inputShadowOffsetAlphaValue; - textComponent = textColor[0u] * inputAlphaValue; - outputColor[0u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); + textComponent = textColor[0u] * inputAlphaValue; + outputColor[0u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); shadowComponent = shadowColor[1u] * inputShadowOffsetAlphaValue; - textComponent = textColor[1u] * inputAlphaValue; - outputColor[1u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); + textComponent = textColor[1u] * inputAlphaValue; + outputColor[1u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); shadowComponent = shadowColor[2u] * inputShadowOffsetAlphaValue; - textComponent = textColor[2u] * inputAlphaValue; - outputColor[2u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); + textComponent = textColor[2u] * inputAlphaValue; + outputColor[2u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]); } } else { // No blending!!! - std::fill( outputColor, outputColor + 4u, 0.f ); + std::fill(outputColor, outputColor + 4u, 0.f); - const float textAlpha = textColor[3u]; + const float textAlpha = textColor[3u]; const float shadowAlpha = shadowColor[3u] * inputShadowOffsetAlphaValue; // Write shadow first. - if( shadowAlpha > Dali::Math::MACHINE_EPSILON_1000 ) + if(shadowAlpha > Dali::Math::MACHINE_EPSILON_1000) { outputColor[0u] = shadowColor[0u] * inputShadowOffsetAlphaValue; outputColor[1u] = shadowColor[1u] * inputShadowOffsetAlphaValue; @@ -1307,7 +1287,7 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) } // Write character on top. - if( textAlpha > Dali::Math::MACHINE_EPSILON_1000 ) + if(textAlpha > Dali::Math::MACHINE_EPSILON_1000) { outputColor[0u] = textColor[0u]; outputColor[1u] = textColor[1u]; @@ -1317,11 +1297,11 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) } // Write the color into the output pixel buffer. - const unsigned int outputIndex = 4u * (rows + columnIndex); - *(outputPixelBufferPtr + outputIndex + 0u) = static_cast( TO_UCHAR * outputColor[0u] ); - *(outputPixelBufferPtr + outputIndex + 1u) = static_cast( TO_UCHAR * outputColor[1u] ); - *(outputPixelBufferPtr + outputIndex + 2u) = static_cast( TO_UCHAR * outputColor[2u] ); - *(outputPixelBufferPtr + outputIndex + 3u) = static_cast( TO_UCHAR * outputColor[3u] ); + const unsigned int outputIndex = 4u * (rows + columnIndex); + *(outputPixelBufferPtr + outputIndex + 0u) = static_cast(TO_UCHAR * outputColor[0u]); + *(outputPixelBufferPtr + outputIndex + 1u) = static_cast(TO_UCHAR * outputColor[1u]); + *(outputPixelBufferPtr + outputIndex + 2u) = static_cast(TO_UCHAR * outputColor[2u]); + *(outputPixelBufferPtr + outputIndex + 3u) = static_cast(TO_UCHAR * outputColor[3u]); } } @@ -1331,50 +1311,50 @@ Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters ) Devel::PixelBuffer ConvertToRgba8888(Devel::PixelBuffer pixelBuffer, const Vector4& color, bool multiplyByAlpha) { - if (Dali::Pixel::A8 != pixelBuffer.GetPixelFormat()) + if(Dali::Pixel::A8 != pixelBuffer.GetPixelFormat()) { // Does nothing. return pixelBuffer; } - const unsigned int width = pixelBuffer.GetWidth(); - const unsigned int height = pixelBuffer.GetHeight(); - Devel::PixelBuffer newPixelBuffer = Devel::PixelBuffer::New( width, height, Dali::Pixel::RGBA8888 ); + const unsigned int width = pixelBuffer.GetWidth(); + const unsigned int height = pixelBuffer.GetHeight(); + Devel::PixelBuffer newPixelBuffer = Devel::PixelBuffer::New(width, height, Dali::Pixel::RGBA8888); - unsigned char* dstBuffer = newPixelBuffer.GetBuffer(); + unsigned char* dstBuffer = newPixelBuffer.GetBuffer(); const unsigned char* const srcBuffer = pixelBuffer.GetBuffer(); - const unsigned char r = static_cast( TO_UCHAR * color.r ); - const unsigned char g = static_cast( TO_UCHAR * color.g ); - const unsigned char b = static_cast( TO_UCHAR * color.b ); + const unsigned char r = static_cast(TO_UCHAR * color.r); + const unsigned char g = static_cast(TO_UCHAR * color.g); + const unsigned char b = static_cast(TO_UCHAR * color.b); unsigned char dstColor[4]; - for( unsigned int j = 0u; j < height; ++j ) + for(unsigned int j = 0u; j < height; ++j) { const unsigned int lineIndex = j * width; - for( unsigned int i=0u; i < width; ++i ) + for(unsigned int i = 0u; i < width; ++i) { const unsigned int srcIndex = lineIndex + i; - const float srcAlpha = static_cast( *( srcBuffer + srcIndex ) ); + const float srcAlpha = static_cast(*(srcBuffer + srcIndex)); - if( multiplyByAlpha ) + if(multiplyByAlpha) { - dstColor[0u] = static_cast( srcAlpha * color.r ); - dstColor[1u] = static_cast( srcAlpha * color.g ); - dstColor[2u] = static_cast( srcAlpha * color.b ); - dstColor[3u] = static_cast( srcAlpha * color.a ); + dstColor[0u] = static_cast(srcAlpha * color.r); + dstColor[1u] = static_cast(srcAlpha * color.g); + dstColor[2u] = static_cast(srcAlpha * color.b); + dstColor[3u] = static_cast(srcAlpha * color.a); } else { dstColor[0u] = r; dstColor[1u] = g; dstColor[2u] = b; - dstColor[3u] = static_cast( srcAlpha ); + dstColor[3u] = static_cast(srcAlpha); } const unsigned int dstIndex = srcIndex * 4u; - memcpy( dstBuffer + dstIndex, dstColor, 4u ); + memcpy(dstBuffer + dstIndex, dstColor, 4u); } } @@ -1384,42 +1364,42 @@ Devel::PixelBuffer ConvertToRgba8888(Devel::PixelBuffer pixelBuffer, const Vecto void UpdateBuffer(Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x, unsigned int y, bool blend) { const Dali::Pixel::Format pixelFormat = dst.GetPixelFormat(); - if( src.GetPixelFormat() != pixelFormat ) + if(src.GetPixelFormat() != pixelFormat) { DALI_LOG_ERROR("PixelBuffer::SetBuffer. The pixel format of the new data must be the same of the current pixel buffer."); return; } - const unsigned int srcWidth = src.GetWidth(); + const unsigned int srcWidth = src.GetWidth(); const unsigned int srcHeight = src.GetHeight(); - const unsigned int dstWidth = dst.GetWidth(); + const unsigned int dstWidth = dst.GetWidth(); const unsigned int dstHeight = dst.GetHeight(); - if( ( x > dstWidth ) || - ( y > dstHeight ) || - ( x + srcWidth > dstWidth ) || - ( y + srcHeight > dstHeight ) ) + if((x > dstWidth) || + (y > dstHeight) || + (x + srcWidth > dstWidth) || + (y + srcHeight > dstHeight)) { DALI_LOG_ERROR("PixelBuffer::SetBuffer. The source pixel buffer is out of the boundaries of the destination pixel buffer."); return; } const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(pixelFormat); - if( bytesPerPixel == 0u || bytesPerPixel == 12u || bytesPerPixel == 24u ) + if(bytesPerPixel == 0u || bytesPerPixel == 12u || bytesPerPixel == 24u) { return; } const unsigned int alphaIndex = bytesPerPixel - 1u; const unsigned char* const srcBuffer = src.GetBuffer(); - unsigned char* dstBuffer = dst.GetBuffer(); + unsigned char* dstBuffer = dst.GetBuffer(); - if( !blend ) + if(!blend) { const unsigned int currentLineSize = dstWidth * bytesPerPixel; - const unsigned int newLineSize = srcWidth * bytesPerPixel; - unsigned char* currentBuffer = dstBuffer + (y * dstWidth + x) * bytesPerPixel; - for (unsigned int j = 0u; j < srcHeight; ++j) + const unsigned int newLineSize = srcWidth * bytesPerPixel; + unsigned char* currentBuffer = dstBuffer + (y * dstWidth + x) * bytesPerPixel; + for(unsigned int j = 0u; j < srcHeight; ++j) { memcpy(currentBuffer + j * currentLineSize, srcBuffer + j * newLineSize, newLineSize); } @@ -1437,41 +1417,41 @@ void UpdateBuffer(Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x // Jump till the 'x,y' position const unsigned int dstWidthBytes = dstWidth * bytesPerPixel; - dstBuffer += ( y * dstWidthBytes + x * bytesPerPixel ); + dstBuffer += (y * dstWidthBytes + x * bytesPerPixel); - for (unsigned int j = 0u; j < srcHeight; ++j) + for(unsigned int j = 0u; j < srcHeight; ++j) { const unsigned int srcLineIndex = j * srcWidth; - for (unsigned int i = 0u; i < srcWidth; ++i) + for(unsigned int i = 0u; i < srcWidth; ++i) { - const float srcAlpha = TO_FLOAT * static_cast( *( srcBuffer + bytesPerPixel * ( srcLineIndex + i ) + alphaIndex ) ); - const float dstAlpha = TO_FLOAT * static_cast( *(dstBuffer + i*bytesPerPixel + alphaIndex) ); + const float srcAlpha = TO_FLOAT * static_cast(*(srcBuffer + bytesPerPixel * (srcLineIndex + i) + alphaIndex)); + const float dstAlpha = TO_FLOAT * static_cast(*(dstBuffer + i * bytesPerPixel + alphaIndex)); // Blends the alpha channel. const float oneMinusSrcAlpha = 1.f - srcAlpha; - outputColor[alphaIndex] = 1.f - (oneMinusSrcAlpha * (1.f - dstAlpha)); + outputColor[alphaIndex] = 1.f - (oneMinusSrcAlpha * (1.f - dstAlpha)); // Blends the RGB channels. const bool isOutputAlphaZero = outputColor[alphaIndex] < Dali::Math::MACHINE_EPSILON_1000; - if( isOutputAlphaZero ) + if(isOutputAlphaZero) { - std::fill( outputColor, outputColor + bytesPerPixel, 0.f ); + std::fill(outputColor, outputColor + bytesPerPixel, 0.f); } else { - const float srcAlphaOverOutputAlpha = srcAlpha / outputColor[alphaIndex]; // fgAlpha / alpha + const float srcAlphaOverOutputAlpha = srcAlpha / outputColor[alphaIndex]; // fgAlpha / alpha const float dstAlphaOneMinusSrcAlphaOverOutputAlpha = dstAlpha * oneMinusSrcAlpha / outputColor[alphaIndex]; // bgAlpha * ( 1 - fgAlpha ) / alpha - for (unsigned int index = 0u; index < alphaIndex; ++index) + for(unsigned int index = 0u; index < alphaIndex; ++index) { - const float dstComponent = TO_FLOAT * static_cast( *( dstBuffer + i * bytesPerPixel + index ) ) * dstAlpha; - const float srcComponent = TO_FLOAT * static_cast(*(srcBuffer + bytesPerPixel * (srcLineIndex + i) + index) ) * srcAlpha; - outputColor[index] = ( srcComponent * srcAlphaOverOutputAlpha ) + ( dstComponent * dstAlphaOneMinusSrcAlphaOverOutputAlpha ); + const float dstComponent = TO_FLOAT * static_cast(*(dstBuffer + i * bytesPerPixel + index)) * dstAlpha; + const float srcComponent = TO_FLOAT * static_cast(*(srcBuffer + bytesPerPixel * (srcLineIndex + i) + index)) * srcAlpha; + outputColor[index] = (srcComponent * srcAlphaOverOutputAlpha) + (dstComponent * dstAlphaOneMinusSrcAlphaOverOutputAlpha); } } - for (unsigned int index = 0u; index < bytesPerPixel; ++index) + for(unsigned int index = 0u; index < bytesPerPixel; ++index) { - *(dstBuffer + i * bytesPerPixel + index) = static_cast( TO_UCHAR * outputColor[index] ); + *(dstBuffer + i * bytesPerPixel + index) = static_cast(TO_UCHAR * outputColor[index]); } } @@ -1480,96 +1460,90 @@ void UpdateBuffer(Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x } } - -Dali::Property::Array RenderForLastIndex( RendererParameters& textParameters ) +Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters) { Property::Array offsetValues; - if( textParameters.text.empty() ) + if(textParameters.text.empty()) { return offsetValues; } FontClient fontClient = FontClient::Get(); MetricsPtr metrics; - metrics = Metrics::New( fontClient ); - - Text::ModelPtr textModel = Text::Model::New(); - InternalDataModel internalData( fontClient, metrics, textModel ); + metrics = Metrics::New(fontClient); - TextAbstraction::TextRenderer::Parameters rendererParameters( textModel->mVisualModel->mGlyphs, - textModel->mVisualModel->mGlyphPositions, - textModel->mVisualModel->mColors, - textModel->mVisualModel->mColorIndices, - internalData.blendingMode, - internalData.isEmoji ); + Text::ModelPtr textModel = Text::Model::New(); + InternalDataModel internalData(fontClient, metrics, textModel); + TextAbstraction::TextRenderer::Parameters rendererParameters(textModel->mVisualModel->mGlyphs, + textModel->mVisualModel->mGlyphPositions, + textModel->mVisualModel->mColors, + textModel->mVisualModel->mColorIndices, + internalData.blendingMode, + internalData.isEmoji); - rendererParameters.width = textParameters.textWidth; + rendererParameters.width = textParameters.textWidth; rendererParameters.height = textParameters.textHeight; //////////////////////////////////////////////////////////////////////////////// // Process the markup string if the mark-up processor is enabled. //////////////////////////////////////////////////////////////////////////////// - ShapeTextPreprocess( textParameters, rendererParameters, internalData ); + ShapeTextPreprocess(textParameters, rendererParameters, internalData); //////////////////////////////////////////////////////////////////////////////// // Retrieve the glyphs. Text shaping //////////////////////////////////////////////////////////////////////////////// Dali::Vector embeddedItemLayout; - ShapeText( rendererParameters, embeddedItemLayout, internalData ); - + ShapeText(rendererParameters, embeddedItemLayout, internalData); //////////////////////////////////////////////////////////////////////////////// // Retrieve the glyph's metrics. //////////////////////////////////////////////////////////////////////////////// - metrics->GetGlyphMetrics( rendererParameters.glyphs.Begin(), internalData.numberOfGlyphs ); - + metrics->GetGlyphMetrics(rendererParameters.glyphs.Begin(), internalData.numberOfGlyphs); //////////////////////////////////////////////////////////////////////////////// // Layout the text //////////////////////////////////////////////////////////////////////////////// - int boundingBox = textParameters.textHeight; + int boundingBox = textParameters.textHeight - (textParameters.padding.top + textParameters.padding.bottom); textParameters.textHeight = MAX_INT; // layout for the entire area. - LayoutText( textParameters, rendererParameters, embeddedItemLayout, internalData ); + LayoutText(textParameters, rendererParameters, embeddedItemLayout, internalData); //////////////////////////////////////////////////////////////////////////////// // Calculation last character index //////////////////////////////////////////////////////////////////////////////// - Vector& lines = internalData.textModel->mVisualModel->mLines; - unsigned int numberOfLines = lines.Count(); - int numberOfCharacters = 0; - float penY = 0.f; - float lineSize = internalData.layoutEngine.GetDefaultLineSize(); - float lineOffset = 0.f; - for( unsigned int index = 0u; index < numberOfLines; ++index ) + Vector& lines = internalData.textModel->mVisualModel->mLines; + unsigned int numberOfLines = lines.Count(); + int numberOfCharacters = 0; + float penY = 0.f; + float lineSize = internalData.layoutEngine.GetDefaultLineSize(); + float lineOffset = 0.f; + for(unsigned int index = 0u; index < numberOfLines; ++index) { - const LineRun& line = *( lines.Begin() + index ); + const LineRun& line = *(lines.Begin() + index); numberOfCharacters += line.characterRun.numberOfCharacters; - lineOffset = lineSize > 0.f ? lineSize : ( line.ascender + -line.descender ); + lineOffset = lineSize > 0.f ? lineSize : (line.ascender + -line.descender); penY += lineOffset; - if( ( penY + lineOffset ) > boundingBox ) + if((penY + lineOffset) > boundingBox) { - offsetValues.PushBack( numberOfCharacters ); + offsetValues.PushBack(numberOfCharacters); penY = 0.f; } } - if( penY > 0.f) + if(penY > 0.f) { // add remain character index - offsetValues.PushBack( numberOfCharacters ); + offsetValues.PushBack(numberOfCharacters); } return offsetValues; } - -Dali::Property::Array GetLastCharacterIndex( RendererParameters& textParameters ) +Dali::Property::Array GetLastCharacterIndex(RendererParameters& textParameters) { - Dali::Property::Array offsetValues = Toolkit::DevelText::RenderForLastIndex( textParameters ); + Dali::Property::Array offsetValues = Toolkit::DevelText::RenderForLastIndex(textParameters); return offsetValues; } - } // namespace DevelText } // namespace Toolkit