Fixed regression with Actor::COLOR property in TextLabel
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / rendering / atlas / atlas-glyph-manager-impl.cpp
index 3c21923..c8ea1e2 100644 (file)
 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/actors/image-actor.h>
-#include <dali/public-api/common/stage.h>
+#include <dali/integration-api/debug.h>
 
-namespace Dali
+namespace
 {
 
-namespace Toolkit
-{
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
+#endif
 
-namespace Internal
+#define MAKE_SHADER(A)#A
+
+const char* VERTEX_SHADER = MAKE_SHADER(
+attribute mediump vec2    aPosition;
+attribute mediump vec2    aTexCoord;
+attribute mediump vec4    aColor;
+uniform   mediump vec2    uOffset;
+uniform   mediump mat4    uMvpMatrix;
+varying   mediump vec2    vTexCoord;
+varying   mediump vec4    vColor;
+
+void main()
 {
+  mediump vec4 position = vec4( aPosition.xy + uOffset, 0.0, 1.0 );
+  gl_Position = uMvpMatrix * position;
+  vTexCoord = aTexCoord;
+  vColor = aColor;
+}
+);
 
-//#define DISPLAY_ATLAS
+const char* FRAGMENT_SHADER_L8 = MAKE_SHADER(
+uniform lowp    vec4      uColor;
+uniform         sampler2D sTexture;
+varying mediump vec2      vTexCoord;
+varying mediump vec4      vColor;
 
-AtlasGlyphManager::AtlasGlyphManager()
-: mCount( 0 )
+void main()
 {
-  mAtlasManager = Dali::Toolkit::AtlasManager::New();
+  mediump vec4 color = texture2D( sTexture, vTexCoord );
+  gl_FragColor = vec4( vColor.rgb * uColor.rgb, vColor.a * uColor.a * color.r );
 }
+);
 
-AtlasGlyphManager::~AtlasGlyphManager()
+const char* FRAGMENT_SHADER_RGBA = MAKE_SHADER(
+uniform         sampler2D sTexture;
+varying mediump vec2      vTexCoord;
+
+void main()
 {
+  gl_FragColor = texture2D( sTexture, vTexCoord );
 }
+);
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+namespace Toolkit
+{
 
-AtlasGlyphManagerPtr AtlasGlyphManager::New()
+namespace Internal
+{
+
+AtlasGlyphManager::AtlasGlyphManager()
 {
-  AtlasGlyphManagerPtr internal = new AtlasGlyphManager();
-  return internal;
+  mShaderL8 = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_L8 );
+  mShaderRgba = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_RGBA );
+  mAtlasManager = Dali::Toolkit::AtlasManager::New();
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
                              const BufferImage& bitmap,
                              Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
-  GlyphRecord record;
-  record.mFontId = glyph.fontId;
-  record.mIndex = glyph.index;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Added glyph, font: %d index: %d\n", glyph.fontId, glyph.index );
+
+  if ( mAtlasManager.Add( bitmap, slot ) )
+  {
+    // A new atlas was created so set the material details for the atlas
+    Dali::Atlas atlas = mAtlasManager.GetAtlasContainer( slot.mAtlasId );
+    Pixel::Format pixelFormat = mAtlasManager.GetPixelFormat( slot.mAtlasId );
+    Material material = Material::New( pixelFormat == Pixel::L8 ? mShaderL8 : mShaderRgba );
+    material.AddTexture( atlas, "sTexture" );
+    material.SetBlendMode( BlendingMode::ON );
+    mAtlasManager.SetMaterial( slot.mAtlasId, material );
+  }
 
-  mAtlasManager.Add( bitmap, slot );
+  GlyphRecordEntry record;
+  record.mIndex = glyph.index;
   record.mImageId = slot.mImageId;
-  mGlyphRecords.PushBack( record );
+  record.mCount = 1;
 
-#ifdef DISPLAY_ATLAS
+  // Have glyph records been created for this fontId ?
+  bool foundGlyph = false;
+  for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+        fontGlyphRecordIt != mFontGlyphRecords.end(); ++fontGlyphRecordIt )
   {
-    uint32_t atlasCount = mAtlasManager.GetAtlasCount();
-    if ( atlasCount > mCount )
+    if ( fontGlyphRecordIt->mFontId == glyph.fontId )
     {
-      for ( uint32_t i = 0; i < atlasCount; ++i )
-      {
-        ImageActor actor = ImageActor::New( mAtlasManager.GetAtlasContainer( i + 1u ) );
-        actor.SetParentOrigin( Vector3( 0.5f, 0.25f + ( static_cast< float >( i ) * 0.25f ), 0.5f ) );
-        actor.SetAnchorPoint( AnchorPoint::CENTER );
-        actor.SetSize( 256.0f, 256.0f );
-        Stage::GetCurrent().Add( actor );
-      }
+      fontGlyphRecordIt->mGlyphRecords.PushBack( record );
+      foundGlyph = true;
+      break;
     }
-    mCount = atlasCount;
   }
-#endif
+
+  if ( !foundGlyph )
+  {
+    // We need to add a new font entry
+    FontGlyphRecord fontGlyphRecord;
+    fontGlyphRecord.mFontId = glyph.fontId;
+    fontGlyphRecord.mGlyphRecords.PushBack( record );
+    mFontGlyphRecords.push_back( fontGlyphRecord );
+  }
 }
 
 void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
                                           const Vector2& position,
                                           Toolkit::AtlasManager::Mesh2D& mesh )
 {
-  mAtlasManager.GenerateMeshData( imageId, position, mesh );
-}
-
-void AtlasGlyphManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
-                                    const Toolkit::AtlasManager::Mesh2D& second )
-{
-  mAtlasManager.StitchMesh( first, second );
+  // Generate mesh data and tell Atlas Manager not to handle reference counting ( we'll do it )
+  mAtlasManager.GenerateMeshData( imageId, position, mesh, false );
 }
 
