Retrieve outline glyph from freetype
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / font-client-plugin-impl.cpp
index 8eabda9..a1e4cc6 100644 (file)
@@ -268,7 +268,7 @@ void FontClient::Plugin::ResetSystemDefaults()
   mDefaultFontDescriptionCached = false;
 }
 
-  void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList )
+void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::SetFontList\n" );
   DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
@@ -369,7 +369,27 @@ void FontClient::Plugin::GetDefaultPlatformFontDescription( FontDescription& fon
 
   if( !mDefaultFontDescriptionCached )
   {
-    FcInitReinitialize(); // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
+    // Clear any font config stored info in the caches.
+    mDefaultFontCharacterSets.Clear();
+    mCharacterSetCache.Clear();
+
+    for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end(); it != endIt; ++it )
+    {
+      FallbackCacheItem& item = *it;
+
+      item.characterSets->Clear();
+    }
+
+    for( std::vector<FontFaceCacheItem>::iterator it = mFontCache.begin(), endIt = mFontCache.end(); it != endIt; ++it )
+    {
+      FontFaceCacheItem& item = *it;
+
+      // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
+      item.mCharacterSet = NULL;
+    }
+
+    // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
+    FcInitReinitialize();
 
     FcPattern* matchPattern = FcPatternCreate();
 
@@ -383,6 +403,41 @@ void FontClient::Plugin::GetDefaultPlatformFontDescription( FontDescription& fon
       FcPatternDestroy( matchPattern );
     }
 
+    // Create again the character sets as they are not valid after FcInitReinitialize()
+
+    for( FontList::const_iterator it = mDefaultFonts.begin(), endIt = mDefaultFonts.end(); it != endIt; ++it )
+    {
+      const FontDescription& description = *it;
+
+      mDefaultFontCharacterSets.PushBack( CreateCharacterSetFromDescription( description ) );
+    }
+
+    for( FontList::const_iterator it = mFontDescriptionCache.begin(), endIt = mFontDescriptionCache.end(); it != endIt; ++it )
+    {
+      const FontDescription& description = *it;
+
+      mCharacterSetCache.PushBack( CreateCharacterSetFromDescription( description ) );
+    }
+
+    for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end(); it != endIt; ++it )
+    {
+      FallbackCacheItem& item = *it;
+
+      if( NULL != item.fallbackFonts )
+      {
+        if( NULL == item.characterSets )
+        {
+          item.characterSets = new CharacterSetList;
+        }
+
+        for( FontList::const_iterator flIt = item.fallbackFonts->begin(), flEndIt = item.fallbackFonts->end(); flIt != flEndIt; ++flIt )
+        {
+          const FontDescription& description = *flIt;
+          item.characterSets->PushBack( CreateCharacterSetFromDescription( description ) );
+        }
+      }
+    }
+
     mDefaultFontDescriptionCached = true;
   }
 
@@ -485,7 +540,32 @@ bool FontClient::Plugin::IsCharacterSupportedByFont( FontId fontId, Character ch
 
   bool isSupported = false;
 
-  const FontFaceCacheItem& cacheItem = mFontCache[fontId];
+  FontFaceCacheItem& cacheItem = mFontCache[fontId];
+
+  if( NULL == cacheItem.mCharacterSet )
+  {
+    // Create again the character set.
+    // It can be null if the ResetSystemDefaults() method has been called.
+
+    FontDescription description;
+    description.path = cacheItem.mPath;
+    description.family = FontFamily( cacheItem.mFreeTypeFace->family_name );
+    description.weight = FontWeight::NONE;
+    description.width = FontWidth::NONE;
+    description.slant = FontSlant::NONE;
+
+    // Note FreeType doesn't give too much info to build a proper font style.
+    if( cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC )
+    {
+      description.slant = FontSlant::ITALIC;
+    }
+    if( cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD )
+    {
+      description.weight = FontWeight::BOLD;
+    }
+
+    cacheItem.mCharacterSet = CreateCharacterSetFromDescription( description );
+  }
 
   isSupported = FcCharSetHasChar( cacheItem.mCharacterSet, character );
 
@@ -596,6 +676,7 @@ FontId FontClient::Plugin::FindDefaultFont( Character charcode,
 
   DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", fontId );
   DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindDefaultFont\n" );
+
   return fontId;
 }
 
@@ -1003,7 +1084,7 @@ bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
 #endif
 }
 
