X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Frendering%2Fatlas%2Ftext-atlas-renderer.cpp;h=5ba07cee2b7c76670238a5d72a9fbcd2b347cf49;hb=d00a250741411c386d988e7ac34525cf94a1918e;hp=55925892cb883e33f20d7505e94a5dffad74beab;hpb=62fdadefe148bf9a5bc7557be6ab001ea1e0a453;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git 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 5592589..5ba07ce 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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,13 +19,13 @@ #include // EXTERNAL INCLUDES -#include -#include -#include +#include +#include #include +#include // INTERNAL INCLUDES -#include +#include #include #include #include @@ -38,7 +38,7 @@ using namespace Dali::Toolkit::Text; namespace { #if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING"); + Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_RENDERING"); #endif const float ZERO( 0.0f ); @@ -59,12 +59,10 @@ struct AtlasRenderer::Impl struct MeshRecord { MeshRecord() - : mColor( Color::BLACK ), - mAtlasId( 0 ) + : mAtlasId( 0u ) { } - Vector4 mColor; uint32_t mAtlasId; AtlasManager::Mesh2D mMesh; FrameBufferImage mBuffer; @@ -82,7 +80,7 @@ struct AtlasRenderer::Impl mRight( 0.0f ), mUnderlinePosition( 0.0f ), mUnderlineThickness( 0.0f ), - mMeshRecordIndex( 0 ) + mMeshRecordIndex( 0u ) { } @@ -142,7 +140,7 @@ struct AtlasRenderer::Impl mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2; mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2; - mQuadIndexFormat[ "indices" ] = Property::INTEGER; + mQuadVertexFormat[ "aColor" ] = Property::VECTOR4; } bool IsGlyphUnderlined( GlyphIndex index, @@ -167,6 +165,9 @@ struct AtlasRenderer::Impl void AddGlyphs( Text::ViewInterface& view, const Vector& positions, const Vector& glyphs, + const Vector4& defaultColor, + const Vector4* const colorsBuffer, + const ColorIndex* const colorIndicesBuffer, int depth ) { AtlasManager::AtlasSlot slot; @@ -175,15 +176,16 @@ struct AtlasRenderer::Impl TextCacheEntry textCacheEntry; mDepth = depth; - const Vector2& actorSize( view.GetControlSize() ); - const Vector2 halfActorSize( actorSize * 0.5f ); - const Vector4& textColor( view.GetTextColor() ); + const Vector2& textSize( view.GetLayoutSize() ); + const Vector2 halfTextSize( textSize * 0.5f ); const Vector2& shadowOffset( view.GetShadowOffset() ); const Vector4& shadowColor( view.GetShadowColor() ); const bool underlineEnabled( view.IsUnderlineEnabled() ); const Vector4& underlineColor( view.GetUnderlineColor() ); const float underlineHeight( view.GetUnderlineHeight() ); + const bool useDefaultColor = ( NULL == colorsBuffer ); + // Get the underline runs. const Length numberOfUnderlineRuns = view.GetNumberOfUnderlineRuns(); Vector underlineRuns; @@ -221,10 +223,10 @@ struct AtlasRenderer::Impl thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; // No operation for white space - if ( glyph.width && glyph.height ) + if( glyph.width && glyph.height ) { // Are we still using the same fontId as previous - if ( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) ) + if( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) ) { // We need to fetch fresh font underline metrics FontMetrics fontMetrics; @@ -248,10 +250,11 @@ struct AtlasRenderer::Impl } // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font - if ( currentUnderlinePosition > descender ) + if( currentUnderlinePosition > descender ) { currentUnderlinePosition = descender; } + if( fabsf( currentUnderlinePosition ) < Math::MACHINE_EPSILON_1000 ) { // Move offset down by one ( EFL behavior ) @@ -261,47 +264,54 @@ struct AtlasRenderer::Impl lastUnderlinedFontId = glyph.fontId; } // underline - if ( !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ) ) + if( !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ) ) { // Select correct size for new atlas if needed....? - if ( lastFontId != glyph.fontId ) + if( lastFontId != glyph.fontId ) { - for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + uint32_t index = 0u; + for( std::vector::const_iterator it = mBlockSizes.begin(), + endIt = mBlockSizes.end(); + it != endIt; + ++it, ++index ) { - if ( mBlockSizes[ j ].mFontId == glyph.fontId ) + const MaxBlockSize& blockSize = *it; + if( blockSize.mFontId == glyph.fontId ) { - currentBlockSize = j; + currentBlockSize = index; mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, DEFAULT_ATLAS_HEIGHT, - mBlockSizes[ j ].mNeededBlockWidth, - mBlockSizes[ j ].mNeededBlockHeight ); + blockSize.mNeededBlockWidth, + blockSize.mNeededBlockHeight ); } } } // Create a new image for the glyph - BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index ); - if ( bitmap ) + PixelData bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index ); + if( bitmap ) { + MaxBlockSize& blockSize = mBlockSizes[currentBlockSize]; + // Ensure that the next image will fit into the current block size bool setSize = false; - if ( bitmap.GetWidth() > mBlockSizes[ currentBlockSize ].mNeededBlockWidth ) + if( bitmap.GetWidth() > blockSize.mNeededBlockWidth ) { setSize = true; - mBlockSizes[ currentBlockSize ].mNeededBlockWidth = bitmap.GetWidth(); + blockSize.mNeededBlockWidth = bitmap.GetWidth(); } - if ( bitmap.GetHeight() > mBlockSizes[ currentBlockSize ].mNeededBlockHeight ) + if( bitmap.GetHeight() > blockSize.mNeededBlockHeight ) { setSize = true; - mBlockSizes[ currentBlockSize ].mNeededBlockHeight = bitmap.GetHeight(); + blockSize.mNeededBlockHeight = bitmap.GetHeight(); } - if ( setSize ) + if( setSize ) { mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, DEFAULT_ATLAS_HEIGHT, - mBlockSizes[ currentBlockSize ].mNeededBlockWidth, - mBlockSizes[ currentBlockSize ].mNeededBlockHeight ); + blockSize.mNeededBlockWidth, + blockSize.mNeededBlockHeight ); } // Locate a new slot for our glyph @@ -315,7 +325,7 @@ struct AtlasRenderer::Impl } // Move the origin (0,0) of the mesh to the center of the actor - Vector2 position = *( positionsBuffer + i ) - halfActorSize; + const Vector2 position = *( positionsBuffer + i ) - halfTextSize; // Generate mesh data for this quad, plugging in our supplied position AtlasManager::Mesh2D newMesh; @@ -325,21 +335,41 @@ struct AtlasRenderer::Impl textCacheEntry.mIndex = glyph.index; newTextCache.PushBack( textCacheEntry ); + AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin(); + // Adjust the vertices if the fixed-size font should be down-scaled if( glyph.scaleFactor > 0 ) { - for( unsigned int i=0; i::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt ) + if( !mActor ) { - Actor actor = CreateMeshActor( *mIt, actorSize ); + // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues. + mActor = Actor::New(); + mActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mActor.SetSize( textSize ); + } + + for( std::vector< MeshRecord >::iterator it = meshContainer.begin(), + endIt = meshContainer.end(); + it != endIt; ++it ) + { + MeshRecord& meshRecord = *it; + + Actor actor = CreateMeshActor( meshRecord, textSize ); + + // Whether the actor has renderers. + const bool hasRenderer = actor.GetRendererCount() > 0u; // Create an effect if necessary - if ( style == STYLE_DROP_SHADOW ) + if( hasRenderer && + ( style == STYLE_DROP_SHADOW ) ) { - // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues. - Actor containerActor = Actor::New(); - containerActor.SetParentOrigin( ParentOrigin::CENTER ); - containerActor.SetSize( actorSize ); + // Change the color of the vertices. + for( Vector::Iterator vIt = meshRecord.mMesh.mVertices.Begin(), + vEndIt = meshRecord.mMesh.mVertices.End(); + vIt != vEndIt; + ++vIt ) + { + AtlasManager::Vertex2D& vertex = *vIt; - Actor shadowActor = Actor::New(); + vertex.mColor = shadowColor; + } + + Actor shadowActor = CreateMeshActor( meshRecord, textSize ); #if defined(DEBUG_ENABLED) shadowActor.SetName( "Text Shadow renderable actor" ); #endif // Offset shadow in x and y shadowActor.RegisterProperty("uOffset", shadowOffset ); - if ( actor.GetRendererCount() ) - { - Dali::Renderer renderer( actor.GetRendererAt( 0 ) ); - Geometry geometry = renderer.GetGeometry(); - Material material = renderer.GetMaterial(); - - Dali::Renderer shadowRenderer = Dali::Renderer::New( geometry, material ); - shadowRenderer.SetDepthIndex( renderer.GetDepthIndex() - 1 ); - shadowActor.AddRenderer( shadowRenderer ); - shadowActor.SetParentOrigin( ParentOrigin::CENTER ); - shadowActor.SetSize( actorSize ); - shadowActor.SetColor( shadowColor ); - containerActor.Add( shadowActor ); - containerActor.Add( actor ); - actor = containerActor; - } + Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) ); + int depthIndex = renderer.GetProperty(Dali::Renderer::Property::DEPTH_INDEX); + renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 ); + mActor.Add( shadowActor ); } - if( mActor ) + if( hasRenderer ) { mActor.Add( actor ); } - else - { - mActor = actor; - } } } #if defined(DEBUG_ENABLED) @@ -417,7 +454,7 @@ struct AtlasRenderer::Impl DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%s\n", metrics.mVerboseGlyphCounts.c_str() ); - for ( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i ) + for( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", i + 1, i > 8 ? "" : " ", @@ -434,7 +471,7 @@ struct AtlasRenderer::Impl void RemoveText() { - for ( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter ) + for( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter ) { mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, -1/*decrement*/ ); } @@ -443,26 +480,29 @@ struct AtlasRenderer::Impl Actor CreateMeshActor( const MeshRecord& meshRecord, const Vector2& actorSize ) { - PropertyBuffer quadVertices = PropertyBuffer::New( mQuadVertexFormat, meshRecord.mMesh.mVertices.Size() ); - PropertyBuffer quadIndices = PropertyBuffer::New( mQuadIndexFormat, meshRecord.mMesh.mIndices.Size() ); - quadVertices.SetData( const_cast< AtlasManager::Vertex2D* >( &meshRecord.mMesh.mVertices[ 0 ] ) ); - quadIndices.SetData( const_cast< unsigned int* >( &meshRecord.mMesh.mIndices[ 0 ] ) ); + PropertyBuffer quadVertices = PropertyBuffer::New( mQuadVertexFormat ); + quadVertices.SetData( const_cast< AtlasManager::Vertex2D* >( &meshRecord.mMesh.mVertices[ 0 ] ), meshRecord.mMesh.mVertices.Size() ); Geometry quadGeometry = Geometry::New(); quadGeometry.AddVertexBuffer( quadVertices ); - quadGeometry.SetIndexBuffer( quadIndices ); - - Material material = mGlyphManager.GetMaterial( meshRecord.mAtlasId ); - Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material ); - renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth ); + quadGeometry.SetIndexBuffer( &meshRecord.mMesh.mIndices[0], meshRecord.mMesh.mIndices.Size() ); + + TextureSet textureSet( mGlyphManager.GetTextures( meshRecord.mAtlasId ) ); + Shader shader( mGlyphManager.GetShader( meshRecord.mAtlasId ) ); + Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, shader ); + renderer.SetTextures( textureSet ); + renderer.SetProperty( Dali::Renderer::Property::BLEND_MODE, BlendMode::ON ); + renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + mDepth ); Actor actor = Actor::New(); #if defined(DEBUG_ENABLED) actor.SetName( "Text renderable actor" ); #endif actor.AddRenderer( renderer ); - actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned + + // Keep all of the origins aligned + actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); actor.SetSize( actorSize ); - actor.SetColor( meshRecord.mColor ); actor.RegisterProperty("uOffset", Vector2::ZERO ); return actor; } @@ -470,7 +510,6 @@ struct AtlasRenderer::Impl void StitchTextMesh( std::vector< MeshRecord >& meshContainer, AtlasManager::Mesh2D& newMesh, Vector< Extent >& extents, - const Vector4& color, float baseLine, bool underlineGlyph, float underlinePosition, @@ -489,7 +528,7 @@ struct AtlasRenderer::Impl mIt != mEndIt; ++mIt, ++index ) { - if ( slot.mAtlasId == mIt->mAtlasId && color == mIt->mColor ) + if( slot.mAtlasId == mIt->mAtlasId ) { // Append the mesh to the existing mesh and adjust any extents Toolkit::Internal::AtlasMeshFactory::AppendMesh( mIt->mMesh, newMesh ); @@ -514,7 +553,6 @@ struct AtlasRenderer::Impl MeshRecord meshRecord; meshRecord.mAtlasId = slot.mAtlasId; meshRecord.mMesh = newMesh; - meshRecord.mColor = color; meshContainer.push_back( meshRecord ); if( underlineGlyph ) @@ -584,25 +622,36 @@ struct AtlasRenderer::Impl void CalculateBlocksSize( const Vector& glyphs ) { - MaxBlockSize maxBlockSize; - for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + for( Vector::ConstIterator glyphIt = glyphs.Begin(), + glyphEndIt = glyphs.End(); + glyphIt != glyphEndIt; + ++glyphIt ) { - FontId fontId = glyphs[ i ].fontId; + const FontId fontId = (*glyphIt).fontId; bool foundFont = false; - for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + + for( std::vector< MaxBlockSize >::const_iterator blockIt = mBlockSizes.begin(), + blockEndIt = mBlockSizes.end(); + blockIt != blockEndIt; + ++blockIt ) { - if ( mBlockSizes[ j ].mFontId == fontId ) + if( (*blockIt).mFontId == fontId ) { foundFont = true; + break; } } + if ( !foundFont ) { FontMetrics fontMetrics; mFontClient.GetFontMetrics( fontId, fontMetrics ); + + MaxBlockSize maxBlockSize; maxBlockSize.mNeededBlockWidth = static_cast< uint32_t >( fontMetrics.height ); - maxBlockSize.mNeededBlockHeight = static_cast< uint32_t >( fontMetrics.height ); + maxBlockSize.mNeededBlockHeight = maxBlockSize.mNeededBlockWidth; maxBlockSize.mFontId = fontId; + mBlockSizes.push_back( maxBlockSize ); } } @@ -610,8 +659,7 @@ struct AtlasRenderer::Impl void GenerateUnderlines( std::vector< MeshRecord >& meshRecords, Vector< Extent >& extents, - const Vector4& underlineColor, - const Vector4& textColor ) + const Vector4& underlineColor ) { AtlasManager::Mesh2D newMesh; unsigned short faceIndex = 0; @@ -636,22 +684,26 @@ struct AtlasRenderer::Impl vert.mPosition.y = baseLine; vert.mTexCoords.x = ZERO; vert.mTexCoords.y = ZERO; + vert.mColor = underlineColor; newMesh.mVertices.PushBack( vert ); vert.mPosition.x = brx; vert.mPosition.y = baseLine; vert.mTexCoords.x = u; + vert.mColor = underlineColor; newMesh.mVertices.PushBack( vert ); vert.mPosition.x = tlx; vert.mPosition.y = baseLine + thickness; vert.mTexCoords.x = ZERO; vert.mTexCoords.y = v; + vert.mColor = underlineColor; newMesh.mVertices.PushBack( vert ); vert.mPosition.x = brx; vert.mPosition.y = baseLine + thickness; vert.mTexCoords.x = u; + vert.mColor = underlineColor; newMesh.mVertices.PushBack( vert ); // Six indices in counter clockwise winding @@ -663,18 +715,7 @@ struct AtlasRenderer::Impl newMesh.mIndices.PushBack( faceIndex + 1u ); faceIndex += 4; - if ( underlineColor == textColor ) - { - Toolkit::Internal::AtlasMeshFactory::AppendMesh( meshRecords[ index ].mMesh, newMesh ); - } - else - { - MeshRecord record; - record.mMesh = newMesh; - record.mAtlasId = meshRecords[ index ].mAtlasId; - record.mColor = underlineColor; - meshRecords.push_back( record ); - } + Toolkit::Internal::AtlasMeshFactory::AppendMesh( meshRecords[ index ].mMesh, newMesh ); } } @@ -684,7 +725,6 @@ struct AtlasRenderer::Impl std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas Vector< TextCacheEntry > mTextCache; ///> Caches data from previous render Property::Map mQuadVertexFormat; ///> Describes the vertex format for text - Property::Map mQuadIndexFormat; ///> Describes the index format for text int mDepth; ///> DepthIndex passed by control when connect to stage }; @@ -697,6 +737,8 @@ Text::RendererPtr AtlasRenderer::New() Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth ) { + DALI_LOG_INFO( gLogFilter, Debug::General, "Text::AtlasRenderer::Render()\n" ); + UnparentAndReset( mImpl->mActor ); Length numberOfGlyphs = view.GetNumberOfGlyphs(); @@ -713,13 +755,28 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth ) positions.Begin(), 0u, numberOfGlyphs ); + glyphs.Resize( numberOfGlyphs ); positions.Resize( numberOfGlyphs ); + const Vector4* const colorsBuffer = view.GetColors(); + const ColorIndex* const colorIndicesBuffer = view.GetColorIndices(); + const Vector4& defaultColor = view.GetTextColor(); + mImpl->AddGlyphs( view, positions, glyphs, + defaultColor, + colorsBuffer, + colorIndicesBuffer, depth ); + + /* In the case where AddGlyphs does not create a renderable Actor for example when glyphs are all whitespace create a new Actor. */ + /* This renderable actor is used to position the text, other "decorations" can rely on there always being an Actor regardless of it is whitespace or regular text. */ + if ( !mImpl->mActor ) + { + mImpl->mActor = Actor::New(); + } } return mImpl->mActor;