[3.0] New methods added to the font-client.
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / font-client-plugin-impl.cpp
index a1edfd4..1ba5361 100644 (file)
@@ -41,6 +41,7 @@ Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New
  * Conversion from Fractional26.6 to float
  */
 const float FROM_266 = 1.0f / 64.0f;
+const float POINTS_PER_INCH = 72.f;
 
 const std::string FONT_FORMAT( "TrueType" );
 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
@@ -54,6 +55,7 @@ const bool FONT_FIXED_SIZE_BITMAP( true );
 
 // http://www.freedesktop.org/software/fontconfig/fontconfig-user.html
 
+// NONE            -1  --> DEFAULT_FONT_WIDTH (NORMAL) will be used.
 // ULTRA_CONDENSED 50
 // EXTRA_CONDENSED 63
 // CONDENSED       75
@@ -63,9 +65,10 @@ const bool FONT_FIXED_SIZE_BITMAP( true );
 // EXPANDED       125
 // EXTRA_EXPANDED 150
 // ULTRA_EXPANDED 200
-const int FONT_WIDTH_TYPE_TO_INT[] = { 50, 63, 75, 87, 100, 113, 125, 150, 200 };
+const int FONT_WIDTH_TYPE_TO_INT[] = { -1, 50, 63, 75, 87, 100, 113, 125, 150, 200 };
 const unsigned int NUM_FONT_WIDTH_TYPE = sizeof( FONT_WIDTH_TYPE_TO_INT ) / sizeof( int );
 
+// NONE                       -1  --> DEFAULT_FONT_WEIGHT (NORMAL) will be used.
 // THIN                        0
 // ULTRA_LIGHT, EXTRA_LIGHT   40
 // LIGHT                      50
@@ -77,13 +80,14 @@ const unsigned int NUM_FONT_WIDTH_TYPE = sizeof( FONT_WIDTH_TYPE_TO_INT ) / size
 // BOLD                      200
 // ULTRA_BOLD, EXTRA_BOLD    205
 // BLACK, HEAVY, EXTRA_BLACK 210
-const int FONT_WEIGHT_TYPE_TO_INT[] = { 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210 };
+const int FONT_WEIGHT_TYPE_TO_INT[] = { -1, 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210 };
 const unsigned int NUM_FONT_WEIGHT_TYPE = sizeof( FONT_WEIGHT_TYPE_TO_INT ) / sizeof( int );
 
-// NORMAL, ROMAN   0
-// ITALIC        100
-// OBLIQUE       110
-const int FONT_SLANT_TYPE_TO_INT[] = { 0, 100, 110 };
+// NONE             -1 --> DEFAULT_FONT_SLANT (NORMAL) will be used.
+// NORMAL, ROMAN     0
+// ITALIC          100
+// OBLIQUE         110
+const int FONT_SLANT_TYPE_TO_INT[] = { -1, 0, 100, 110 };
 const unsigned int NUM_FONT_SLANT_TYPE = sizeof( FONT_SLANT_TYPE_TO_INT ) / sizeof( int );
 
 } // namespace
@@ -149,44 +153,46 @@ FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const Fo
 }
 
 FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
-                                                      PointSize26Dot6 pointSize,
+                                                      PointSize26Dot6 requestedPointSize,
                                                       FontId fontId )
 : validatedFontId( validatedFontId ),
-  pointSize( pointSize ),
+  requestedPointSize( requestedPointSize ),
   fontId( fontId )
 {
 }
 
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
-                                          const FontPath& path,
-                                          PointSize26Dot6 pointSize,
-                                          FaceIndex face,
-                                          const FontMetrics& metrics )
+FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
+                                                          const FontPath& path,
+                                                          PointSize26Dot6 requestedPointSize,
+                                                          FaceIndex face,
+                                                          const FontMetrics& metrics )
 : mFreeTypeFace( ftFace ),
   mPath( path ),
-  mPointSize( pointSize ),
+  mRequestedPointSize( requestedPointSize ),
   mFaceIndex( face ),
   mMetrics( metrics ),
   mFixedWidthPixels( 0.0f ),
   mFixedHeightPixels( 0.0f ),
