From: Agnelo Vaz Date: Wed, 20 Sep 2017 13:21:55 +0000 (+0100) Subject: TextVisual Outline support X-Git-Tag: dali_1.2.58~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=4cfc161e92f47722b38d58987ac8f8773bad13c5 TextVisual Outline support Text outline support for TextVisual Memory Consuption memps Average over 10 runs. 200 TextLabels = 16112 bytes 80 bytes per TextLabel (pre this patch) 200 TextLabels = 16118 bytes 80 bytes per TextLabel (including this patch) No significant change before and after this patch for Textlabel 200 TextLabels = 101931 bytes 509 bytes per TextLabel with outline Styling increases memory usage as expected. MemPS data 16112 80 bytes per TextLabel before patch 16116 16112 16112 16116 16112 16116 16108 16116 16112 161132/10 = 16113 = 80bytes 16120 80 bytes per TextLabel after patch 16116 16116 16120 16116 16116 16128 16116 16116 16120 161184/10 = 16118 = 80bytes 101832 509 bytes per TextLabel after patch with outline 101832 101860 101836 101828 101828 101828 101832 101832 102808 1019316/10 = 101931 = 509 bytes Change-Id: I69aa79f6211a3fb076f557faf6f104b472fd0787 --- diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp old mode 100644 new mode 100755 index df25aaa..5cc9401 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp @@ -152,8 +152,8 @@ public: void GetFontMetrics( FontId fontId, FontMetrics& metrics ){} GlyphIndex GetGlyphIndex( FontId fontId, Character charcode ){return 0;} bool GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal ){return true;} - void CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data ){} - PixelData CreateBitmap( FontId fontId, GlyphIndex glyphIndex ){return PixelData();} + void CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth ){} + PixelData CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth ){return PixelData();} void CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight ) { @@ -472,14 +472,14 @@ bool FontClient::GetGlyphMetrics( GlyphInfo* array, uint32_t size, GlyphType typ return GetImplementation(*this).GetGlyphMetrics( array, size, horizontal ); } -void FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data ) +void FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth ) { - GetImplementation(*this).CreateBitmap( fontId, glyphIndex, data ); + GetImplementation(*this).CreateBitmap( fontId, glyphIndex, data, outlineWidth ); } -PixelData FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex ) +PixelData FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth ) { - return GetImplementation(*this).CreateBitmap( fontId, glyphIndex ); + return GetImplementation(*this).CreateBitmap( fontId, glyphIndex, outlineWidth ); } void FontClient::CreateVectorBlob( FontId fontId, diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 3fd4bd6..59925df 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -732,8 +732,19 @@ int UtcDaliTextEditorSetPropertyP(void) DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION ); // Check the outline property - editor.SetProperty( TextEditor::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + + editor.SetProperty( TextEditor::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = editor.GetProperty( TextEditor::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the input outline property editor.SetProperty( TextEditor::Property::INPUT_OUTLINE, "Outline input properties" ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 08b194f..a7389b0 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -827,8 +827,19 @@ int UtcDaliTextFieldSetPropertyP(void) DALI_TEST_EQUALS( field.GetProperty( TextField::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION ); // Check the outline property - field.SetProperty( TextField::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + + field.SetProperty( TextField::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = field.GetProperty( TextField::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the input outline property field.SetProperty( TextField::Property::INPUT_OUTLINE, "Outline input properties" ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index beba3a6..2f2e692 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -434,8 +434,18 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::EMBOSS ), std::string("Emboss properties"), TEST_LOCATION ); // Check the outline property - label.SetProperty( TextLabel::Property::OUTLINE, "Outline properties" ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION ); + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 2.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + outlineMapSet["color"] = "red"; + outlineMapSet["width"] = "2"; + outlineMapGet = label.GetProperty( TextLabel::Property::OUTLINE ); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); // Check the pixel size of font label.SetProperty( DevelTextLabel::Property::PIXEL_SIZE, 20.f ); @@ -990,3 +1000,71 @@ int UtcDaliToolkitTextLabelColorComponents(void) END_TEST; } + +int UtcDaliToolkitTextlabelTextStyle01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextlabelTextStyle Setting Outline after Shadow"); + + TextLabel label = TextLabel::New(); + label.SetSize( 300.0f, 300.f ); + label.SetProperty( TextLabel::Property::TEXT, "Hello world Hello world" ); + label.SetProperty( TextLabel::Property::POINT_SIZE, 12 ); + Stage::GetCurrent().Add( label ); + + Property::Map outlineMapSet; + Property::Map outlineMapGet; + + outlineMapSet["color"] = Color::BLUE; + outlineMapSet["width"] = 2.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + application.SendNotification(); + application.Render(); + + Property::Map shadowMapSet; + shadowMapSet.Insert( "color", "green" ); + shadowMapSet.Insert( "offset", "2 2" ); + label.SetProperty( TextLabel::Property::SHADOW, shadowMapSet ); + + outlineMapSet["color"] = Color::RED; + outlineMapSet["width"] = 0.0f; + label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); + + application.SendNotification(); + application.Render(); + + outlineMapGet = label.GetProperty( TextLabel::Property::OUTLINE ); + + Property::Value* colorValue = outlineMapGet.Find("color"); + + bool colorMatched( false ); + + if ( colorValue ) + { + Property::Type valueType = colorValue->GetType(); + + if ( Property::STRING == valueType ) + { + std::string stringValue; + colorValue->Get( stringValue ); + if ( stringValue == "red" ) + { + colorMatched = true; + } + } + else if ( Property::VECTOR4 == valueType ) + { + Vector4 colorVector4; + colorValue->Get( colorVector4 ); + if ( colorVector4 == Color::RED ) + { + colorMatched = true; + } + } + } + + DALI_TEST_EQUALS( colorMatched, true, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 13eeae6..62865d6 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -94,6 +94,7 @@ const float HALF( 0.5f ); const float ONE( 1.0f ); const uint32_t DEFAULT_ATLAS_WIDTH = 512u; const uint32_t DEFAULT_ATLAS_HEIGHT = 512u; +const int NO_OUTLINE( 0 ); } struct AtlasRenderer::Impl @@ -354,7 +355,8 @@ struct AtlasRenderer::Impl mFontClient.CreateBitmap( glyph.fontId, glyph.index, - glyphBufferData ); + glyphBufferData, + NO_OUTLINE ); // Create the pixel data. bitmap = PixelData::New( glyphBufferData.buffer, diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp old mode 100644 new mode 100755 index 66bb797..b524710 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -102,7 +102,7 @@ void TypesetGlyph( GlyphData& data, if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) { // Do not write out of bounds. - break; + continue; } const int verticalOffset = yOffsetIndex * data.width; @@ -114,7 +114,7 @@ void TypesetGlyph( GlyphData& data, if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) { // Don't write out of bounds. - break; + continue; } uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); @@ -138,7 +138,7 @@ void TypesetGlyph( GlyphData& data, } // Update the alpha channel. - if( Typesetter::STYLE_MASK == style ) + if( Typesetter::STYLE_MASK == style || Typesetter::STYLE_OUTLINE == style ) // Outline not shown for color glyph { // Create an alpha mask for color glyph. *( packedColorGlyphBuffer + 3u ) = 0u; @@ -191,7 +191,7 @@ void TypesetGlyph( GlyphData& data, if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) { // Do not write out of bounds. - break; + continue; } const int verticalOffset = yOffsetIndex * data.width; @@ -203,7 +203,7 @@ void TypesetGlyph( GlyphData& data, if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) { // Don't write out of bounds. - break; + continue; } uint8_t* bitmapBuffer = reinterpret_cast< uint8_t* >( data.bitmapBuffer.GetBuffer() ); @@ -217,7 +217,6 @@ void TypesetGlyph( GlyphData& data, // Check alpha of overlapped pixels uint8_t& currentAlpha = *( bitmapBuffer + verticalOffset + xOffsetIndex ); uint8_t newAlpha = static_cast( color->a * static_cast( alpha ) ); -// printf("y: %d, x: %d: alpha: %u, currentAlpha: %u, newAlpha: %u, a: %u\n", yOffsetIndex, xOffsetIndex, alpha, currentAlpha, newAlpha, std::max( currentAlpha, newAlpha ) ); // For any pixel overlapped with the pixel in previous glyphs, make sure we don't // overwrite a previous bigger alpha with a smaller alpha (in order to avoid @@ -327,6 +326,18 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( ( RENDER_NO_STYLES != behaviour ) && ( RENDER_MASK != behaviour ) ) { + + // Generate the outline if enabled + const float outlineWidth = mModel->GetOutlineWidth(); + 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 ); + + // Combine the two buffers + imageBuffer = CombineImageBuffer( imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight ); + } + // @todo. Support shadow and underline for partial text later on. // Generate the shadow if enabled @@ -379,6 +390,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth glyphData.width = bufferWidth; glyphData.height = bufferHeight; glyphData.bitmapBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, pixelFormat ); + glyphData.horizontalOffset = 0; if ( Pixel::RGBA8888 == pixelFormat ) { @@ -405,14 +417,27 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth // Increases the vertical offset with the line's ascender. glyphData.verticalOffset += static_cast( line.ascender ); - if ( style == Typesetter::STYLE_SHADOW ) + // Retrieves the glyph's outline width + float outlineWidth = mModel->GetOutlineWidth(); + + if( style == Typesetter::STYLE_OUTLINE ) + { + glyphData.horizontalOffset -= outlineWidth; + if( lineIndex == 0u ) + { + // Only need to add the vertical outline offset for the first line + glyphData.verticalOffset -= outlineWidth; + } + } + else if ( style == Typesetter::STYLE_SHADOW ) { const Vector2& shadowOffset = mModel->GetShadowOffset(); - glyphData.horizontalOffset += shadowOffset.x; + glyphData.horizontalOffset += shadowOffset.x - outlineWidth; // if outline enabled then shadow should offset from outline + if ( lineIndex == 0u ) { - // Only need to add the vertical shadow offset for once - glyphData.verticalOffset += shadowOffset.y; + // Only need to add the vertical shadow offset for first line + glyphData.verticalOffset += shadowOffset.y - outlineWidth; } } @@ -532,6 +557,10 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth { color = &( mModel->GetShadowColor() ); } + else if ( style == Typesetter::STYLE_OUTLINE ) + { + color = &( mModel->GetOutlineColor() ); + } else { color = ( useDefaultColor || ( 0u == colorIndex ) ) ? &defaultColor : colorsBuffer + ( colorIndex - 1u ); @@ -541,9 +570,17 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth glyphData.glyphBitmap.buffer = NULL; glyphData.glyphBitmap.width = glyphInfo->width; // Desired width and height. glyphData.glyphBitmap.height = glyphInfo->height; + + if( style != Typesetter::STYLE_OUTLINE && style != Typesetter::STYLE_SHADOW ) + { + // Don't render outline for other styles + outlineWidth = 0.0f; + } + fontClient.CreateBitmap( glyphInfo->fontId, glyphInfo->index, - glyphData.glyphBitmap ); + glyphData.glyphBitmap, + outlineWidth ); // Sets the glyph's bitmap into the bitmap of the whole text. if( NULL != glyphData.glyphBitmap.buffer ) diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp old mode 100644 new mode 100755 index 1dcda36..fe3c451 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -188,6 +188,16 @@ void ViewModel::GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex ind mModel->GetUnderlineRuns( underlineRuns, index, numberOfRuns ); } +const Vector4& ViewModel::GetOutlineColor() const +{ + return mModel->GetOutlineColor(); +} + +float ViewModel::GetOutlineWidth() const +{ + return mModel->GetOutlineWidth(); +} + void ViewModel::ElideGlyphs() { mIsTextElided = false; diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h old mode 100644 new mode 100755 index e15fa9c..827ecf0 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -172,6 +172,16 @@ public: virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const; /** + * @copydoc ModelInterface::GetOutlineColor() + */ + virtual const Vector4& GetOutlineColor() const; + + /** + * @copydoc ModelInterface::GetOutlineWidth() + */ + virtual float GetOutlineWidth() const; + + /** * @brief Does the text elide. * * It stores a copy of the visible glyphs and removes as many glyphs as needed diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp old mode 100644 new mode 100755 index 258fea7..482cfc3 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -1129,6 +1129,30 @@ float Controller::GetUnderlineHeight() const return mImpl->mModel->mVisualModel->GetUnderlineHeight(); } +void Controller::SetOutlineColor( const Vector4& color ) +{ + mImpl->mModel->mVisualModel->SetOutlineColor( color ); + + mImpl->RequestRelayout(); +} + +const Vector4& Controller::GetOutlineColor() const +{ + return mImpl->mModel->mVisualModel->GetOutlineColor(); +} + +void Controller::SetOutlineWidth( float width ) +{ + mImpl->mModel->mVisualModel->SetOutlineWidth( width ); + + mImpl->RequestRelayout(); +} + +float Controller::GetOutlineWidth() const +{ + return mImpl->mModel->mVisualModel->GetOutlineWidth(); +} + void Controller::SetDefaultEmbossProperties( const std::string& embossProperties ) { if( NULL == mImpl->mEmbossDefaults ) diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h old mode 100644 new mode 100755 index 9e193c7..3d0eb6c --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -777,6 +777,34 @@ public: // Default style & Input style float GetUnderlineHeight() const; /** + * @brief Set the outline color. + * + * @param[in] color color of outline. + */ + void SetOutlineColor( const Vector4& color ); + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + const Vector4& GetOutlineColor() const; + + /** + * @brief Set the outline width + * + * @param[in] width The width in pixels of the outline, 0 indicates no outline + */ + void SetOutlineWidth( float width ); + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + float GetOutlineWidth() const; + + /** * @brief Sets the emboss's properties string. * * @note The string is stored to be recovered. diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp old mode 100644 new mode 100755 index 75fabd7..8b71d30 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -35,6 +35,7 @@ namespace { const std::string COLOR_KEY( "color" ); const std::string OFFSET_KEY( "offset" ); +const std::string WIDTH_KEY( "width" ); const std::string HEIGHT_KEY( "height" ); const std::string ENABLE_KEY( "enable" ); const std::string TRUE_TOKEN( "true" ); @@ -120,6 +121,36 @@ bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap, return 0u == numberOfItems; } +bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap, + bool& colorDefined, + Vector4& color, + bool& widthDefined, + float& width ) +{ + const unsigned int numberOfItems = underlinePropertiesMap.Count(); + + // Parses and applies the style. + for( unsigned int index = 0u; index < numberOfItems; ++index ) + { + const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index ); + + if( COLOR_KEY == valueGet.first.stringKey ) + { + /// Color key. + colorDefined = true; + color = valueGet.second.Get(); + } + else if( WIDTH_KEY == valueGet.first.stringKey ) + { + /// Width key. + widthDefined = true; + width = valueGet.second.Get(); + } + } + + return 0u == numberOfItems; +} + bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) { bool update = false; @@ -463,24 +494,63 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu if( controller ) { - const std::string properties = value.Get< std::string >(); - switch( type ) { case EffectStyle::DEFAULT: { - // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function. - controller->SetDefaultOutlineProperties( properties ); + const Property::Map& propertiesMap = value.Get(); + + bool colorDefined = false; + Vector4 color; + bool widthDefined = false; + float width = 0.f; + + bool empty = true; + + if ( !propertiesMap.Empty() ) + { + empty = ParseOutlineProperties( propertiesMap, + colorDefined, + color, + widthDefined, + width ); + } + + if( !empty ) + { + // Sets the default outline values. + if( colorDefined && ( controller->GetOutlineColor() != color ) ) + { + controller->SetOutlineColor( color ); + update = true; + } + + if( widthDefined && ( fabsf( controller->GetOutlineWidth() - width ) > Math::MACHINE_EPSILON_1000 ) ) + { + controller->SetOutlineWidth( width ); + update = true; + } + } + else + { + // Disable outline + if( fabsf( controller->GetOutlineWidth() ) > Math::MACHINE_EPSILON_1000 ) + { + controller->SetOutlineWidth( 0.0f ); + update = true; + } + } break; } case EffectStyle::INPUT: { - // Stores the input outline's properties string to be recovered by the GetOutlineProperties() function. - controller->SetInputOutlineProperties( properties ); + const std::string& outlineProperties = value.Get(); + + controller->SetInputOutlineProperties( outlineProperties ); break; } - } - } + } // switch + } // if( controller ) return update; } @@ -493,7 +563,21 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff { case EffectStyle::DEFAULT: { - value = controller->GetDefaultOutlineProperties(); + const Vector4& color = controller->GetOutlineColor(); + const float width = controller->GetOutlineWidth(); + + Property::Map map; + + std::string colorStr; + Vector4ToColorString( color, colorStr ); + map.Insert( COLOR_KEY, colorStr ); + + std::string widthStr; + FloatToString( width, widthStr ); + map.Insert( WIDTH_KEY, widthStr ); + + value = map; + break; } case EffectStyle::INPUT: diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h old mode 100644 new mode 100755 index 4ab61a3..521f52c --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -72,6 +72,21 @@ bool ParseUnderlineProperties( const Property::Map& underlineProperties, float& height ); /** + * @brief Parses the outline properties. + * + * @param[in] outlineProperties The map with the outline properties. + * @param[out] colorDefined Whether the outline's color is defined. + * @param[out] color The outline's color. + * @param[out] widthDefined Whether the outline's width is defined. + * @param[out] width The outline's width. + */ +bool ParseOutlineProperties( const Property::Map& outlineProperties, + bool& colorDefined, + Vector4& color, + bool& widthDefined, + float& width ); + +/** * @brief Sets the underline properties. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h old mode 100644 new mode 100755 index 38e1fa2..18cb7cc --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -210,6 +210,21 @@ public: * @param[in] numberOfRuns Number of underline runs to be copied. */ virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const = 0; + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + virtual const Vector4& GetOutlineColor() const = 0; + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + virtual float GetOutlineWidth() const = 0; + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp old mode 100644 new mode 100755 index 2c00cf8..cf6f35c --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -147,6 +147,16 @@ void Model::GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, mVisualModel->GetUnderlineRuns( underlineRuns, index, numberOfRuns ); } +const Vector4& Model::GetOutlineColor() const +{ + return mVisualModel->GetOutlineColor(); +} + +float Model::GetOutlineWidth() const +{ + return mVisualModel->GetOutlineWidth(); +} + Model::Model() : mLogicalModel(), mVisualModel(), diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h old mode 100644 new mode 100755 index a7b0bb8..cd49581 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -174,6 +174,16 @@ public: */ virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const; + /** + * @copydoc ModelInterface::GetOutlineColor() + */ + virtual const Vector4& GetOutlineColor() const; + + /** + * @copydoc ModelInterface::GetOutlineWidth() + */ + virtual float GetOutlineWidth() const; + private: // Private contructors & copy operator. /** diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp old mode 100644 new mode 100755 index 1b114c4..3e3f2d6 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -350,6 +350,11 @@ void VisualModel::SetUnderlineColor( const Vector4& color ) mUnderlineColorSet = true; } +void VisualModel::SetOutlineColor( const Vector4& color ) +{ + mOutlineColor = color; +} + void VisualModel::SetUnderlineEnabled( bool enabled ) { mUnderlineEnabled = enabled; @@ -360,6 +365,11 @@ void VisualModel::SetUnderlineHeight( float height ) mUnderlineHeight = height; } +void VisualModel::SetOutlineWidth( float width ) +{ + mOutlineWidth = width; +} + const Vector4& VisualModel::GetTextColor() const { return mTextColor; @@ -380,6 +390,11 @@ const Vector4& VisualModel::GetUnderlineColor() const return mUnderlineColor; } +const Vector4& VisualModel::GetOutlineColor() const +{ + return mOutlineColor; +} + bool VisualModel::IsUnderlineEnabled() const { return mUnderlineEnabled; @@ -390,6 +405,11 @@ float VisualModel::GetUnderlineHeight() const return mUnderlineHeight; } +float VisualModel::GetOutlineWidth() const +{ + return mOutlineWidth; +} + Length VisualModel::GetNumberOfUnderlineRuns() const { return mUnderlineRuns.Count(); @@ -415,9 +435,11 @@ VisualModel::VisualModel() mTextColor( Color::BLACK ), mShadowColor( Color::BLACK ), mUnderlineColor( Color::BLACK ), + mOutlineColor( Color::WHITE ), mControlSize(), mShadowOffset(), mUnderlineHeight( 0.0f ), + mOutlineWidth( 0.0f ), mNaturalSize(), mLayoutSize(), mCachedLineIndex( 0u ), diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h old mode 100644 new mode 100755 index 6356f32..ea888cd --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -287,6 +287,34 @@ public: */ Length GetNumberOfUnderlineRuns() const; + /** + * @brief Set the outline color. + * + * @param[in] color color of outline. + */ + void SetOutlineColor( const Vector4& color ); + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + const Vector4& GetOutlineColor() const; + + /** + * @brief Set the outline width + * + * @param[in] width The width in pixels of the outline, 0 indicates no outline + */ + void SetOutlineWidth( float width ); + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + float GetOutlineWidth() const; + protected: /** @@ -323,9 +351,11 @@ public: Vector4 mTextColor; ///< The text color Vector4 mShadowColor; ///< Color of drop shadow Vector4 mUnderlineColor; ///< Color of underline + Vector4 mOutlineColor; ///< Color of outline Size mControlSize; ///< The size of the UI control. Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow float mUnderlineHeight; ///< Fixed height for underline to override font metrics. + float mOutlineWidth; ///< Width of outline. private: diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp old mode 100644 new mode 100755 index c90c727..4031f94 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -586,6 +586,7 @@ void TextVisual::UpdateRenderer() } // Check whether the text contains any style colors (e.g. underline color, shadow color, etc.) + bool shadowEnabled = false; const Vector2& shadowOffset = mController->GetTextModel()->GetShadowOffset(); if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) @@ -593,9 +594,16 @@ void TextVisual::UpdateRenderer() shadowEnabled = true; } + bool outlineWidthEnabled = false; + float outlineWidth = mController->GetTextModel()->GetOutlineWidth(); + if ( outlineWidth > Math::MACHINE_EPSILON_1 ) + { + outlineWidthEnabled = true; + } + const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled(); - if ( hasMultipleTextColors || containsEmoji || shadowEnabled || underlineEnabled ) + if ( hasMultipleTextColors || containsEmoji || shadowEnabled || underlineEnabled || outlineWidthEnabled ) { // Create RGBA textures if the text contains emojis or styles or multiple text colors