From: Richard Underhill Date: Thu, 2 Apr 2015 14:46:04 +0000 (+0100) Subject: Added TEXT_COLOR, UNDERLINE_ENABLED and UNDERLINE_COLOR to properties and atlas renderer X-Git-Tag: dali_1.0.38~11^2~15 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=9db1f87a421a896c62580a733449486512315c9a Added TEXT_COLOR, UNDERLINE_ENABLED and UNDERLINE_COLOR to properties and atlas renderer Change-Id: I0bc2f5a71a64b145c600fd9015dd02db131e5fe7 Signed-off-by: Richard Underhill --- diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp index 826ea1e..83bb423 100644 --- a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp @@ -37,12 +37,14 @@ namespace const Vector2 DEFAULT_BLOCK_SIZE( 32.0f, 32.0f ); const uint32_t SINGLE_PIXEL_PADDING( 1u ); const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 ); + const uint32_t FILLED_PIXEL( -1 ); } AtlasManager::AtlasManager() : mNewAtlasSize( DEFAULT_ATLAS_SIZE ), mNewBlockSize( DEFAULT_BLOCK_SIZE ), - mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES ) + mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES ), + mFilledPixel( FILLED_PIXEL ) { } @@ -103,7 +105,8 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( SizeType width, SINGLE_PIXEL_PADDING, blockHeight - DOUBLE_PIXEL_PADDING, pixelformat ); - + atlasDescriptor.mFilledPixelImage = BufferImage::New( reinterpret_cast< PixelBuffer* >( &mFilledPixel ), 1, 1, pixelformat ); + atlas.Upload( atlasDescriptor.mFilledPixelImage, 0, 0 ); mAtlasList.push_back( atlasDescriptor ); return mAtlasList.size(); } @@ -413,7 +416,6 @@ void AtlasManager::CreateMesh( SizeType atlas, meshData.SetFaceIndices( faces ); meshData.SetMaterial( mAtlasList[ atlas ].mMaterial ); - //PrintMeshData( meshData ); } void AtlasManager::PrintMeshData( const MeshData& meshData ) @@ -510,9 +512,6 @@ void AtlasManager::StitchMesh( MeshData& first, } first.SetFaceIndices( f1 ); - - // TODO rather than set the material to the second, check to see if there's a match and return if not - first.SetMaterial( second.GetMaterial() ); } void AtlasManager::StitchMesh( const MeshData& first, @@ -565,8 +564,7 @@ void AtlasManager::StitchMesh( const MeshData& first, out.SetVertices( vertices ); } - // TODO rather than set the material to the second, check to see if there's a match and return if not - out.SetMaterial( second.GetMaterial() ); + out.SetMaterial( first.GetMaterial() ); out.SetFaceIndices( faces ); } @@ -604,20 +602,25 @@ void AtlasManager::UploadImage( const BufferImage& image, DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n"); } - // Blit top strip - if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, - blockOffsetX, - blockOffsetY ) ) + // If this is the first block then we need to keep the first pixel free for underline texture + if ( block ) { - DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n"); - } - // Blit left strip - if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, - blockOffsetX, - blockOffsetY + SINGLE_PIXEL_PADDING ) ) - { - DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n"); + // Blit top strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, + blockOffsetX, + blockOffsetY ) ) + { + DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n"); + } + + // Blit left strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, + blockOffsetX, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n"); + } } // Blit bottom strip @@ -743,7 +746,7 @@ Vector2 AtlasManager::GetBlockSize( AtlasId atlas ) } else { - return Vector2( 0.0f, 0.0f ); + return Vector2::ZERO; } } @@ -756,7 +759,7 @@ Vector2 AtlasManager::GetAtlasSize( AtlasId atlas ) } else { - return Vector2( 0.0f, 0.0f ); + return Vector2::ZERO; } } diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h index 6f1411e..0656da7 100644 --- a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h @@ -67,6 +67,7 @@ public: Pixel::Format mPixelFormat; // pixel format used by atlas BufferImage mHorizontalStrip; // Image used to pad upload BufferImage mVerticalStrip; // Image used to pad upload + BufferImage mFilledPixelImage; // Image used by atlas for operations such as underline PixelBuffer* mStripBuffer; // Blank image buffer used to pad upload Material mMaterial; // material used for atlas texture SizeType mNextFreeBlock; // next free block will be placed here ( actually +1 ) @@ -217,6 +218,7 @@ private: Vector2 mNewAtlasSize; Vector2 mNewBlockSize; Toolkit::AtlasManager::AddFailPolicy mAddFailPolicy; + uint32_t mFilledPixel; }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index 4ff2035..6149e29 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -83,9 +83,11 @@ DALI_PROPERTY_REGISTRATION( TextLabel, "point-size", FLOAT, POINT_SI DALI_PROPERTY_REGISTRATION( TextLabel, "multi-line", BOOLEAN, MULTI_LINE ) DALI_PROPERTY_REGISTRATION( TextLabel, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) DALI_PROPERTY_REGISTRATION( TextLabel, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) -DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-offset", VECTOR2, SHADOW_OFFSET ) -DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-color", VECTOR4, SHADOW_COLOR ) - +DALI_PROPERTY_REGISTRATION( TextLabel, "text-color", VECTOR4, TEXT_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-offset", VECTOR2, SHADOW_OFFSET ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-color", VECTOR4, SHADOW_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-enabled", BOOLEAN, UNDERLINE_ENABLED ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-color", VECTOR4, UNDERLINE_COLOR ) DALI_TYPE_REGISTRATION_END() } // namespace @@ -220,7 +222,22 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr } break; } - case Toolkit::TextLabel::Property::SHADOW_OFFSET: + + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + Vector4 textColor = value.Get< Vector4 >(); + if ( impl.mController->GetTextColor() != textColor ) + { + impl.mController->SetTextColor( textColor ); + impl.RequestTextRelayout(); + } + } + break; + } + + case Toolkit::TextLabel::Property::SHADOW_OFFSET: { if( impl.mController ) { @@ -246,6 +263,32 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr } break; } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if( impl.mController ) + { + Vector4 color = value.Get< Vector4 >(); + if ( impl.mController->GetUnderlineColor() != color ) + { + impl.mController->SetUnderlineColor( color ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if( impl.mController ) + { + bool enabled = value.Get< bool >(); + if ( impl.mController->IsUnderlineEnabled() != enabled ) + { + impl.mController->SetUnderlineEnabled( enabled ); + impl.RequestTextRelayout(); + } + } + break; + } } } } @@ -304,7 +347,15 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde } break; } - case Toolkit::TextLabel::Property::SHADOW_OFFSET: + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetTextColor(); + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_OFFSET: { if ( impl.mController ) { @@ -320,6 +371,22 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde } break; } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetUnderlineColor(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if ( impl.mController ) + { + value = impl.mController->IsUnderlineEnabled(); + } + break; + } } } diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp index 03091e5..16fdc8a 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp @@ -108,6 +108,11 @@ void AtlasGlyphManager::Cached( Text::FontId fontId, slot.mImageId = 0; } +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + return mAtlasManager.GetAtlasSize( atlasId ); +} + void AtlasGlyphManager::SetNewAtlasSize( const Vector2& size, const Vector2& blockSize ) { diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h index 868add6..5068426 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h @@ -93,6 +93,11 @@ public: Dali::Toolkit::AtlasManager::AtlasSlot& slot ); /** + * @copydoc Toolkit::AtlasGlyphManager::GetAtlasSize + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** * @copydoc Toolkit::AtlasGlyphManager::SetNewAtlasSize */ void SetNewAtlasSize( const Vector2& size, diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp index 275836c..d46ef18 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp @@ -104,6 +104,11 @@ void AtlasGlyphManager::SetNewAtlasSize( const Vector2& size, GetImplementation(*this).SetNewAtlasSize( size, blockSize ); } +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + return GetImplementation(*this).GetAtlasSize( atlasId ); +} + void AtlasGlyphManager::Remove( uint32_t imageId ) { GetImplementation(*this).Remove( imageId ); diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h index 6a53481..cbfa754 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h @@ -111,6 +111,15 @@ public: AtlasManager::AtlasSlot& slot ); /** + * @brief Retrieve the size of an atlas + * + * @param[in] atlasId Id of the atlas to interrogate + * + * @return The pixel size of the atlas + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** * @brief Set the Atlas size and block size for subsequent atlas generation * * @param[in] size size of the atlas in pixels 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 63deea2..fda82f4 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -54,9 +54,21 @@ struct AtlasRenderer::Impl : public ConnectionTracker struct MeshRecord { + Vector4 mColor; uint32_t mAtlasId; MeshData mMeshData; FrameBufferImage mBuffer; + bool mIsUnderline; + }; + + struct Extent + { + float mBaseLine; + float mLeft; + float mRight; + float mUnderlinePosition; + float mUnderlineThickness; + uint32_t mMeshRecordIndex; }; struct AtlasRecord @@ -79,19 +91,30 @@ struct AtlasRenderer::Impl : public ConnectionTracker mBasicShader = BasicShader::New(); mBgraShader = BgraShader::New(); mBasicShadowShader = BasicShadowShader::New(); + + mFace.reserve( 6u ); + mFace.push_back( 0 ); mFace.push_back( 2u ); mFace.push_back( 1u ); + mFace.push_back( 1u ); mFace.push_back( 2u ); mFace.push_back( 3u ); } void AddGlyphs( const std::vector& positions, const Vector& glyphs, + const Vector4& textColor, const Vector2& shadowOffset, - const Vector4& shadowColor ) + const Vector4& shadowColor, + float underlineEnabled, + const Vector4& underlineColor ) { AtlasManager::AtlasSlot slot; std::vector< MeshRecord > meshContainer; + Vector< Extent > extents; + + float currentUnderlinePosition = 0.0f; + float currentUnderlineThickness = 0.0f; FontId lastFontId = 0; Style style = STYLE_NORMAL; - if ( shadowOffset.x > 0.0f || shadowOffset.y > 0.0f ) + if ( shadowOffset.x != 0.0f || shadowOffset.y != 0.0f ) { style = STYLE_DROP_SHADOW; } @@ -111,6 +134,22 @@ struct AtlasRenderer::Impl : public ConnectionTracker // No operation for white space if ( glyph.width && glyph.height ) { + // Are we still using the same fontId as previous + if ( glyph.fontId != lastFontId ) + { + // We need to fetch fresh font underline metrics + FontMetrics fontMetrics; + mFontClient.GetFontMetrics( glyph.fontId, fontMetrics ); + currentUnderlinePosition = fontMetrics.underlinePosition; + currentUnderlineThickness = fontMetrics.underlineThickness; + + // Ensure that an underline is at least 1 pixel high + if ( currentUnderlineThickness < 1.0f ) + { + currentUnderlineThickness = 1.0f; + } + } + Vector2 position = positions[ i ]; MeshData newMeshData; mGlyphManager.Cached( glyph.fontId, glyph.index, slot ); @@ -151,25 +190,46 @@ struct AtlasRenderer::Impl : public ConnectionTracker } } // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) - StitchTextMesh( meshContainer, newMeshData, slot ); + StitchTextMesh( meshContainer, + newMeshData, + extents, + textColor, + position.y + glyph.yBearing, + currentUnderlinePosition, + currentUnderlineThickness, + slot ); } } + if ( underlineEnabled ) + { + // Check to see if any of the text needs an underline + GenerateUnderlines( meshContainer, extents, underlineColor, textColor ); + } + // For each MeshData object, create a mesh actor and add to the renderable actor if ( meshContainer.size() ) { - for ( uint32_t i = 0; i < meshContainer.size(); ++i ) + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt ) { - MeshActor actor = MeshActor::New( Mesh::New( meshContainer[ i ].mMeshData ) ); - actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + MeshActor actor = MeshActor::New( Mesh::New( mIt->mMeshData ) ); + actor.SetColor( mIt->mColor ); + if ( mIt->mIsUnderline ) + { + actor.SetColorMode( USE_OWN_COLOR ); + } + else + { + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + } // Check to see what pixel format the shader should be - if ( mGlyphManager.GetPixelFormat( meshContainer[ i ].mAtlasId ) == Pixel::L8 ) + if ( mGlyphManager.GetPixelFormat( mIt->mAtlasId ) == Pixel::L8 ) { // Create an effect if necessary if ( style == STYLE_DROP_SHADOW ) { - actor.Add( GenerateEffect( meshContainer[ i ], shadowOffset, shadowColor ) ); + actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) ); } actor.SetShaderEffect( mBasicShader ); } @@ -178,7 +238,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker actor.SetShaderEffect( mBgraShader ); } - if ( i ) + if ( mActor ) { mActor.Add( actor ); } @@ -212,17 +272,36 @@ struct AtlasRenderer::Impl : public ConnectionTracker void StitchTextMesh( std::vector< MeshRecord >& meshContainer, MeshData& newMeshData, + Vector< Extent >& extents, + const Vector4& color, + float baseLine, + float underlinePosition, + float underlineThickness, AtlasManager::AtlasSlot& slot ) { if ( slot.mImageId ) { + MeshData::VertexContainer verts = newMeshData.GetVertices(); + float left = verts[ 0 ].x; + float right = verts[ 1 ].x; + // Check to see if there's a mesh data object that references the same atlas ? - for ( uint32_t i = 0; i < meshContainer.size(); ++i ) + uint32_t index = 0; + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt, ++index ) { - if ( slot.mAtlasId == meshContainer[ i ].mAtlasId ) + if ( slot.mAtlasId == mIt->mAtlasId ) { - // Stitch the mesh to the existing mesh - mGlyphManager.StitchMesh( meshContainer[ i ].mMeshData, newMeshData ); + // Stitch the mesh to the existing mesh and adjust any extents + mGlyphManager.StitchMesh( mIt->mMeshData, newMeshData ); + AdjustExtents( extents, + meshContainer, + index, + color, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); return; } } @@ -231,7 +310,73 @@ struct AtlasRenderer::Impl : public ConnectionTracker MeshRecord meshRecord; meshRecord.mAtlasId = slot.mAtlasId; meshRecord.mMeshData = newMeshData; + meshRecord.mColor = color; + meshRecord.mIsUnderline = false; meshContainer.push_back( meshRecord ); + + // Adjust extents for this new meshrecord + AdjustExtents( extents, + meshContainer, + meshContainer.size() - 1u, + color, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + + } + } + + void AdjustExtents( Vector< Extent >& extents, + std::vector< MeshRecord>& meshRecords, + uint32_t index, + const Vector4& color, + float left, + float right, + float baseLine, + float underlinePosition, + float underlineThickness ) + { + bool foundExtent = false; + for ( Vector< Extent >::Iterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + if ( Equals( baseLine, eIt->mBaseLine ) ) + { + // If we've found an extent with the same color then we don't need to create a new extent + if ( color == meshRecords[ index ].mColor ) + { + foundExtent = true; + if ( left < eIt->mLeft ) + { + eIt->mLeft = left; + } + if ( right > eIt->mRight ) + { + eIt->mRight = right; + } + } + // Font metrics use negative values for lower underline positions + if ( underlinePosition < eIt->mUnderlinePosition ) + { + eIt->mUnderlinePosition = underlinePosition; + } + if ( underlineThickness > eIt->mUnderlineThickness ) + { + eIt->mUnderlineThickness = underlineThickness; + } + } + } + if ( !foundExtent ) + { + Extent extent; + extent.mLeft = left; + extent.mRight = right; + extent.mBaseLine = baseLine; + extent.mUnderlinePosition = underlinePosition; + extent.mUnderlineThickness = underlineThickness; + extent.mMeshRecordIndex = index; + extents.PushBack( extent ); } } @@ -286,14 +431,77 @@ struct AtlasRenderer::Impl : public ConnectionTracker } } - MeshActor GenerateEffect( MeshRecord& meshRecord, + void GenerateUnderlines( std::vector< MeshRecord>& meshRecords, + Vector< Extent >& extents, + const Vector4& underlineColor, + const Vector4& textColor ) + { + MeshData newMeshData; + const float zero = 0.0f; + const float half = 0.5f; + + for ( Vector< Extent >::ConstIterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + MeshData::VertexContainer newVerts; + newVerts.reserve( 4u ); + uint32_t index = eIt->mMeshRecordIndex; + Vector2 uv = mGlyphManager.GetAtlasSize( meshRecords[ index ].mAtlasId ); + + // Make sure we don't hit texture edge for single pixel texture ( filled pixel is in top left of every atlas ) + float u = half / uv.x; + float v = half / uv.y; + float thickness = eIt->mUnderlineThickness; + float baseLine = eIt->mBaseLine - eIt->mUnderlinePosition - ( thickness * 0.5f ); + float tlx = eIt->mLeft; + float brx = eIt->mRight; + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine, zero ), + Vector2( zero, zero ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine, zero ), + Vector2( u, zero ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine + thickness, zero ), + Vector2( zero, v ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine + thickness, zero ), + Vector2( u, v ), + Vector3( zero, zero, zero ) ) ); + + newMeshData.SetVertices( newVerts ); + newMeshData.SetFaceIndices( mFace ); + + if ( underlineColor == textColor ) + { + mGlyphManager.StitchMesh( meshRecords[ index ].mMeshData, newMeshData ); + } + else + { + MeshRecord record; + newMeshData.SetMaterial( meshRecords[ index ].mMeshData.GetMaterial() ); + newMeshData.SetHasNormals( true ); + newMeshData.SetHasColor( false ); + newMeshData.SetHasTextureCoords( true ); + record.mMeshData = newMeshData; + record.mAtlasId = meshRecords[ index ].mAtlasId; + record.mColor = underlineColor; + record.mIsUnderline = true; + meshRecords.push_back( record ); + } + } + } + + MeshActor GenerateShadow( MeshRecord& meshRecord, const Vector2& shadowOffset, const Vector4& shadowColor ) { // Scan vertex buffer to determine width and height of effect buffer needed MeshData::VertexContainer verts = meshRecord.mMeshData.GetVertices(); - const float zero = 0.0f; const float one = 1.0f; + const float zero = 0.0f; float tlx = verts[ 0 ].x; float tly = verts[ 0 ].y; float brx = zero; @@ -325,7 +533,6 @@ struct AtlasRenderer::Impl : public ConnectionTracker float divHeight = 2.0f / height; // Create a buffer to render to - // TODO bloom style filter from this buffer meshRecord.mBuffer = FrameBufferImage::New( width, height ); // Create a mesh actor to contain the post-effect render @@ -348,15 +555,12 @@ struct AtlasRenderer::Impl : public ConnectionTracker Vector2( one, one ), Vector3( zero, zero, zero ) ) ); - face.push_back( 0 ); face.push_back( 2u ); face.push_back( 1u ); - face.push_back( 1u ); face.push_back( 2u ); face.push_back( 3u ); - MeshData meshData; Material newMaterial = Material::New("effect buffer"); newMaterial.SetDiffuseTexture( meshRecord.mBuffer ); meshData.SetMaterial( newMaterial ); meshData.SetVertices( vertices ); - meshData.SetFaceIndices( face ); + meshData.SetFaceIndices( mFace ); meshData.SetHasNormals( true ); meshData.SetHasColor( false ); meshData.SetHasTextureCoords( true ); @@ -364,7 +568,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); actor.SetShaderEffect( mBgraShader ); actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); - actor.SetSortModifier( one ); // force behind main text + actor.SetSortModifier( 0.1f ); // force behind main text // Create a sub actor to render once with normalized vertex positions MeshData newMeshData; @@ -441,6 +645,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker ShaderEffect mBgraShader; ///> Shader used to render BGRA glyphs ShaderEffect mBasicShadowShader; ///> Shader used to render drop shadow into buffer std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas + std::vector< MeshData::FaceIndex > mFace; ///> Face indices for a quad }; Text::RendererPtr AtlasRenderer::New() @@ -467,8 +672,11 @@ RenderableActor AtlasRenderer::Render( Text::ViewInterface& view ) view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); mImpl->AddGlyphs( positions, glyphs, + view.GetTextColor(), view.GetShadowOffset(), - view.GetShadowColor() ); + view.GetShadowColor(), + view.IsUnderlineEnabled(), + view.GetUnderlineColor() ); } return mImpl->mActor; } @@ -482,4 +690,4 @@ AtlasRenderer::AtlasRenderer() AtlasRenderer::~AtlasRenderer() { delete mImpl; -} +} \ No newline at end of file diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 219d8e5..15d79a1 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -651,9 +651,11 @@ struct Controller::Impl mView.SetVisualModel( mVisualModel ); - // Set the shadow properties to default + // Set the text properties to default + mVisualModel->SetTextColor( Color::WHITE ); mVisualModel->SetShadowOffset( Vector2::ZERO ); mVisualModel->SetShadowColor( Vector4::ZERO ); + mVisualModel->SetUnderlineEnabled( false ); } ~Impl() @@ -849,6 +851,11 @@ void Controller::GetDefaultFonts( Vector& fonts, Length numberOfCharact } } +const Vector4& Controller::GetTextColor() const +{ + return mImpl->mVisualModel->GetTextColor(); +} + const Vector2& Controller::GetShadowOffset() const { return mImpl->mVisualModel->GetShadowOffset(); @@ -859,6 +866,21 @@ const Vector4& Controller::GetShadowColor() const return mImpl->mVisualModel->GetShadowColor(); } +const Vector4& Controller::GetUnderlineColor() const +{ + return mImpl->mVisualModel->GetUnderlineColor(); +} + +bool Controller::IsUnderlineEnabled() const +{ + return mImpl->mVisualModel->IsUnderlineEnabled(); +} + +void Controller::SetTextColor( const Vector4& textColor ) +{ + mImpl->mVisualModel->SetTextColor( textColor ); +} + void Controller::SetShadowOffset( const Vector2& shadowOffset ) { mImpl->mVisualModel->SetShadowOffset( shadowOffset ); @@ -869,6 +891,16 @@ void Controller::SetShadowColor( const Vector4& shadowColor ) mImpl->mVisualModel->SetShadowColor( shadowColor ); } +void Controller::SetUnderlineColor( const Vector4& color ) +{ + mImpl->mVisualModel->SetUnderlineColor( color ); +} + +void Controller::SetUnderlineEnabled( bool enabled ) +{ + mImpl->mVisualModel->SetUnderlineEnabled( enabled ); +} + void Controller::EnableTextInput( DecoratorPtr decorator ) { if( !mImpl->mTextInput ) diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index ddb1051..129459b 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -173,32 +173,74 @@ public: void GetDefaultFonts( Dali::Vector& fonts, Length numberOfCharacters ); /** + * @brief Set the text color + * + * @param textColor The text color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text color + * + * @return The text color + */ + const Vector4& GetTextColor() const; + + /** * @brief Set the shadow offset. * * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. */ - void SetShadowOffset( const Vector2& shadowOffset ); + void SetShadowOffset( const Vector2& shadowOffset ); /** * @brief Retrieve the shadow offset. * * @return The shadow offset. */ - const Vector2& GetShadowOffset() const; + const Vector2& GetShadowOffset() const; /** * @brief Set the shadow color. * * @param[in] shadowColor The shadow color. */ - void SetShadowColor( const Vector4& shadowColor ); + void SetShadowColor( const Vector4& shadowColor ); /** * @brief Retrieve the shadow color. * * @return The shadow color. */ - const Vector4& GetShadowColor() const; + const Vector4& GetShadowColor() const; + + /** + * @brief Set the underline color. + * + * @param[in] color color of underline. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieve the underline color. + * + * @return The underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Set the underline enabled flag. + * + * @param[in] enabled The underline enabled flag. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return The underline state. + */ + bool IsUnderlineEnabled() const; /** * @brief Called to enable text input. diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 4220b66..116ad50 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -89,7 +89,14 @@ public: Length numberOfGlyphs ) const = 0; /** - * @brief Retrieves the shadow offset, 0,0 indicates no shadow. + * @brief Retrieves the text color + * + * @return The text color + */ + virtual const Vector4& GetTextColor() const = 0; + + /** + * @brief Retrieves the shadow offset, 0 indicates no shadow. * * @return The shadow offset. */ @@ -101,6 +108,21 @@ public: * @return The shadow color. */ virtual const Vector4& GetShadowColor() const = 0; + + /** + * @brief Retrieves the underline color. + * + * @return The underline color. + */ + virtual const Vector4& GetUnderlineColor() const = 0; + + /** + * @brief Returns whether is underline is enabled or not. + * + * @return The underline state. + */ + virtual bool IsUnderlineEnabled() const = 0; + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index bfe3f70..b0825f6 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -51,6 +51,16 @@ void View::SetVisualModel( VisualModelPtr visualModel ) mImpl->mVisualModel = visualModel; } +const Vector4& View::GetTextColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetTextColor(); + } + return Vector4::ZERO; +} + const Vector2& View::GetShadowOffset() const { if ( mImpl->mVisualModel ) @@ -71,6 +81,26 @@ const Vector4& View::GetShadowColor() const return Vector4::ZERO; } +const Vector4& View::GetUnderlineColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetUnderlineColor(); + } + return Vector4::ZERO; +} + +bool View::IsUnderlineEnabled() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.IsUnderlineEnabled(); + } + return false; +} + Length View::GetNumberOfGlyphs() const { if( mImpl->mVisualModel ) diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index ba4d3bd..b9bd7fc 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -77,6 +77,11 @@ public: Length numberOfGlyphs ) const; /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor() + */ + virtual const Vector4& GetTextColor() const; + + /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetShadowOffset() */ virtual const Vector2& GetShadowOffset() const; @@ -86,6 +91,16 @@ public: */ virtual const Vector4& GetShadowColor() const; + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineColor() + */ + virtual const Vector4& GetUnderlineColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::IsUnderlineEnabled() + */ + virtual bool IsUnderlineEnabled() const; + private: // Undefined diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 0c056ad..ec94ecc 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -370,6 +370,16 @@ const Vector2& VisualModel::GetActualSize() const return mActualSize; } +void VisualModel::SetTextColor( const Vector4& textColor ) +{ + mTextColor = textColor; + + if ( !mUnderlineColorSet ) + { + mUnderlineColor = textColor; + } +} + void VisualModel::SetShadowOffset( const Vector2& shadowOffset ) { mShadowOffset = shadowOffset; @@ -380,6 +390,22 @@ void VisualModel::SetShadowColor( const Vector4& shadowColor ) mShadowColor = shadowColor; } +void VisualModel::SetUnderlineColor( const Vector4& color ) +{ + mUnderlineColor = color; + mUnderlineColorSet = true; +} + +void VisualModel::SetUnderlineEnabled( bool enabled ) +{ + mUnderlineEnabled = enabled; +} + +const Vector4& VisualModel::GetTextColor() const +{ + return mTextColor; +} + const Vector2& VisualModel::GetShadowOffset() const { return mShadowOffset; @@ -390,12 +416,22 @@ const Vector4& VisualModel::GetShadowColor() const return mShadowColor; } +const Vector4& VisualModel::GetUnderlineColor() const +{ + return mUnderlineColor; +} + +bool VisualModel::IsUnderlineEnabled() const +{ + return mUnderlineEnabled; +} VisualModel::~VisualModel() { } VisualModel::VisualModel() +: mUnderlineColorSet( false ) { } diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 9deaea7..c8ea7e9 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -385,6 +385,20 @@ public: const Vector2& GetActualSize() const; /** + * @brief Set the text's color + * + * @param[in] textColor The text's color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text's color + * + * @return The text's color + */ + const Vector4& GetTextColor() const; + + /** * @brief Sets the text's shadow offset. * * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. @@ -412,6 +426,34 @@ public: */ const Vector4& GetShadowColor() const; + /** + * @brief Sets the text's underline color. + * + * @param[in] color The text's underline color. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieves the text's underline color. + * + * @return The text's underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Sets the text underline flag. + * + * @param[in] enabled true if underlined. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return underline state. + */ + bool IsUnderlineEnabled() const; + protected: /** @@ -434,16 +476,20 @@ private: public: - Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. - Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. - Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. - Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. - Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. - Vector mGlyphPositions; ///< For each glyph, the position. - Vector mLines; ///< The laid out lines. - - Vector2 mShadowOffset; ///< Offset for drop shadow, 0.0 indicates no shadow - Vector4 mShadowColor; ///< Color of drop shadow + Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. + Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. + Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. + Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. + Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. + Vector mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. + + Vector4 mTextColor; ///< The text color + Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow + Vector4 mShadowColor; ///< Color of drop shadow + Vector4 mUnderlineColor; ///< Color of underline + bool mUnderlineEnabled:1; ///< Underline enabled flag + bool mUnderlineColorSet:1; ///< Has the underline color been explicitly set? private: diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h index ac64fe6..7ecb200 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -64,9 +64,12 @@ public: POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT MULTI_LINE, ///< name "multi-line", The single-line or multi-line layout option, type BOOLEAN HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", The line horizontal alignment, type STRING, values "BEGIN", "CENTER", "END" - VERTICAL_ALIGNMENT, ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + VERTICAL_ALIGNMENT, ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + TEXT_COLOR, ///< name "text-color", The text color, type VECTOR4 SHADOW_OFFSET, ///< name "shadow-offset", The drop shadow offset 0 indicates no shadow, type VECTOR2 - SHADOW_COLOR, ///< name "shadow-color", The color of a drop shadow , type VECTOR4 + SHADOW_COLOR, ///< name "shadow-color", The color of a drop shadow, type VECTOR4 + UNDERLINE_ENABLED, ///< name "underline-enabled", The underline enabled flag type BOOLEAN + UNDERLINE_COLOR, ///< name "underline-color", The color of the underline type VECTOR4 }; };