-void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data )
+void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
 {
   if( ( fontId > 0 ) &&
       ( fontId - 1u < mFontCache.size() ) )
@@ -1033,6 +1114,33 @@ void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dal
       {
         if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
         {
+          // Check whether we should create a bitmap for the outline
+          if( glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0 )
+          {
+            // Set up a stroker
+            FT_Stroker stroker;
+            error = FT_Stroker_New(mFreeTypeLibrary, &stroker );
+
+            if ( FT_Err_Ok == error )
+            {
+              FT_Stroker_Set( stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 );
+              error = FT_Glyph_StrokeBorder( &glyph, stroker, 0, 1 );
+
+              if ( FT_Err_Ok == error )
+              {
+                FT_Stroker_Done( stroker );
+              }
+              else
+              {
+                DALI_LOG_ERROR( "FT_Glyph_StrokeBorder Failed with error: %d\n", error );
+              }
+            }
+            else
+            {
+              DALI_LOG_ERROR( "FT_Stroker_New Failed with error: %d\n", error );
+            }
+          }
+
           error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
           if ( FT_Err_Ok == error )
           {
@@ -1060,12 +1168,11 @@ void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dal
   }
 }
 
-PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
-                                            GlyphIndex glyphIndex )
+PixelData FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
 {
   TextAbstraction::FontClient::GlyphBufferData data;
 
-  CreateBitmap( fontId, glyphIndex, data );
+  CreateBitmap( fontId, glyphIndex, data, outlineWidth );
 
   return PixelData::New( data.buffer,
                          data.width * data.height * Pixel::GetBytesPerPixel( data.format ),
@@ -1098,6 +1205,9 @@ void FontClient::Plugin::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex,
 
 const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requestedPointSize )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetEllipsisGlyph\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize %d.\n", requestedPointSize );
+
   // First look into the cache if there is an ellipsis glyph for the requested point size.
   for( Vector<EllipsisItem>::ConstIterator it = mEllipsisCache.Begin(),
          endIt = mEllipsisCache.End();
@@ -1109,6 +1219,11 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requested
     if( fabsf( item.requestedPointSize - requestedPointSize ) < Math::MACHINE_EPSILON_1000 )
     {
       // Use the glyph in the cache.
+
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  glyph id %d found in the cache.\n", item.glyph.index );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "      font %d.\n", item.glyph.fontId );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetEllipsisGlyph\n" );
+
       return item.glyph;
     }
   }
@@ -1130,6 +1245,10 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requested
 
   GetBitmapMetrics( &item.glyph, 1u, true );
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  glyph id %d found in the cache.\n", item.glyph.index );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "      font %d.\n", item.glyph.fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetEllipsisGlyph\n" );
+
   return item.glyph;
 }
 
@@ -1177,11 +1296,6 @@ void FontClient::Plugin::InitSystemFonts()
       // Skip fonts with no path
       if( GetFcString( fontPattern, FC_FILE, path ) )
       {
-        FcCharSet* characterSet = NULL;
-        FcPatternGetCharSet( fontPattern, FC_CHARSET, 0u, &characterSet );
-
-        mSystemFontCharacterSets.PushBack( characterSet );
-
         mSystemFonts.push_back( FontDescription() );
         FontDescription& fontDescription = mSystemFonts.back();
 
@@ -1252,7 +1366,7 @@ bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali
   return matched;
 }
 
-FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontDescription& fontDescription )
+FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontDescription& fontDescription ) const
 {
   // create the cached font family lookup pattern
   // a pattern holds a set of names, each name refers to a property of the font
@@ -1861,6 +1975,26 @@ void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Do
   }
 }
 
+FcCharSet* FontClient::Plugin::CreateCharacterSetFromDescription( const FontDescription& description ) const
+{
+  FcCharSet* characterSet = NULL;
+
+  FcPattern* pattern = CreateFontFamilyPattern( description );
+
+  if( NULL != pattern )
+  {
+    FcResult result = FcResultMatch;
+    FcPattern* match = FcFontMatch( NULL, pattern, &result );
+
+    FcPatternGetCharSet( match, FC_CHARSET, 0u, &characterSet );
+
+    FcPatternDestroy( match );
+    FcPatternDestroy( pattern );
+  }
+
+  return characterSet;
+}
+
 } // namespace Internal
 
 } // namespace TextAbstraction