+  mVectorFontId( 0 ),
   mIsFixedSizeBitmap( false )
 {
 }
 
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
-                                          const FontPath& path,
-                                          PointSize26Dot6 pointSize,
-                                          FaceIndex face,
-                                          const FontMetrics& metrics,
-                                          float fixedWidth,
-                                          float fixedHeight )
+FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
+                                                          const FontPath& path,
+                                                          PointSize26Dot6 requestedPointSize,
+                                                          FaceIndex face,
+                                                          const FontMetrics& metrics,
+                                                          float fixedWidth,
+                                                          float fixedHeight )
 : mFreeTypeFace( ftFace ),
   mPath( path ),
-  mPointSize( pointSize ),
+  mRequestedPointSize( requestedPointSize ),
   mFaceIndex( face ),
   mMetrics( metrics ),
   mFixedWidthPixels( fixedWidth ),
   mFixedHeightPixels( fixedHeight ),
+  mVectorFontId( 0 ),
   mIsFixedSizeBitmap( true )
 {
 }
@@ -203,6 +209,7 @@ FontClient::Plugin::Plugin( unsigned int horizontalDpi,
   mValidatedFontCache(),
   mFontDescriptionCache( 1u ),
   mFontIdCache(),
+  mVectorFontCache( NULL ),
   mEllipsisCache(),
   mDefaultFontDescriptionCached( false )
 {
@@ -211,6 +218,10 @@ FontClient::Plugin::Plugin( unsigned int horizontalDpi,
   {
     DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
   }
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  mVectorFontCache = new VectorFontCache( mFreeTypeLibrary );
+#endif
 }
 
 FontClient::Plugin::~Plugin()
@@ -228,6 +239,10 @@ FontClient::Plugin::~Plugin()
     }
   }
 
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  delete mVectorFontCache;
+#endif
+
   FT_Done_FreeType( mFreeTypeLibrary );
 }
 
@@ -379,7 +394,7 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
   if( id > 0u &&
       index < mFontCache.size() )
   {
-    return ( *( mFontCache.begin() + index ) ).mPointSize;
+    return ( *( mFontCache.begin() + index ) ).mRequestedPointSize;
   }
   else
   {
@@ -391,17 +406,16 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
 
 FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
                                                  Character charcode,
-                                                 PointSize26Dot6 requestedSize,
+                                                 PointSize26Dot6 requestedPointSize,
                                                  bool preferColor )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFontForCharacter\n");
 
-  FontId fontId(0);
-  bool foundColor(false);
+  FontId fontId = 0u;
+  bool foundColor = false;
 
   // Traverse the list of fonts.
-  // Check for each default font if supports the character.
-
+  // Check for each font if supports the character.
   for( FontList::const_iterator it = fontList.begin(), endIt = fontList.end();
        it != endIt;
        ++it )
@@ -422,37 +436,35 @@ FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
       GetFixedSizes( description,
                      fixedSizes );
 
+      PointSize26Dot6 actualPointSize = requestedPointSize;
+
       const Vector< PointSize26Dot6 >::SizeType count = fixedSizes.Count();
+
       if( 0 != count )
       {
-        // If the font is not scalable, pick the largest size <= requestedSize
-        PointSize26Dot6 size = fixedSizes[0];
+        // If the font is not scalable, pick the largest size <= requestedPointSize
+        actualPointSize = fixedSizes[0];
         for( unsigned int i=1; i<count; ++i )
         {
-          if( fixedSizes[i] <= requestedSize &&
-              fixedSizes[i] > size )
+          if( fixedSizes[i] <= requestedPointSize &&
+              fixedSizes[i] > actualPointSize )
           {
-            size = fixedSizes[i];
+            actualPointSize = fixedSizes[i];
           }
         }
-        requestedSize = size;
       }
 
       fontId = GetFontId( description,
-                          requestedSize,
+                          requestedPointSize,
+                          actualPointSize,
                           0u );
 
       if( preferColor )
       {
-        BufferImage bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
-        if( bitmap &&
-            Pixel::BGRA8888 == bitmap.GetPixelFormat() )
-        {
-          foundColor = true;
-        }
+        foundColor = IsColorGlyph( fontId, GetGlyphIndex( fontId, charcode ) );
       }
 
-      // Keep going unless we prefer a different (color) font
+      // Keep going unless we prefer a different (color) font.
       if( !preferColor || foundColor )
       {
         FcPatternDestroy( match );
@@ -469,7 +481,7 @@ FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
 }
 
 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
-                                            PointSize26Dot6 requestedSize,
+                                            PointSize26Dot6 requestedPointSize,
                                             bool preferColor )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindDefaultFont DefaultFontsList(%s)\n", (mDefaultFonts.empty()?"empty":"created") );
