X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Frendering%2Fatlas%2Ftext-atlas-renderer.cpp;h=b655772532e9d9ab37035e19dc4ca022b2fbe5c5;hp=2e94ce13fdc88fe22c5f9b132278f14ba9f6a0ea;hb=7c53e2bd8999b5a488d6b701b240c708b5341584;hpb=5b3cf0e6742934674bdf62bbe15af00e39eae566 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 2e94ce1..b655772 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -30,6 +30,7 @@ // INTERNAL INCLUDES #include +#include #include #include @@ -72,6 +73,10 @@ struct AtlasRenderer::Impl : public ConnectionTracker FrameBufferImage mBuffer; }; + /** + * brief Struct used to generate the underline mesh. + * There is one Extent per line of text. + */ struct Extent { Extent() @@ -143,8 +148,30 @@ struct AtlasRenderer::Impl : public ConnectionTracker mQuadIndexFormat[ "indices" ] = Property::INTEGER; } + bool IsGlyphUnderlined( GlyphIndex index, + const Vector& underlineRuns ) + { + // TODO: At the moment it works because we always traverse the glyphs starting from the beginning + // and there is only one glyph run! If there are more they should be ordered. + + for( Vector::ConstIterator it = underlineRuns.Begin(), + endIt = underlineRuns.End(); + it != endIt; + ++it ) + { + const GlyphRun& run = *it; + + if( ( run.glyphIndex <= index ) && ( index < run.glyphIndex + run.numberOfGlyphs ) ) + { + return true; + } + } + + return false; + } + void AddGlyphs( Text::ViewInterface& view, - const std::vector& positions, + const Vector& positions, const Vector& glyphs, int depth ) { @@ -155,18 +182,29 @@ struct AtlasRenderer::Impl : public ConnectionTracker mDepth = depth; const Vector2& actorSize( view.GetControlSize() ); - Vector2 halfActorSize( actorSize * 0.5f ); + const Vector2 halfActorSize( actorSize * 0.5f ); const Vector4& textColor( view.GetTextColor() ); const Vector2& shadowOffset( view.GetShadowOffset() ); const Vector4& shadowColor( view.GetShadowColor() ); - bool underlineEnabled( view.IsUnderlineEnabled() ); + const bool underlineEnabled( view.IsUnderlineEnabled() ); const Vector4& underlineColor( view.GetUnderlineColor() ); - float underlineHeight( view.GetUnderlineHeight() ); + const float underlineHeight( view.GetUnderlineHeight() ); + + // Get the underline runs. + const Length numberOfUnderlineRuns = view.GetNumberOfUnderlineRuns(); + Vector underlineRuns; + underlineRuns.Resize( numberOfUnderlineRuns ); + view.GetUnderlineRuns( underlineRuns.Begin(), + 0u, + numberOfUnderlineRuns ); + + bool thereAreUnderlinedGlyphs = false; float currentUnderlinePosition = ZERO; float currentUnderlineThickness = underlineHeight; uint32_t currentBlockSize = 0; FontId lastFontId = 0; + FontId lastUnderlinedFontId = 0; Style style = STYLE_NORMAL; if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) @@ -179,16 +217,20 @@ struct AtlasRenderer::Impl : public ConnectionTracker // Avoid emptying mTextCache (& removing references) until after incremented references for the new text Vector< TextCacheEntry > newTextCache; const GlyphInfo* const glyphsBuffer = glyphs.Begin(); + const Vector2* const positionsBuffer = positions.Begin(); for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i ) { const GlyphInfo& glyph = *( glyphsBuffer + i ); + const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( i, underlineRuns ); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; + // No operation for white space if ( glyph.width && glyph.height ) { // Are we still using the same fontId as previous - if ( glyph.fontId != lastFontId ) + if ( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) ) { // We need to fetch fresh font underline metrics FontMetrics fontMetrics; @@ -221,7 +263,9 @@ struct AtlasRenderer::Impl : public ConnectionTracker // Move offset down by one ( EFL behavior ) currentUnderlinePosition = ONE; } - } + + lastUnderlinedFontId = glyph.fontId; + } // underline if ( !mGlyphManager.Cached( glyph.fontId, glyph.index, slot ) ) { @@ -277,7 +321,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker } // Move the origin (0,0) of the mesh to the center of the actor - Vector2 position = positions[ i ] - halfActorSize; + Vector2 position = *( positionsBuffer + i ) - halfActorSize; // Generate mesh data for this quad, plugging in our supplied position AtlasManager::Mesh2D newMesh; @@ -287,12 +331,23 @@ struct AtlasRenderer::Impl : public ConnectionTracker textCacheEntry.mIndex = glyph.index; newTextCache.PushBack( textCacheEntry ); + // Adjust the vertices if the fixed-size font should be down-scaled + if( glyph.scaleFactor > 0 ) + { + for( unsigned int i=0; i& extents, const Vector4& color, float baseLine, + bool underlineGlyph, float underlinePosition, float underlineThickness, AtlasManager::AtlasSlot& slot ) @@ -416,14 +474,19 @@ struct AtlasRenderer::Impl : public ConnectionTracker { // Stitch the mesh to the existing mesh and adjust any extents mGlyphManager.StitchMesh( mIt->mMesh, newMesh ); - AdjustExtents( extents, - meshContainer, - index, - left, - right, - baseLine, - underlinePosition, - underlineThickness ); + + if( underlineGlyph ) + { + AdjustExtents( extents, + meshContainer, + index, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + } + return; } } @@ -435,16 +498,18 @@ struct AtlasRenderer::Impl : public ConnectionTracker meshRecord.mColor = color; meshContainer.push_back( meshRecord ); - // Adjust extents for this new meshrecord - AdjustExtents( extents, - meshContainer, - meshContainer.size() - 1u, - left, - right, - baseLine, - underlinePosition, - underlineThickness ); - + if( underlineGlyph ) + { + // Adjust extents for this new meshrecord + AdjustExtents( extents, + meshContainer, + meshContainer.size() - 1u, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + } } } @@ -658,8 +723,8 @@ struct AtlasRenderer::Impl : public ConnectionTracker Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material ); - // Ensure shadow is behind the text... - renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth - 1 ); + // Set depth index to -1.0 to make sure shadow is rendered first in 3D layers + renderer.SetDepthIndex( -1.0f ); Actor actor = Actor::New(); actor.AddRenderer( renderer ); actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned @@ -692,29 +757,43 @@ struct AtlasRenderer::Impl : public ConnectionTracker subActor.AddRenderer( normRenderer ); subActor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned subActor.SetSize( actorSize ); - subActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); subActor.SetColor( shadowColor ); + // Discard redundant render-tasks + RemoveShadowRenderTask(); + // Create a render task to render the effect - RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask(); - task.SetTargetFrameBuffer( meshRecord.mBuffer ); - task.SetSourceActor( subActor ); - task.SetClearEnabled( true ); - task.SetClearColor( Vector4::ZERO ); - task.SetExclusive( true ); - task.SetRefreshRate( RenderTask::REFRESH_ONCE ); - task.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete ); + mShadowTask = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + mShadowTask.SetTargetFrameBuffer( meshRecord.mBuffer ); + mShadowTask.SetSourceActor( subActor ); + mShadowTask.SetClearEnabled( true ); + mShadowTask.SetClearColor( Vector4::ZERO ); + mShadowTask.SetExclusive( true ); + mShadowTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); + mShadowTask.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete ); actor.Add( subActor ); return actor; } - void RenderComplete( RenderTask& renderTask ) + void RemoveShadowRenderTask() { - // Disconnect and remove this single shot render task - renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete ); - Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask ); + if( mShadowTask ) + { + mShadowTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete ); + // Guard to prevent accessing Stage after dali-core destruction + if( Stage::IsInstalled() ) + { + Stage::GetCurrent().GetRenderTaskList().RemoveTask( mShadowTask ); + } + + mShadowTask.Reset(); + } + } + + void RenderComplete( RenderTask& renderTask ) + { // Get the actor used for render to buffer and remove it from the parent Actor renderActor = renderTask.GetSourceActor(); if ( renderActor ) @@ -725,10 +804,13 @@ struct AtlasRenderer::Impl : public ConnectionTracker parent.Remove( renderActor ); } } + + RemoveShadowRenderTask(); } Actor mActor; ///< The actor parent which renders the text AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching + RenderTask mShadowTask; ///< Used to render shadows TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas std::vector< uint32_t > mFace; ///> Face indices for a quad @@ -756,15 +838,15 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth ) Vector glyphs; glyphs.Resize( numberOfGlyphs ); - std::vector positions; - positions.resize( numberOfGlyphs ); + Vector positions; + positions.Resize( numberOfGlyphs ); numberOfGlyphs = view.GetGlyphs( glyphs.Begin(), - &positions[0], + positions.Begin(), 0u, numberOfGlyphs ); glyphs.Resize( numberOfGlyphs ); - positions.resize( numberOfGlyphs ); + positions.Resize( numberOfGlyphs ); mImpl->AddGlyphs( view, positions, @@ -783,6 +865,8 @@ AtlasRenderer::AtlasRenderer() AtlasRenderer::~AtlasRenderer() { + mImpl->RemoveShadowRenderTask(); + mImpl->RemoveText(); delete mImpl; }