Fix for shadow 'leak' reported on SPIN homescreen.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / rendering / atlas / text-atlas-renderer.cpp
index 42961ce..7c629fd 100644 (file)
@@ -331,6 +331,16 @@ 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<newMesh.mVertices.Count(); ++i )
+          {
+            newMesh.mVertices[i].mPosition.x = position.x + ( ( newMesh.mVertices[i].mPosition.x - position.x ) * glyph.scaleFactor );
+            newMesh.mVertices[i].mPosition.y = position.y + ( ( newMesh.mVertices[i].mPosition.y - position.y ) * glyph.scaleFactor );
+          }
+        }
+
         // 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,
                         newMesh,
@@ -348,6 +358,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     // Now remove references for the old text
     RemoveText();
     mTextCache.Swap( newTextCache );
+    RemoveAllShadowRenderTasks();
 
     if( thereAreUnderlinedGlyphs )
     {
@@ -365,7 +376,9 @@ struct AtlasRenderer::Impl : public ConnectionTracker
         // Create an effect if necessary
         if ( style == STYLE_DROP_SHADOW )
         {
-          actor.Add( GenerateShadow( *mIt, actorSize, shadowOffset, shadowColor ) );
+          Actor shadowActor = GenerateShadow( *mIt, actorSize, shadowOffset, shadowColor );
+          shadowActor.Add( actor );
+          actor = shadowActor;
         }
 
         if( mActor )
@@ -711,8 +724,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
@@ -745,29 +758,40 @@ 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 );
 
     // 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 );
+    RenderTask shadowTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
+    shadowTask.SetTargetFrameBuffer( meshRecord.mBuffer );
+    shadowTask.SetSourceActor( subActor );
+    shadowTask.SetClearEnabled( true );
+    shadowTask.SetClearColor( Vector4::ZERO );
+    shadowTask.SetExclusive( true );
+    shadowTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
+    shadowTask.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete );
+    mShadowTasks.push_back( shadowTask );
     actor.Add( subActor );
 
     return actor;
   }
 
-  void RenderComplete( RenderTask& renderTask )
+  void RemoveShadowRenderTask( RenderTask renderTask )
   {
-    // Disconnect and remove this single shot render task
-    renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete );
-    Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask );
+    if( renderTask )
+    {
+      renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete );
 
+      // Guard to prevent accessing Stage after dali-core destruction
+      if( Stage::IsInstalled() )
+      {
+        Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask );
+      }
+      renderTask.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 )
@@ -778,10 +802,22 @@ struct AtlasRenderer::Impl : public ConnectionTracker
         parent.Remove( renderActor );
       }
     }
+
+    RemoveShadowRenderTask( renderTask );
+  }
+
+  void RemoveAllShadowRenderTasks()
+  {
+    for ( std::vector< RenderTask >::iterator shadowIterator = mShadowTasks.begin();
+          shadowIterator != mShadowTasks.end(); ++shadowIterator )
+    {
+      RemoveShadowRenderTask( *shadowIterator );
+    }
   }
 
   Actor mActor;                                       ///< The actor parent which renders the text
   AtlasGlyphManager mGlyphManager;                    ///< Glyph Manager to handle upload and caching
+  std::vector< RenderTask > mShadowTasks;             ///< 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
@@ -836,6 +872,8 @@ AtlasRenderer::AtlasRenderer()
 
 AtlasRenderer::~AtlasRenderer()
 {
+  mImpl->RemoveAllShadowRenderTasks();
+
   mImpl->RemoveText();
   delete mImpl;
 }