@@ -484,26 +496,32 @@ FontId FontClient::Plugin::FindDefaultFont( Character charcode,
     fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
     fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
     fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
+
     SetFontList( fontDescription, mDefaultFonts );
   }
 
   // Traverse the list of default fonts.
   // Check for each default font if supports the character.
-  fontId = FindFontForCharacter( mDefaultFonts, charcode, requestedSize, preferColor );
+  fontId = FindFontForCharacter( mDefaultFonts, charcode, requestedPointSize, preferColor );
 
   return fontId;
 }
 
-FontId FontClient::Plugin::FindFallbackFont( FontId preferredFont,
-                                             Character charcode,
-                                             PointSize26Dot6 requestedSize,
+FontId FontClient::Plugin::FindFallbackFont( Character charcode,
+                                             const FontDescription& preferredFontDescription,
+                                             PointSize26Dot6 requestedPointSize,
                                              bool preferColor )
 {
   // The font id to be returned.
   FontId fontId = 0u;
 
   FontDescription fontDescription;
-  GetDescription( preferredFont, fontDescription );
+
+  // Fill the font description with the preferred font description and complete with the defaults.
+  fontDescription.family = preferredFontDescription.family.empty() ? DEFAULT_FONT_FAMILY_NAME : preferredFontDescription.family;
+  fontDescription.weight = ( ( FontWeight::NONE == preferredFontDescription.weight ) ? IntToWeightType( DEFAULT_FONT_WEIGHT ) : preferredFontDescription.weight );
+  fontDescription.width = ( ( FontWidth::NONE == preferredFontDescription.width ) ? IntToWidthType( DEFAULT_FONT_WIDTH ) : preferredFontDescription.width );
+  fontDescription.slant = ( ( FontSlant::NONE == preferredFontDescription.slant ) ? IntToSlantType( DEFAULT_FONT_SLANT ) : preferredFontDescription.slant );
 
   // Check first if the font's description has been queried before.
   FontList* fontList( NULL );
@@ -514,19 +532,20 @@ FontId FontClient::Plugin::FindFallbackFont( FontId preferredFont,
     SetFontList( fontDescription, *fontList );
 
     // Add the font-list to the cache.
-    mFallbackCache.push_back( FallbackCacheItem(fontDescription, fontList) );
+    mFallbackCache.push_back( FallbackCacheItem( fontDescription, fontList ) );
   }
 
   if( fontList )
   {
-    fontId = FindFontForCharacter( *fontList, charcode, requestedSize, preferColor );
+    fontId = FindFontForCharacter( *fontList, charcode, requestedPointSize, preferColor );
   }
 
   return fontId;
 }
 
 FontId FontClient::Plugin::GetFontId( const FontPath& path,
-                                      PointSize26Dot6 pointSize,
+                                      PointSize26Dot6 requestedPointSize,
+                                      PointSize26Dot6 actualPointSize,
                                       FaceIndex faceIndex,
                                       bool cacheDescription )
 {
@@ -537,13 +556,13 @@ FontId FontClient::Plugin::GetFontId( const FontPath& path,
   if( NULL != mFreeTypeLibrary )
   {
     FontId foundId(0);
-    if( FindFont( path, pointSize, faceIndex, foundId ) )
+    if( FindFont( path, requestedPointSize, faceIndex, foundId ) )
     {
       id = foundId;
     }
     else
     {
-      id = CreateFont( path, pointSize, faceIndex, cacheDescription );
+      id = CreateFont( path, requestedPointSize, actualPointSize, faceIndex, cacheDescription );
     }
   }
 
@@ -551,7 +570,8 @@ FontId FontClient::Plugin::GetFontId( const FontPath& path,
 }
 
 FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
-                                      PointSize26Dot6 pointSize,
+                                      PointSize26Dot6 requestedPointSize,
+                                      PointSize26Dot6 actualPointSize,
                                       FaceIndex faceIndex )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetFontId font family(%s)\n", fontDescription.family.c_str() );
@@ -587,21 +607,22 @@ FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
                   validatedFontId );
   }
 