-void AtlasGlyphManager::Cached( Text::FontId fontId,
-                                uint32_t index,
+bool AtlasGlyphManager::IsCached( Text::FontId fontId,
+                                Text::GlyphIndex index,
                                 Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
-  for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
+  for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+        fontGlyphRecordIt != mFontGlyphRecords.end();
+        ++fontGlyphRecordIt )
   {
-    if ( fontId == mGlyphRecords[ i ].mFontId && index == mGlyphRecords[ i ].mIndex )
+    if ( fontGlyphRecordIt->mFontId == fontId )
     {
-      slot.mImageId = mGlyphRecords[ i ].mImageId;
-      slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
-      return;
+      for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+            glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+            ++glyphRecordIt )
+      {
+        if ( glyphRecordIt->mIndex == index )
+        {
+          slot.mImageId = glyphRecordIt->mImageId;
+          slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
+          return true;
+        }
+      }
     }
   }
   slot.mImageId = 0;
+  return false;
 }
 
 Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId )
@@ -124,24 +184,73 @@ void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32
   mAtlasManager.SetNewAtlasSize( size );
 }
 
-void AtlasGlyphManager::Remove( uint32_t imageId )
+Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
+{
+  return mAtlasManager.GetPixelFormat( atlasId );
+}
+
+const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
 {
-  if ( mAtlasManager.Remove( imageId ) )
+  std::ostringstream verboseMetrics;
+
+  mMetrics.mGlyphCount = 0u;
+  for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+        fontGlyphRecordIt != mFontGlyphRecords.end();
+        ++fontGlyphRecordIt )
   {
-    for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
+    mMetrics.mGlyphCount += fontGlyphRecordIt->mGlyphRecords.Size();
+
+    verboseMetrics << "[FontId " << fontGlyphRecordIt->mFontId << " Glyph ";
+    for ( Vector< GlyphRecordEntry >::Iterator glyphRecordEntryIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+          glyphRecordEntryIt != fontGlyphRecordIt->mGlyphRecords.End();
+          ++glyphRecordEntryIt )
     {
-      if ( mGlyphRecords[ i ].mImageId == imageId )
-      {
-        mGlyphRecords.Remove( mGlyphRecords.Begin() + i );
-        return;
-      }
+      verboseMetrics << glyphRecordEntryIt->mIndex << "(" << glyphRecordEntryIt->mCount << ") ";
     }
+    verboseMetrics << "] ";
   }
+  mMetrics.mVerboseGlyphCounts = verboseMetrics.str();
+
+  mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
+
+  return mMetrics;
 }
 
-Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta )
 {
-  return mAtlasManager.GetPixelFormat( atlasId );
+  if( 0 != delta )
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "AdjustReferenceCount %d, font: %d index: %d\n", delta, fontId, index );
+
+    for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+          fontGlyphRecordIt != mFontGlyphRecords.end();
+          ++fontGlyphRecordIt )
+    {
+      if ( fontGlyphRecordIt->mFontId == fontId )
+      {
+        for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+              glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+              ++glyphRecordIt )
+        {
+          if ( glyphRecordIt->mIndex == index )
+          {
+            glyphRecordIt->mCount += delta;
+            DALI_ASSERT_DEBUG( glyphRecordIt->mCount >= 0 && "Glyph ref-count should not be negative" );
+
+            if ( !glyphRecordIt->mCount )
+            {
+              mAtlasManager.Remove( glyphRecordIt->mImageId );
+              fontGlyphRecordIt->mGlyphRecords.Remove( glyphRecordIt );
+            }
+            return;
+          }
+        }
+      }
+    }
+
+    // Should not arrive here
+    DALI_ASSERT_DEBUG( false && "Failed to adjust ref-count" );
+  }
 }
 
 Material AtlasGlyphManager::GetMaterial( uint32_t atlasId ) const
@@ -149,16 +258,9 @@ Material AtlasGlyphManager::GetMaterial( uint32_t atlasId ) const
   return mAtlasManager.GetMaterial( atlasId );
 }
 
-Sampler AtlasGlyphManager::GetSampler( uint32_t atlasId ) const
-{
-  return mAtlasManager.GetSampler( atlasId );
-}
-
-const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
+AtlasGlyphManager::~AtlasGlyphManager()
 {
-  mMetrics.mGlyphCount = mGlyphRecords.Size();
-  mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
-  return mMetrics;
+  // mAtlasManager handle is automatically released here
 }
 
 } // namespace Internal