-  // Check if exists a pair 'validatedFontId, pointSize' in the cache.
-  if( !FindFont( validatedFontId, pointSize, fontId ) )
+  // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
+  if( !FindFont( validatedFontId, requestedPointSize, fontId ) )
   {
     // Retrieve the font file name path.
     const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
 
     // Retrieve the font id. Do not cache the description as it has been already cached.
     fontId = GetFontId( description.path,
-                        pointSize,
+                        requestedPointSize,
+                        actualPointSize,
                         faceIndex,
                         false );
 
-    // Cache the pair 'validatedFontId, pointSize' to improve the following queries.
+    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
     mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
-                                             pointSize,
+                                             requestedPointSize,
                                              fontId ) );
   }
 
@@ -629,11 +650,23 @@ void FontClient::Plugin::ValidateFont( const FontDescription& fontDescription,
     // Add the path to the cache.
     mFontDescriptionCache.push_back( description );
 
-    // Cache the index and the font's description.
+    // Cache the index and the matched font's description.
     FontDescriptionCacheItem item( description,
                                    validatedFontId );
 
     mValidatedFontCache.push_back( item );
+
+    if( ( fontDescription.family != description.family ) ||
+        ( fontDescription.width != description.width )   ||
+        ( fontDescription.weight != description.weight ) ||
+        ( fontDescription.slant != description.slant ) )
+    {
+      // Cache the given font's description if it's different than the matched.
+      FontDescriptionCacheItem item( fontDescription,
+                                     validatedFontId );
+
+      mValidatedFontCache.push_back( item );
+    }
   }
   else
   {
@@ -648,28 +681,30 @@ void FontClient::Plugin::ValidateFont( const FontDescription& fontDescription,
 }
 
 void FontClient::Plugin::GetFontMetrics( FontId fontId,
-                                         FontMetrics& metrics,
-                                         int maxFixedSize )
+                                         FontMetrics& metrics )
 {
-  if( fontId > 0 &&
-      fontId-1 < mFontCache.size() )
+  if( ( fontId > 0 ) &&
+      ( fontId - 1u < mFontCache.size() ) )
   {
-    const CacheItem& font = mFontCache[fontId-1];
+    const FontFaceCacheItem& font = mFontCache[fontId-1];
 
     metrics = font.mMetrics;
 
     // Adjust the metrics if the fixed-size font should be down-scaled
-    if( font.mIsFixedSizeBitmap &&
-        ( maxFixedSize > 0 ) &&
-        ( font.mFixedHeightPixels > maxFixedSize ) )
+    if( font.mIsFixedSizeBitmap )
     {
-      float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
+      const float desiredFixedSize =  static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
 
-      metrics.ascender           *= scaleFactor;
-      metrics.descender          *= scaleFactor;
-      metrics.height             *= scaleFactor;
-      metrics.underlinePosition  *= scaleFactor;
-      metrics.underlineThickness *= scaleFactor;
+      if( desiredFixedSize > 0.f )
+      {
+        const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
+
+        metrics.ascender = floorf( metrics.ascender * scaleFactor );
+        metrics.descender = floorf( metrics.descender * scaleFactor );
+        metrics.height = floorf( metrics.height * scaleFactor );
+        metrics.underlinePosition = floorf( metrics.underlinePosition * scaleFactor );
+        metrics.underlineThickness = floorf( metrics.underlineThickness * scaleFactor );
+      }
     }
   }
   else
@@ -696,19 +731,33 @@ GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
 
 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
                                           uint32_t size,
-                                          bool horizontal,
-                                          int maxFixedSize )
+                                          GlyphType type,
+                                          bool horizontal )
+{
+  if( VECTOR_GLYPH == type )
+  {
+    return GetVectorMetrics( array, size, horizontal );
+  }
+
+  return GetBitmapMetrics( array, size, horizontal );
+}
+
+bool FontClient::Plugin::GetBitmapMetrics( GlyphInfo* array,
+                                           uint32_t size,
+                                           bool horizontal )
 {
   bool success( true );
 
   for( unsigned int i=0; i<size; ++i )
   {
-    FontId fontId = array[i].fontId;
+    GlyphInfo& glyph = array[i];
+
+    FontId fontId = glyph.fontId;
 
     if( fontId > 0 &&
         fontId-1 < mFontCache.size() )
     {
-      const CacheItem& font = mFontCache[fontId-1];
+      const FontFaceCacheItem& font = mFontCache[fontId-1];
 
       FT_Face ftFace = font.mFreeTypeFace;
 
@@ -716,28 +765,29 @@ bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
       // Check to see if we should be loading a Fixed Size bitmap?
       if ( font.mIsFixedSizeBitmap )
       {
-        int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_COLOR );
+        int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_COLOR );
         if ( FT_Err_Ok == error )
         {
-          array[i].width = font.mFixedWidthPixels;
-          array[i].height = font.mFixedHeightPixels;
-          array[i].advance = font.mFixedWidthPixels;
-          array[i].xBearing = 0.0f;
-          array[i].yBearing = font.mFixedHeightPixels;
+          glyph.width = font.mFixedWidthPixels;
+          glyph.height = font.mFixedHeightPixels;
+          glyph.advance = font.mFixedWidthPixels;
+          glyph.xBearing = 0.0f;
+          glyph.yBearing = font.mFixedHeightPixels;
 
           // Adjust the metrics if the fixed-size font should be down-scaled
-          if( ( maxFixedSize > 0 ) &&
-              ( font.mFixedHeightPixels > maxFixedSize ) )
+          const float desiredFixedSize =  static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
+
+          if( desiredFixedSize > 0.f )
           {
-            float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
+            const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
 
-            array[i].width    *= scaleFactor;
-            array[i].height   *= scaleFactor;
-            array[i].advance  *= scaleFactor;
-            array[i].xBearing *= scaleFactor;
-            array[i].yBearing *= scaleFactor;
+            glyph.width = floorf( glyph.width * scaleFactor );
+            glyph.height = floorf( glyph.height * scaleFactor );
+            glyph.advance = floorf( glyph.advance * scaleFactor );
+            glyph.xBearing = floorf( glyph.xBearing * scaleFactor );
+            glyph.yBearing = floorf( glyph.yBearing * scaleFactor );
 
-            array[i].scaleFactor = scaleFactor;
+            glyph.scaleFactor = scaleFactor;
           }
         }
         else
@@ -749,21 +799,21 @@ bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
       else
 #endif
       {
-        int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
+        int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_DEFAULT );
 
         if( FT_Err_Ok == error )
         {
-          array[i].width  = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
-          array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
+          glyph.width  = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
+          glyph.height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
           if( horizontal )
           {
-            array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
-            array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
+            glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
+            glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
           }
           else
           {
-            array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
-            array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
+            glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
+            glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
           }
         }
         else
@@ -781,21 +831,61 @@ bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
   return success;
 }
 
-BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
-                                              GlyphIndex glyphIndex )
+bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
+                                           uint32_t size,
+                                           bool horizontal )
 {
-  BufferImage bitmap;
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  bool success( true );
 
-  if( fontId > 0 &&
-      fontId-1 < mFontCache.size() )
+  for( unsigned int i=0; i<size; ++i )
   {
-    FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
+    FontId fontId = array[i].fontId;
+
+    if( fontId > 0 &&
+        fontId-1 < mFontCache.size() )
+    {
+      FontFaceCacheItem& font = mFontCache[fontId-1];
+
+      if( ! font.mVectorFontId )
+      {
+        font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
+      }
+
+      mVectorFontCache->GetGlyphMetrics( font.mVectorFontId, array[i] );
+
+      // Vector metrics are in EMs, convert to pixels
+      const float scale = ( static_cast<float>( font.mRequestedPointSize ) * FROM_266 ) * static_cast<float>( mDpiVertical ) / POINTS_PER_INCH;
+      array[i].width    *= scale;
+      array[i].height   *= scale;
+      array[i].xBearing *= scale;
+      array[i].yBearing *= scale;
+      array[i].advance  *= scale;
+    }
+    else
+    {
+      success = false;
+    }
+  }
+
+  return success;
+#else
+  return false;
+#endif
+}
+
+void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data )
+{
+  if( ( fontId > 0 ) &&
+      ( fontId - 1u < mFontCache.size() ) )
+  {
+    FT_Face ftFace = mFontCache[fontId - 1u].mFreeTypeFace;
 
     FT_Error error;
 
 #ifdef FREETYPE_BITMAP_SUPPORT
     // Check to see if this is fixed size bitmap
-    if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
+    if ( mFontCache[fontId - 1u].mIsFixedSizeBitmap )
     {
       error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
     }
@@ -818,7 +908,7 @@ BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
           if ( FT_Err_Ok == error )
           {
             FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
-            ConvertBitmap( bitmap, bitmapGlyph->bitmap );
+            ConvertBitmap( data, bitmapGlyph->bitmap );
           }
           else
           {
@@ -827,7 +917,7 @@ BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
         }
         else
         {
-          ConvertBitmap( bitmap, ftFace->glyph->bitmap );
+          ConvertBitmap( data, ftFace->glyph->bitmap );
         }
 
         // Created FT_Glyph object must be released with FT_Done_Glyph
@@ -839,11 +929,45 @@ BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
       DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
     }
   }
+}
+
+PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
+                                            GlyphIndex glyphIndex )
+{
+  TextAbstraction::FontClient::GlyphBufferData data;
+
+  CreateBitmap( fontId, glyphIndex, data );
+
+  return PixelData::New( data.buffer,
+                         data.width * data.height * Pixel::GetBytesPerPixel( data.format ),
+                         data.width,
+                         data.height,
+                         data.format,
+                         PixelData::DELETE_ARRAY );
+}
+
+void FontClient::Plugin::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight )
+{
+  blob = NULL;
+  blobLength = 0;
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  if( fontId > 0 &&
+      fontId-1 < mFontCache.size() )
+  {
+    FontFaceCacheItem& font = mFontCache[fontId-1];
 
-  return bitmap;
+    if( ! font.mVectorFontId )
+    {
+      font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
+    }
+
+    mVectorFontCache->GetVectorBlob( font.mVectorFontId, fontId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight );
+  }
+#endif
 }
 
-const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 pointSize )
+const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requestedPointSize )
 {
   // First look into the cache if there is an ellipsis glyph for the requested point size.
   for( Vector<EllipsisItem>::ConstIterator it = mEllipsisCache.Begin(),
@@ -853,7 +977,7 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 pointSize
   {
     const EllipsisItem& item = *it;
 
-    if( fabsf( item.size - pointSize ) < Math::MACHINE_EPSILON_1000 )
+    if( fabsf( item.requestedPointSize - requestedPointSize ) < Math::MACHINE_EPSILON_1000 )
     {
       // Use the glyph in the cache.
       return item.glyph;
@@ -864,22 +988,44 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 pointSize
   mEllipsisCache.PushBack( EllipsisItem() );
   EllipsisItem& item = *( mEllipsisCache.End() - 1u );
 
-  item.size = pointSize;
+  item.requestedPointSize = requestedPointSize;
 
   // Find a font for the ellipsis glyph.
   item.glyph.fontId = FindDefaultFont( ELLIPSIS_CHARACTER,
-                                       pointSize,
+                                       requestedPointSize,
                                        false );
 
   // Set the character index to access the glyph inside the font.
   item.glyph.index = FT_Get_Char_Index( mFontCache[item.glyph.fontId-1].mFreeTypeFace,
                                         ELLIPSIS_CHARACTER );
 
-  GetGlyphMetrics( &item.glyph, 1u, true, 0 );
+  GetBitmapMetrics( &item.glyph, 1u, true );
 
   return item.glyph;
 }
 
+bool FontClient::Plugin::IsColorGlyph( FontId fontId, GlyphIndex glyphIndex )
+{
+  FT_Error error = -1;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+  if( ( fontId > 0 ) &&
+      ( fontId - 1u < mFontCache.size() ) )
+  {
+    const FontFaceCacheItem& item = mFontCache[fontId - 1u];
+    FT_Face ftFace = item.mFreeTypeFace;
+
+    // Check to see if this is fixed size bitmap
+    if( item.mIsFixedSizeBitmap )
+    {
+      error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
+    }
+  }
+#endif
+
+  return FT_Err_Ok == error;
+}
+
 void FontClient::Plugin::InitSystemFonts()
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::InitSystemFonts \n");
@@ -945,6 +1091,7 @@ bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali
     fontDescription.width = IntToWidthType( width );
     fontDescription.weight = IntToWeightType( weight );
     fontDescription.slant = IntToSlantType( slant );
+
     // destroyed the matched pattern
     FcPatternDestroy( match );
     ret = true;
@@ -962,9 +1109,30 @@ FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontDescription& f
   // add a property to the pattern for the font family
   FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontDescription.family.c_str() ) );
 
-  FcPatternAddInteger( fontFamilyPattern, FC_WIDTH, FONT_WIDTH_TYPE_TO_INT[fontDescription.width] );
-  FcPatternAddInteger( fontFamilyPattern, FC_WEIGHT, FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight] );
-  FcPatternAddInteger( fontFamilyPattern, FC_SLANT, FONT_SLANT_TYPE_TO_INT[fontDescription.slant] );
+  int width = FONT_WIDTH_TYPE_TO_INT[fontDescription.width];
+  if( width < 0 )
+  {
+    // Use default.
+    width = DEFAULT_FONT_WIDTH;
+  }
+
+  int weight = FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight];
+  if( weight < 0 )
+  {
+    // Use default.
+    weight = DEFAULT_FONT_WEIGHT;
+  }
+
+  int slant = FONT_SLANT_TYPE_TO_INT[fontDescription.slant];
+  if( slant < 0 )
+  {
+    // Use default.
+    slant = DEFAULT_FONT_SLANT;
+  }
+
+  FcPatternAddInteger( fontFamilyPattern, FC_WIDTH, width );
+  FcPatternAddInteger( fontFamilyPattern, FC_WEIGHT, weight );
+  FcPatternAddInteger( fontFamilyPattern, FC_SLANT, slant );
 
   // Add a property of the pattern, to say we want to match TrueType fonts
   FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
@@ -1044,7 +1212,8 @@ bool FontClient::Plugin::GetFcInt( const _FcPattern* const pattern, const char*
 }
 
 FontId FontClient::Plugin::CreateFont( const FontPath& path,
-                                       PointSize26Dot6 pointSize,
+                                       PointSize26Dot6 requestedPointSize,
+                                       PointSize26Dot6 actualPointSize,
                                        FaceIndex faceIndex,
                                        bool cacheDescription )
 {
@@ -1065,7 +1234,7 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
       // Ensure this size is available
       for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
       {
-        if ( static_cast<FT_Pos>(pointSize) == ftFace->available_sizes[ i ].size )
+        if ( static_cast<FT_Pos>( actualPointSize ) == ftFace->available_sizes[ i ].size )
         {
           // Tell Freetype to use this size
           error = FT_Select_Size( ftFace, i );
@@ -1085,27 +1254,14 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
                                  0.0f,
                                  0.0f );
 
-            mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
+            mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
             id = mFontCache.size();
 
             if( cacheDescription )
             {
-              FontDescription description;
-              description.path = path;
-              description.family = FontFamily( ftFace->family_name );
-
-              // Note FreeType doesn't give too much info to build a proper font style.
-              if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
-              {
-                description.slant = FontSlant::ITALIC;
-              }
-              if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
-              {
-                description.weight = FontWeight::BOLD;
-              }
-
-              mFontDescriptionCache.push_back( description );
+              CacheFontPath( ftFace, id, requestedPointSize, path );
             }
+
             return id;
           }
         }
@@ -1122,15 +1278,15 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
         sizes << ftFace->available_sizes[ i ].size;
       }
       DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
-                       path.c_str(), pointSize, sizes.str().c_str() );
+                       path.c_str(), actualPointSize, sizes.str().c_str() );
     }
     else
     {
       error = FT_Set_Char_Size( ftFace,
-                              0,
-                              pointSize,
-                              mDpiHorizontal,
-                              mDpiVertical );
+                                0,
+                                actualPointSize,
+                                mDpiHorizontal,
+                                mDpiVertical );
 
       if( FT_Err_Ok == error )
       {
@@ -1143,31 +1299,17 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
                              static_cast< float >( ftFace->underline_position ) * FROM_266,
                              static_cast< float >( ftFace->underline_thickness ) * FROM_266 );
 
-        mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) );
+        mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
         id = mFontCache.size();
 
         if( cacheDescription )
         {
-          FontDescription description;
-          description.path = path;
-          description.family = FontFamily( ftFace->family_name );
-
-          // Note FreeType doesn't give too much info to build a proper font style.
-          if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
-          {
-            description.slant = FontSlant::ITALIC;
-          }
-          if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
-          {
-            description.weight = FontWeight::BOLD;
-          }
-
-          mFontDescriptionCache.push_back( description );
+          CacheFontPath( ftFace, id, requestedPointSize, path );
         }
       }
       else
       {
-        DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, pointSize );
+        DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, actualPointSize );
       }
     }
   }
@@ -1179,8 +1321,7 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
   return id;
 }
 
-void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
-                                        FT_Bitmap srcBitmap )
+void FontClient::Plugin::ConvertBitmap( TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap )
 {
   if( srcBitmap.width*srcBitmap.rows > 0 )
   {
@@ -1188,19 +1329,14 @@ void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
     {
       case FT_PIXEL_MODE_GRAY:
       {
-        if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
+        if( srcBitmap.pitch == static_cast<int>( srcBitmap.width ) )
         {
-          destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
-
-          PixelBuffer* destBuffer = destBitmap.GetBuffer();
-          if( destBuffer )
-          {
-            memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
-          }
-          else
-          {
-            DALI_LOG_ERROR( "GetBuffer returns null\n" );
-          }
+          const unsigned int bufferSize = srcBitmap.width * srcBitmap.rows;
+          data.buffer = new unsigned char[bufferSize];
+          data.width = srcBitmap.width;
+          data.height = srcBitmap.rows;
+          data.format = Pixel::L8;
+          memcpy( data.buffer, srcBitmap.buffer, bufferSize );
         }
         break;
       }
@@ -1208,19 +1344,14 @@ void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
 #ifdef FREETYPE_BITMAP_SUPPORT
       case FT_PIXEL_MODE_BGRA:
       {
-        if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
+        if( srcBitmap.pitch == static_cast<int>( srcBitmap.width << 2u ) )
         {
-          destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888 );
-
-          PixelBuffer* destBuffer = destBitmap.GetBuffer();
-          if( destBuffer )
-          {
-            memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows*4 );
-          }
-          else
-          {
-            DALI_LOG_ERROR( "GetBuffer returns null\n" );
-          }
+          const unsigned int bufferSize = srcBitmap.width * srcBitmap.rows * 4u;
+          data.buffer = new unsigned char[bufferSize];
+          data.width = srcBitmap.width;
+          data.height = srcBitmap.rows;
+          data.format = Pixel::BGRA8888;
+          memcpy( data.buffer, srcBitmap.buffer, bufferSize );
         }
         break;
       }
@@ -1235,19 +1366,19 @@ void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
 }
 
 bool FontClient::Plugin::FindFont( const FontPath& path,
-                                   PointSize26Dot6 pointSize,
+                                   PointSize26Dot6 requestedPointSize,
                                    FaceIndex faceIndex,
                                    FontId& fontId ) const
 {
   fontId = 0u;
-  for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
+  for( std::vector<FontFaceCacheItem>::const_iterator it = mFontCache.begin(),
          endIt = mFontCache.end();
        it != endIt;
        ++it, ++fontId )
   {
-    const CacheItem& cacheItem = *it;
+    const FontFaceCacheItem& cacheItem = *it;
 
-    if( cacheItem.mPointSize == pointSize &&
+    if( cacheItem.mRequestedPointSize == requestedPointSize &&
         cacheItem.mFaceIndex == faceIndex &&
         cacheItem.mPath == path )
     {
@@ -1325,7 +1456,7 @@ bool FontClient::Plugin::FindFallbackFontList( const FontDescription& fontDescri
 }
 
 bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
-                                   PointSize26Dot6 pointSize,
+                                   PointSize26Dot6 requestedPointSize,
                                    FontId& fontId )
 {
   fontId = 0u;
@@ -1338,7 +1469,7 @@ bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
     const FontIdCacheItem& item = *it;
 
     if( ( validatedFontId == item.validatedFontId ) &&
-        ( pointSize == item.pointSize ) )
+        ( requestedPointSize == item.requestedPointSize ) )
     {
       fontId = item.fontId;
       return true;
@@ -1448,6 +1579,48 @@ void FontClient::Plugin::GetFixedSizes( const FontDescription& fontDescription,
   FcPatternDestroy( fontFamilyPattern );
 }
 
+void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize,  const FontPath& path )
+{
+  FontDescription description;
+  description.path = path;
+  description.family = FontFamily( ftFace->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( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
+  {
+    description.slant = FontSlant::ITALIC;
+  }
+  if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
+  {
+    description.weight = FontWeight::BOLD;
+  }
+
+  FontDescriptionId validatedFontId = 0u;
+  if( !FindValidatedFont( description,
+                          validatedFontId ) )
+  {
+    // Set the index to the vector of paths to font file names.
+    validatedFontId = mFontDescriptionCache.size();
+
+    // Add the path to the cache.
+    mFontDescriptionCache.push_back( description );
+
+    // Cache the index and the font's description.
+    FontDescriptionCacheItem item( description,
+                                   validatedFontId );
+
+    mValidatedFontCache.push_back( item );
+
+    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
+    mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
+                                             requestedPointSize,
+                                             id ) );
+  }
+}
+
 } // namespace Internal
 
 } // namespace TextAbstraction