[4.0] Support software styling
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / font-client-plugin-impl.cpp
index feaec05..b11fd72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/text-abstraction/font-list.h>
+
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/internal/text-abstraction/font-client-helper.h>
+#include <platform-abstractions/portable/image-operations.h>
 #include <adaptor-impl.h>
 
 // EXTERNAL INCLUDES
@@ -42,6 +44,7 @@ Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New
  */
 const float FROM_266 = 1.0f / 64.0f;
 const float POINTS_PER_INCH = 72.f;
+const FT_Fixed FONT_SLANT_TANGENT = 0.221694663 * 0x10000; // For support software italic
 
 const std::string FONT_FORMAT( "TrueType" );
 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
@@ -51,10 +54,9 @@ const int DEFAULT_FONT_SLANT  =   0; // normal
 
 const uint32_t ELLIPSIS_CHARACTER = 0x2026;
 
-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
@@ -64,9 +66,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
@@ -78,17 +81,20 @@ 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
 
+
+
 using Dali::Vector;
 
 namespace Dali
@@ -136,113 +142,150 @@ FontSlant::Type IntToSlantType( int slant )
   return static_cast<FontSlant::Type>( ValueToIndex( slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u ) );
 }
 
-FontClient::Plugin::FallbackCacheItem::FallbackCacheItem( const FontDescription& font, FontList* list )
-: fontDescription( font ),
-  fallbackFonts( list )
+FontClient::Plugin::FallbackCacheItem::FallbackCacheItem( FontDescription&& font, FontList* fallbackFonts, CharacterSetList* characterSets )
+: fontDescription{ std::move( font ) },
+  fallbackFonts{ fallbackFonts },
+  characterSets{ characterSets }
 {
 }
 
 FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontDescription& fontDescription,
                                                                         FontDescriptionId index )
-: fontDescription( fontDescription ),
-  index( index )
+: fontDescription{ fontDescription },
+  index{ index }
 {
 }
 
-FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
-                                                      PointSize26Dot6 requestedPointSize,
-                                                      FontId fontId )
+FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( FontDescription&& fontDescription,
+                                                                        FontDescriptionId index )
+: fontDescription{ std::move( fontDescription ) },
+  index{ index }
+{
+}
+
+FontClient::Plugin::FontDescriptionSizeCacheItem::FontDescriptionSizeCacheItem( FontDescriptionId validatedFontId,
+                                                                                PointSize26Dot6 requestedPointSize,
+                                                                                FontId fontId )
 : validatedFontId( validatedFontId ),
   requestedPointSize( requestedPointSize ),
   fontId( fontId )
 {
 }
 
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
-                                          const FontPath& path,
-                                          PointSize26Dot6 requestedPointSize,
-                                          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 ),
   mRequestedPointSize( requestedPointSize ),
   mFaceIndex( face ),
   mMetrics( metrics ),
+  mCharacterSet( nullptr ),
   mFixedWidthPixels( 0.0f ),
   mFixedHeightPixels( 0.0f ),
   mVectorFontId( 0 ),
-  mIsFixedSizeBitmap( false )
+  mIsFixedSizeBitmap( false ),
+  mHasColorTables( false )
 {
 }
 
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
-                                          const FontPath& path,
-                                          PointSize26Dot6 requestedPointSize,
-                                          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,
+                                                          bool hasColorTables )
 : mFreeTypeFace( ftFace ),
   mPath( path ),
   mRequestedPointSize( requestedPointSize ),
   mFaceIndex( face ),
   mMetrics( metrics ),
+  mCharacterSet( nullptr ),
   mFixedWidthPixels( fixedWidth ),
   mFixedHeightPixels( fixedHeight ),
   mVectorFontId( 0 ),
-  mIsFixedSizeBitmap( true )
+  mIsFixedSizeBitmap( true ),
+  mHasColorTables( hasColorTables )
 {
 }
 
 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
                             unsigned int verticalDpi )
-: mFreeTypeLibrary( NULL ),
+: mFreeTypeLibrary( nullptr ),
   mDpiHorizontal( horizontalDpi ),
   mDpiVertical( verticalDpi ),
   mDefaultFontDescription(),
   mSystemFonts(),
   mDefaultFonts(),
-  mFontCache(),
+  mFontFaceCache(),
   mValidatedFontCache(),
   mFontDescriptionCache( 1u ),
-  mFontIdCache(),
-  mVectorFontCache( NULL ),
+  mCharacterSetCache(),
+  mFontDescriptionSizeCache(),
+  mVectorFontCache( nullptr ),
   mEllipsisCache(),
   mDefaultFontDescriptionCached( false )
 {
+  mCharacterSetCache.Resize( 1u );
+
   int error = FT_Init_FreeType( &mFreeTypeLibrary );
   if( FT_Err_Ok != error )
   {
-    DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FreeType Init error: %d\n", error );
   }
 
 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
   mVectorFontCache = new VectorFontCache( mFreeTypeLibrary );
 #endif
+
 }
 
 FontClient::Plugin::~Plugin()
 {
-  for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end();
-       it != endIt;
-       ++it )
+  for( auto& item : mFallbackCache )
   {
-    FallbackCacheItem& item = *it;
-
     if( item.fallbackFonts )
     {
       delete item.fallbackFonts;
-      item.fallbackFonts = NULL;
+      delete item.characterSets;
+      item.fallbackFonts = nullptr;
+      item.characterSets = nullptr;
     }
   }
 
 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
   delete mVectorFontCache;
 #endif
-
+  DestroyMatchedPatterns();
   FT_Done_FreeType( mFreeTypeLibrary );
 }
 
+void FontClient::Plugin::ClearCache()
+{
+  mFontFaceCache.clear();
+  mValidatedFontCache.clear();
+  mFontDescriptionCache.clear();
+  mFontDescriptionCache.resize( 1u );
+
+  mCharacterSetCache.Clear();
+  mCharacterSetCache.Resize( 1u );
+
+  mFontDescriptionSizeCache.clear();
+  mFallbackCache.clear();
+
+  mEllipsisCache.Clear();
+  mSystemFonts.clear();
+  mDefaultFonts.clear();
+  mDefaultFontDescriptionCached = false;
+  mDefaultFontCharacterSets.Clear();
+  mDefaultFontDescription = FontDescription();
+  DestroyMatchedPatterns();
+}
+
 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
                                  unsigned int verticalDpi )
 {
@@ -255,9 +298,13 @@ void FontClient::Plugin::ResetSystemDefaults()
   mDefaultFontDescriptionCached = false;
 }
 
-void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList )
+void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::SetFontList family(%s)\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::SetFontList\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
 
   fontList.clear();
 
@@ -266,14 +313,15 @@ void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, Fo
   FcResult result = FcResultMatch;
 
   // Match the pattern.
-  FcFontSet* fontSet = FcFontSort( NULL /* use default configure */,
+  FcFontSet* fontSet = FcFontSort( nullptr /* use default configure */,
                                    fontFamilyPattern,
                                    false /* don't trim */,
-                                   NULL,
+                                   nullptr,
                                    &result );
 
-  if( NULL != fontSet )
+  if( nullptr != fontSet )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  number of fonts found : [%d]\n", fontSet->nfont );
     // Reserve some space to avoid reallocations.
     fontList.reserve( fontSet->nfont );
 
@@ -286,10 +334,14 @@ void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, Fo
       // Skip fonts with no path
       if( GetFcString( fontPattern, FC_FILE, path ) )
       {
+        FcCharSet* characterSet = nullptr;
+        FcPatternGetCharSet( fontPattern, FC_CHARSET, 0u, &characterSet );
+
+        characterSetList.PushBack( characterSet );
         fontList.push_back( FontDescription() );
         FontDescription& newFontDescription = fontList.back();
 
-        newFontDescription.path = path;
+        newFontDescription.path = std::move( path );
 
         int width = 0;
         int weight = 0;
@@ -301,18 +353,29 @@ void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, Fo
         newFontDescription.width = IntToWidthType( width );
         newFontDescription.weight = IntToWeightType( weight );
         newFontDescription.slant = IntToSlantType( slant );
+
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  description; family : [%s]\n", newFontDescription.family.c_str() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", newFontDescription.path.c_str() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[newFontDescription.width] );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[newFontDescription.weight] );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[newFontDescription.slant] );
       }
     }
 
     FcFontSetDestroy( fontSet );
   }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  No fonts found.\n" );
+  }
 
   FcPatternDestroy( fontFamilyPattern );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::SetFontList\n" );
 }
 
 void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetDefaultFonts mDefaultFonts(%s)\n", ( mDefaultFonts.empty()?"empty":"valid" ) );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDefaultFonts\n" );
 
   if( mDefaultFonts.empty() )
   {
@@ -321,26 +384,78 @@ void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
     fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
     fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
     fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
-    SetFontList( fontDescription, mDefaultFonts );
+    SetFontList( fontDescription, mDefaultFonts, mDefaultFontCharacterSets );
   }
 
   defaultFonts = mDefaultFonts;
+
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  number of default fonts : [%d]\n", mDefaultFonts.size() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDefaultFonts\n" );
 }
 
 void FontClient::Plugin::GetDefaultPlatformFontDescription( FontDescription& fontDescription )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetDefaultPlatformFontDescription\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDefaultPlatformFontDescription\n");
 
   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( auto& item : mFallbackCache )
+    {
+      item.characterSets->Clear();
+    }
+
+    for( auto& item : mFontFaceCache )
+    {
+      // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
+      item.mCharacterSet = nullptr;
+    }
+
+    // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
+    FcInitReinitialize();
 
     FcPattern* matchPattern = FcPatternCreate();
-    FcConfigSubstitute(NULL, matchPattern, FcMatchPattern);
-    FcDefaultSubstitute( matchPattern );
 
-    MatchFontDescriptionToPattern( matchPattern, mDefaultFontDescription );
-    FcPatternDestroy( matchPattern );
+    if( matchPattern )
+    {
+      FcConfigSubstitute( nullptr, matchPattern, FcMatchPattern );
+      FcDefaultSubstitute( matchPattern );
+
+      FcCharSet* characterSet = nullptr;
+      MatchFontDescriptionToPattern( matchPattern, mDefaultFontDescription, &characterSet );
+      FcPatternDestroy( matchPattern );
+    }
+
+    // Create again the character sets as they are not valid after FcInitReinitialize()
+
+    for( const auto& description : mDefaultFonts )
+    {
+      mDefaultFontCharacterSets.PushBack( CreateCharacterSetFromDescription( description ) );
+    }
+
+    for( const auto& description : mFontDescriptionCache )
+    {
+      mCharacterSetCache.PushBack( CreateCharacterSetFromDescription( description ) );
+    }
+
+    for( auto& item : mFallbackCache )
+    {
+      if( nullptr != item.fallbackFonts )
+      {
+        if( nullptr == item.characterSets )
+        {
+          item.characterSets = new CharacterSetList;
+        }
+
+        for( const auto& description : *( item.fallbackFonts ) )
+        {
+          item.characterSets->PushBack( CreateCharacterSetFromDescription( description ) );
+        }
+      }
+    }
 
     mDefaultFontDescriptionCached = true;
   }
@@ -350,11 +465,18 @@ void FontClient::Plugin::GetDefaultPlatformFontDescription( FontDescription& fon
   fontDescription.width  = mDefaultFontDescription.width;
   fontDescription.weight = mDefaultFontDescription.weight;
   fontDescription.slant  = mDefaultFontDescription.slant;
+
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDefaultPlatformFontDescription\n");
 }
 
 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetSystemFonts\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetSystemFonts\n");
 
   if( mSystemFonts.empty() )
   {
@@ -362,124 +484,178 @@ void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
   }
 
   systemFonts = mSystemFonts;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  number of system fonts : [%d]\n", mSystemFonts.size() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetSystemFonts\n");
 }
 
 void FontClient::Plugin::GetDescription( FontId id,
                                          FontDescription& fontDescription ) const
 {
-  for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
-         endIt = mFontIdCache.end();
-       it != endIt;
-       ++it )
-  {
-    const FontIdCacheItem& item = *it;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDescription\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", id );
 
+  for( const auto& item : mFontDescriptionSizeCache )
+  {
     if( item.fontId == id )
     {
       fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId );
+
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDescription\n");
       return;
     }
   }
 
-  DALI_LOG_ERROR( "FontClient::Plugin::GetDescription. No description found for the font ID %d\n", id );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  No description found for the font ID %d\n", id );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDescription\n");
 }
 
 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetPointSize\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", id );
   const FontId index = id - 1u;
 
-  if( id > 0u &&
-      index < mFontCache.size() )
+  if( ( id > 0u ) &&
+      ( index < mFontFaceCache.size() ) )
   {
-    return ( *( mFontCache.begin() + index ) ).mRequestedPointSize;
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  point size : %d\n", ( *( mFontFaceCache.begin() + index ) ).mRequestedPointSize );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetPointSize\n");
+    return ( *( mFontFaceCache.begin() + index ) ).mRequestedPointSize;
   }
   else
   {
-    DALI_LOG_ERROR( "FontClient::Plugin::GetPointSize. Invalid font ID %d\n", id );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  Invalid font ID %d\n", id );
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  default point size : %d\n", TextAbstraction::FontClient::DEFAULT_POINT_SIZE );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetPointSize\n");
   return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
 }
 
-FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
-                                                 Character charcode,
-                                                 PointSize26Dot6 requestedPointSize,
-                                                 bool preferColor )
+bool FontClient::Plugin::IsCharacterSupportedByFont( FontId fontId, Character character )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFontForCharacter\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::IsCharacterSupportedByFont\n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "    font id : %d\n", fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  character : %p\n", character );
 
-  FontId fontId(0);
-  bool foundColor(false);
+  if( ( fontId < 1u ) || ( fontId > mFontFaceCache.size() ) )
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  Invalid font id. Number of items in the cache: %d\n",mFontFaceCache.size());
+    DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::IsCharacterSupportedByFont\n");
+    return false;
+  }
 
-  // Traverse the list of fonts.
-  // Check for each default font if supports the character.
+  --fontId;
+
+  bool isSupported = false;
 
-  for( FontList::const_iterator it = fontList.begin(), endIt = fontList.end();
-       it != endIt;
-       ++it )
+  FontFaceCacheItem& cacheItem = mFontFaceCache[fontId];
+
+  if( nullptr == cacheItem.mCharacterSet )
   {
-    const FontDescription& description = *it;
+    // Create again the character set.
+    // It can be null if the ResetSystemDefaults() method has been called.
+
+    FontDescription description;
+    description.path = cacheItem.mPath;
+    description.family = std::move( 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;
+    }
 
-    FcPattern* pattern = CreateFontFamilyPattern( description );
+    cacheItem.mCharacterSet = CreateCharacterSetFromDescription( description );
+  }
 
-    FcResult result = FcResultMatch;
-    FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
+  isSupported = FcCharSetHasChar( cacheItem.mCharacterSet, character );
 
-    FcCharSet* charSet = NULL;
-    FcPatternGetCharSet( match, FC_CHARSET, 0u, &charSet );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false") );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::IsCharacterSupportedByFont\n");
+  return isSupported;
+}
 
-    if( FcCharSetHasChar( charSet, charcode ) )
-    {
-      Vector< PointSize26Dot6 > fixedSizes;
-      GetFixedSizes( description,
-                     fixedSizes );
+FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
+                                                 const CharacterSetList& characterSetList,
+                                                 Character character,
+                                                 PointSize26Dot6 requestedPointSize,
+                                                 bool preferColor )
+{
+  DALI_ASSERT_DEBUG( ( fontList.size() == characterSetList.Count() ) && "FontClient::Plugin::FindFontForCharacter. Different number of fonts and character sets." );
 
-      PointSize26Dot6 actualPointSize = requestedPointSize;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFontForCharacter\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "           character : %p\n", character );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "         preferColor : %s\n", ( preferColor ? "true" : "false" ) );
 
-      const Vector< PointSize26Dot6 >::SizeType count = fixedSizes.Count();
+  FontId fontId = 0u;
+  bool foundColor = false;
 
-      if( 0 != count )
-      {
-        // 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] <= requestedPointSize &&
-              fixedSizes[i] > actualPointSize )
-          {
-            actualPointSize = fixedSizes[i];
-          }
-        }
-      }
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  number of fonts : %d\n", fontList.size() );
 
+  // Traverse the list of fonts.
+  // Check for each font if supports the character.
+  for( unsigned int index = 0u, numberOfFonts = fontList.size(); index < numberOfFonts; ++index )
+  {
+    const FontDescription& description = fontList[index];
+    const FcCharSet* const characterSet = characterSetList[index];
+
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  description; family : [%s]\n", description.family.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", description.path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[description.width] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[description.weight] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[description.slant] );
+
+    bool foundInRanges = false;
+    if( nullptr != characterSet )
+    {
+      foundInRanges = FcCharSetHasChar( characterSet, character );
+    }
+
+    if( foundInRanges )
+    {
       fontId = GetFontId( description,
                           requestedPointSize,
-                          actualPointSize,
                           0u );
 
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "     font id : %d\n", fontId );
+
       if( preferColor )
       {
-        PixelData bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
-        if( bitmap &&
-            Pixel::BGRA8888 == bitmap.GetPixelFormat() )
+        if( ( fontId > 0 ) &&
+            ( fontId - 1u < mFontFaceCache.size() ) )
         {
-          foundColor = true;
+          const FontFaceCacheItem& item = mFontFaceCache[fontId - 1u];
+
+          foundColor = item.mHasColorTables;
         }
+
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  foundColor : %s\n", ( foundColor ? "true" : "false" ) );
       }
 
-      // Keep going unless we prefer a different (color) font
+      // Keep going unless we prefer a different (color) font.
       if( !preferColor || foundColor )
       {
-        FcPatternDestroy( match );
-        FcPatternDestroy( pattern );
         break;
       }
     }
-
-    FcPatternDestroy( match );
-    FcPatternDestroy( pattern );
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFontForCharacter\n" );
   return fontId;
 }
 
@@ -487,7 +663,10 @@ FontId FontClient::Plugin::FindDefaultFont( Character charcode,
                                             PointSize26Dot6 requestedPointSize,
                                             bool preferColor )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindDefaultFont DefaultFontsList(%s)\n", (mDefaultFonts.empty()?"empty":"created") );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindDefaultFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "           character : %p\n", charcode );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "         preferColor : %s\n", ( preferColor ? "true" : "false" ) );
 
   FontId fontId(0);
 
@@ -499,58 +678,86 @@ 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 );
+
+    SetFontList( fontDescription, mDefaultFonts, mDefaultFontCharacterSets );
   }
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  number of default fonts : %d\n", mDefaultFonts.size() );
+
 
   // Traverse the list of default fonts.
   // Check for each default font if supports the character.
-  fontId = FindFontForCharacter( mDefaultFonts, charcode, requestedPointSize, preferColor );
+  fontId = FindFontForCharacter( mDefaultFonts, mDefaultFontCharacterSets, charcode, requestedPointSize, preferColor );
+
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindDefaultFont\n" );
 
   return fontId;
 }
 
-FontId FontClient::Plugin::FindFallbackFont( FontId preferredFont,
-                                             Character charcode,
+FontId FontClient::Plugin::FindFallbackFont( Character charcode,
+                                             const FontDescription& preferredFontDescription,
                                              PointSize26Dot6 requestedPointSize,
                                              bool preferColor )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFallbackFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "           character : %p\n", charcode );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "         preferColor : %s\n", ( preferColor ? "true" : "false" ) );
+
   // 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 );
+
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  preferredFontDescription --> fontDescription\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  [%s] --> [%s]\n", preferredFontDescription.family.c_str(), fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  [%s] --> [%s]\n", FontWeight::Name[preferredFontDescription.weight], FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  [%s] --> [%s]\n", FontWidth::Name[preferredFontDescription.width], FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  [%s] --> [%s]\n", FontSlant::Name[preferredFontDescription.slant], FontSlant::Name[fontDescription.slant] );
 
   // Check first if the font's description has been queried before.
-  FontList* fontList( NULL );
+  FontList* fontList = nullptr;
+  CharacterSetList* characterSetList = nullptr;
 
-  if( !FindFallbackFontList( fontDescription, fontList ) )
+  if( !FindFallbackFontList( fontDescription, fontList, characterSetList ) )
   {
     fontList = new FontList;
-    SetFontList( fontDescription, *fontList );
+    characterSetList = new CharacterSetList;
+
+    SetFontList( fontDescription, *fontList, *characterSetList );
 
     // Add the font-list to the cache.
-    mFallbackCache.push_back( FallbackCacheItem(fontDescription, fontList) );
+    mFallbackCache.push_back( std::move( FallbackCacheItem( std::move( fontDescription ), fontList, characterSetList ) ) );
   }
 
-  if( fontList )
+  if( fontList && characterSetList )
   {
-    fontId = FindFontForCharacter( *fontList, charcode, requestedPointSize, preferColor );
+    fontId = FindFontForCharacter( *fontList, *characterSetList, charcode, requestedPointSize, preferColor );
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFont\n");
   return fontId;
 }
 
 FontId FontClient::Plugin::GetFontId( const FontPath& path,
                                       PointSize26Dot6 requestedPointSize,
-                                      PointSize26Dot6 actualPointSize,
                                       FaceIndex faceIndex,
                                       bool cacheDescription )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetFontId fontPatch:%s\n", path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetFontId\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "                path : [%s]\n", path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
 
   FontId id( 0 );
 
-  if( NULL != mFreeTypeLibrary )
+  if( nullptr != mFreeTypeLibrary )
   {
     FontId foundId(0);
     if( FindFont( path, requestedPointSize, faceIndex, foundId ) )
@@ -559,19 +766,27 @@ FontId FontClient::Plugin::GetFontId( const FontPath& path,
     }
     else
     {
-      id = CreateFont( path, requestedPointSize, actualPointSize, faceIndex, cacheDescription );
+      id = CreateFont( path, requestedPointSize, faceIndex, cacheDescription );
     }
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", id );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetFontId\n" );
+
   return id;
 }
 
 FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
                                       PointSize26Dot6 requestedPointSize,
-                                      PointSize26Dot6 actualPointSize,
                                       FaceIndex faceIndex )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetFontId font family(%s)\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetFontId\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "   requestedPointSize : %d\n", requestedPointSize );
 
   // This method uses three vectors which caches:
   // * Pairs of non validated font descriptions and an index to a vector with paths to font file names.
@@ -597,8 +812,6 @@ FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
   if( !FindValidatedFont( fontDescription,
                           validatedFontId ) )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetFontId Validating Font\n");
-
     // Use font config to validate the font's description.
     ValidateFont( fontDescription,
                   validatedFontId );
@@ -613,45 +826,63 @@ FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
     // Retrieve the font id. Do not cache the description as it has been already cached.
     fontId = GetFontId( description.path,
                         requestedPointSize,
-                        actualPointSize,
                         faceIndex,
                         false );
 
+    mFontFaceCache[fontId-1u].mCharacterSet = mCharacterSetCache[validatedFontId];
+
     // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
-                                             requestedPointSize,
-                                             fontId ) );
+    mFontDescriptionSizeCache.push_back( FontDescriptionSizeCacheItem( validatedFontId,
+                                                                       requestedPointSize,
+                                                                       fontId ) );
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", fontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetFontId\n" );
+
   return fontId;
 }
 
 void FontClient::Plugin::ValidateFont( const FontDescription& fontDescription,
                                        FontDescriptionId& validatedFontId )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::ValidateFont Validating Font family(%s) \n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::ValidateFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
 
   // Create a font pattern.
   FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
 
   FontDescription description;
 
-  bool matched = MatchFontDescriptionToPattern( fontFamilyPattern, description );
+  FcCharSet* characterSet = nullptr;
+  bool matched = MatchFontDescriptionToPattern( fontFamilyPattern, description, &characterSet );
   FcPatternDestroy( fontFamilyPattern );
 
-  if( matched )
+  if( matched && ( nullptr != characterSet ) )
   {
     // Set the index to the vector of paths to font file names.
     validatedFontId = mFontDescriptionCache.size();
 
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  matched description; family : [%s]\n", description.family.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                         path : [%s]\n", description.path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                        width : [%s]\n", FontWidth::Name[description.width] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                       weight : [%s]\n", FontWeight::Name[description.weight] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                        slant : [%s]\n\n", FontSlant::Name[description.slant] );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  validatedFontId : %d\n", validatedFontId );
+
     // Add the path to the cache.
     mFontDescriptionCache.push_back( description );
+    mCharacterSetCache.PushBack( characterSet );
 
     // Cache the index and the matched font's description.
     FontDescriptionCacheItem item( description,
                                    validatedFontId );
 
-    mValidatedFontCache.push_back( item );
+    mValidatedFontCache.push_back( std::move( item ) );
 
     if( ( fontDescription.family != description.family ) ||
         ( fontDescription.width != description.width )   ||
@@ -662,28 +893,24 @@ void FontClient::Plugin::ValidateFont( const FontDescription& fontDescription,
       FontDescriptionCacheItem item( fontDescription,
                                      validatedFontId );
 
-      mValidatedFontCache.push_back( item );
+      mValidatedFontCache.push_back( std::move( item ) );
     }
   }
   else
   {
-    DALI_LOG_ERROR( "FontClient::Plugin::ValidateFont failed for font %s %d %d %d\n",
-                    fontDescription.family.c_str(),
-                    fontDescription.width,
-                    fontDescription.weight,
-                    fontDescription.slant );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  font validation failed for font [%s]\n", fontDescription.family.c_str() );
   }
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::ValidateFont validatedFontId(%u) font family(%s)\n", validatedFontId, fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::ValidateFont\n" );
 }
 
 void FontClient::Plugin::GetFontMetrics( FontId fontId,
                                          FontMetrics& metrics )
 {
   if( ( fontId > 0 ) &&
-      ( fontId - 1u < mFontCache.size() ) )
+      ( fontId - 1u < mFontFaceCache.size() ) )
   {
-    const CacheItem& font = mFontCache[fontId-1];
+    const FontFaceCacheItem& font = mFontFaceCache[fontId-1];
 
     metrics = font.mMetrics;
 
@@ -706,19 +933,19 @@ void FontClient::Plugin::GetFontMetrics( FontId fontId,
   }
   else
   {
-    DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId );
   }
 }
 
 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
                                               Character charcode )
 {
-  GlyphIndex index( 0 );
+  GlyphIndex index = 0u;
 
-  if( fontId > 0 &&
-      fontId-1 < mFontCache.size() )
+  if( ( fontId > 0u ) &&
+      ( fontId - 1u < mFontFaceCache.size() ) )
   {
-    FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
+    FT_Face ftFace = mFontFaceCache[fontId-1u].mFreeTypeFace;
 
     index = FT_Get_Char_Index( ftFace, charcode );
   }
@@ -752,9 +979,9 @@ bool FontClient::Plugin::GetBitmapMetrics( GlyphInfo* array,
     FontId fontId = glyph.fontId;
 
     if( fontId > 0 &&
-        fontId-1 < mFontCache.size() )
+        fontId-1 < mFontFaceCache.size() )
     {
-      const CacheItem& font = mFontCache[fontId-1];
+      const FontFaceCacheItem& font = mFontFaceCache[fontId-1];
 
       FT_Face ftFace = font.mFreeTypeFace;
 
@@ -789,14 +1016,14 @@ bool FontClient::Plugin::GetBitmapMetrics( GlyphInfo* array,
         }
         else
         {
-          DALI_LOG_ERROR( "FreeType Bitmap Load_Glyph error %d\n", error );
+          DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error );
           success = false;
         }
       }
       else
 #endif
       {
-        int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_DEFAULT );
+        int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_NO_AUTOHINT );
 
         if( FT_Err_Ok == error )
         {
@@ -840,9 +1067,9 @@ bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
     FontId fontId = array[i].fontId;
 
     if( fontId > 0 &&
-        fontId-1 < mFontCache.size() )
+        fontId-1 < mFontFaceCache.size() )
     {
-      CacheItem& font = mFontCache[fontId-1];
+      FontFaceCacheItem& font = mFontFaceCache[fontId-1];
 
       if( ! font.mVectorFontId )
       {
@@ -871,32 +1098,42 @@ bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
 #endif
 }
 
-PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
-                                              GlyphIndex glyphIndex )
+void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, bool softwareItalic, bool softwareBold, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
 {
-  PixelData bitmap;
-
-  if( fontId > 0 &&
-      fontId-1 < mFontCache.size() )
+  if( ( fontId > 0 ) &&
+      ( fontId - 1u < mFontFaceCache.size() ) )
   {
-    FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
+    FT_Face ftFace = mFontFaceCache[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 ( mFontFaceCache[fontId - 1u].mIsFixedSizeBitmap )
     {
       error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
     }
     else
 #endif
     {
-      error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
+      error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_NO_AUTOHINT );
     }
     if( FT_Err_Ok == error )
     {
       FT_Glyph glyph;
+
+      if( softwareBold )
+      {
+        FT_GlyphSlot_Embolden(ftFace->glyph);
+      }
+
+      if( softwareItalic )
+      {
+        // FT Matrix uses 16.16 fixed-point format
+        FT_Matrix transform = {0x10000, FONT_SLANT_TANGENT, 0x00000, 0x10000};
+        FT_Outline_Transform(&ftFace->glyph->outline, &transform);
+      }
+
       error = FT_Get_Glyph( ftFace->glyph, &glyph );
 
       // Convert to bitmap if necessary
@@ -904,20 +1141,47 @@ PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
       {
         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 )
           {
-            FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
-            ConvertBitmap( bitmap, bitmapGlyph->bitmap );
+            FT_BitmapGlyph bitmapGlyph = reinterpret_cast< FT_BitmapGlyph >( glyph );
+            ConvertBitmap( data, bitmapGlyph->bitmap );
           }
           else
           {
-            DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
+            DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error );
           }
         }
         else
         {
-          ConvertBitmap( bitmap, ftFace->glyph->bitmap );
+          ConvertBitmap( data, ftFace->glyph->bitmap );
         }
 
         // Created FT_Glyph object must be released with FT_Done_Glyph
@@ -926,23 +1190,35 @@ PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
     }
     else
     {
-      DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error );
     }
   }
+}
 
-  return bitmap;
+PixelData FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
+{
+  TextAbstraction::FontClient::GlyphBufferData data;
+
+  CreateBitmap( fontId, glyphIndex, false, false, data, outlineWidth );
+
+  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;
+  blob = nullptr;
   blobLength = 0;
 
 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
   if( fontId > 0 &&
-      fontId-1 < mFontCache.size() )
+      fontId-1 < mFontFaceCache.size() )
   {
-    CacheItem& font = mFontCache[fontId-1];
+    FontFaceCacheItem& font = mFontFaceCache[fontId-1];
 
     if( ! font.mVectorFontId )
     {
@@ -956,17 +1232,20 @@ 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();
-       it != endIt;
-       ++it )
+  for( const auto& item : mEllipsisCache )
   {
-    const EllipsisItem& item = *it;
-
     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;
     }
   }
@@ -983,22 +1262,56 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requested
                                        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,
+  item.glyph.index = FT_Get_Char_Index( mFontFaceCache[item.glyph.fontId-1].mFreeTypeFace,
                                         ELLIPSIS_CHARACTER );
 
   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;
 }
 
+bool FontClient::Plugin::IsColorGlyph( FontId fontId, GlyphIndex glyphIndex )
+{
+  FT_Error error = -1;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+  if( ( fontId > 0 ) &&
+      ( fontId - 1u < mFontFaceCache.size() ) )
+  {
+    const FontFaceCacheItem& item = mFontFaceCache[fontId - 1u];
+    FT_Face ftFace = item.mFreeTypeFace;
+
+    // Check to see if this is fixed size bitmap
+    if( item.mHasColorTables )
+    {
+      error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
+    }
+  }
+#endif
+
+  return FT_Err_Ok == error;
+}
+
+bool FontClient::Plugin::AddCustomFontDirectory( const FontPath& path )
+{
+  // nullptr as first parameter means the current configuration is used.
+  return FcConfigAppFontAddDir( nullptr, reinterpret_cast<const FcChar8 *>( path.c_str() ) );
+}
+
 void FontClient::Plugin::InitSystemFonts()
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::InitSystemFonts \n");
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::InitSystemFonts\n" );
 
   FcFontSet* fontSet = GetFcFontSet();
 
   if( fontSet )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  number of system fonts : %d\n", fontSet->nfont );
+
     // Reserve some space to avoid reallocations.
     mSystemFonts.reserve( fontSet->nfont );
 
@@ -1014,7 +1327,7 @@ void FontClient::Plugin::InitSystemFonts()
         mSystemFonts.push_back( FontDescription() );
         FontDescription& fontDescription = mSystemFonts.back();
 
-        fontDescription.path = path;
+        fontDescription.path = std::move( path );
 
         int width = 0;
         int weight = 0;
@@ -1026,62 +1339,112 @@ void FontClient::Plugin::InitSystemFonts()
         fontDescription.width = IntToWidthType( width );
         fontDescription.weight = IntToWeightType( weight );
         fontDescription.slant = IntToSlantType( slant );
-        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::InitSystemFonts font family(%s)\n", fontDescription.family.c_str() );
 
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  description; family : [%s]\n", fontDescription.family.c_str() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
       }
     }
 
     FcFontSetDestroy( fontSet );
   }
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::InitSystemFonts\n" );
 }
 
-bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription )
+bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::MatchFontDescriptionToPattern\n" );
+
   FcResult result = FcResultMatch;
-  FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
+  FcPattern* match = FcFontMatch( nullptr /* use default configure */, pattern, &result );
 
-  bool ret = false;
+  const bool matched = nullptr != match;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  pattern matched : %s\n", ( matched ? "true" : "false" ) );
 
-  if( match )
+  if( matched )
   {
     int width = 0;
     int weight = 0;
     int slant = 0;
     GetFcString( match, FC_FILE, fontDescription.path );
     GetFcString( match, FC_FAMILY, fontDescription.family );
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::MatchFontDescriptionToPattern matched:%s \n", fontDescription.family.c_str());
     GetFcInt( match, FC_WIDTH, width );
     GetFcInt( match, FC_WEIGHT, weight );
     GetFcInt( match, FC_SLANT, slant );
     fontDescription.width = IntToWidthType( width );
     fontDescription.weight = IntToWeightType( weight );
     fontDescription.slant = IntToSlantType( slant );
+
+    // Cache the character ranges.
+    FcPatternGetCharSet( match, FC_CHARSET, 0u, characterSet );
+
     // destroyed the matched pattern
     FcPatternDestroy( match );
-    ret = true;
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
   }
-  return ret;
-}
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::MatchFontDescriptionToPattern\n" );
+  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
   FcPattern* fontFamilyPattern = FcPatternCreate();
 
+  if( !fontFamilyPattern )
+  {
+    return nullptr;
+  }
+
   // 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] );
+  // add a property to the pattern for local setting.
+  const char* locale = setlocale( LC_MESSAGES, nullptr );
+  if( locale != nullptr)
+  {
+    FcPatternAddString( fontFamilyPattern, FC_LANG, reinterpret_cast<const FcChar8*>( locale ) );
+  }
+
+  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() ) );
 
   // modify the config, with the mFontFamilyPatterm
-  FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
+  FcConfigSubstitute( nullptr /* use default configure */, fontFamilyPattern, FcMatchPattern );
 
   // provide default values for unspecified properties in the font pattern
   // e.g. patterns without a specified style or weight are set to Medium
@@ -1108,7 +1471,7 @@ _FcFontSet* FontClient::Plugin::GetFcFontSet() const
 
   // get a list of fonts
   // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
-  FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
+  FcFontSet* fontset = FcFontList( nullptr /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
 
   // clear up the object set
   if( objectSet )
@@ -1128,7 +1491,7 @@ bool FontClient::Plugin::GetFcString( const FcPattern* const pattern,
                                       const char* const n,
                                       std::string& string )
 {
-  FcChar8* file = NULL;
+  FcChar8* file = nullptr;
   const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
 
   if( FcResultMatch == retVal )
@@ -1156,11 +1519,14 @@ bool FontClient::Plugin::GetFcInt( const _FcPattern* const pattern, const char*
 
 FontId FontClient::Plugin::CreateFont( const FontPath& path,
                                        PointSize26Dot6 requestedPointSize,
-                                       PointSize26Dot6 actualPointSize,
                                        FaceIndex faceIndex,
                                        bool cacheDescription )
 {
-  FontId id( 0 );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::CreateFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "                path : [%s]\n", path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+
+  FontId id = 0u;
 
   // Create & cache new font face
   FT_Face ftFace;
@@ -1171,63 +1537,68 @@ FontId FontClient::Plugin::CreateFont( const FontPath& path,
 
   if( FT_Err_Ok == error )
   {
+    // Check if a font is scalable.
+    const bool isScalable = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_SCALABLE ) );
+    const bool hasFixedSizedBitmaps = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) && ( 0 != ftFace->num_fixed_sizes );
+    const bool hasColorTables = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_COLOR ) );
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "            isScalable : [%s]\n", ( isScalable ? "true" : "false" ) );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  hasFixedSizedBitmaps : [%s]\n", ( hasFixedSizedBitmaps ? "true" : "false" ) );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "        hasColorTables : [%s]\n", ( hasColorTables ? "true" : "false" ) );
+
     // Check to see if the font contains fixed sizes?
-    if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
+    if( !isScalable && hasFixedSizedBitmaps )
     {
-      // Ensure this size is available
-      for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
+      PointSize26Dot6 actualPointSize = 0u;
+      int fixedSizeIndex = 0;
+      for( ; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex )
       {
-        if ( static_cast<FT_Pos>( actualPointSize ) == ftFace->available_sizes[ i ].size )
-        {
-          // Tell Freetype to use this size
-          error = FT_Select_Size( ftFace, i );
-          if ( FT_Err_Ok != error )
-          {
-            DALI_LOG_ERROR( "FreeType Select_Size error: %d\n", error );
-          }
-          else
-          {
-            float fixedWidth  = static_cast< float >( ftFace->available_sizes[ i ].width );
-            float fixedHeight = static_cast< float >( ftFace->available_sizes[ i ].height );
+        const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size;
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  size index : %d, size : %d\n", fixedSizeIndex, fixedSize );
 
-            // Indicate that the font is a fixed sized bitmap
-            FontMetrics metrics( fixedHeight, // The ascender in pixels.
-                                 0.0f,
-                                 fixedHeight, // The height in pixels.
-                                 0.0f,
-                                 0.0f );
+        if( fixedSize >= requestedPointSize )
+        {
+          actualPointSize = fixedSize;
+          break;
+        }
+      }
 
-            mFontCache.push_back( CacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
-            id = mFontCache.size();
+      if( 0u == actualPointSize )
+      {
+        // The requested point size is bigger than the bigest fixed size.
+        fixedSizeIndex = ftFace->num_fixed_sizes - 1;
+        actualPointSize = ftFace->available_sizes[fixedSizeIndex].size;
+      }
 
-            if( cacheDescription )
-            {
-              CacheFontPath( ftFace, id, requestedPointSize, path );
-            }
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize );
 
-            return id;
-          }
-        }
+      // Tell Freetype to use this size
+      error = FT_Select_Size( ftFace, fixedSizeIndex );
+      if ( FT_Err_Ok != error )
+      {
+        DALI_LOG_INFO( gLogFilter, Debug::General, "FreeType Select_Size error: %d\n", error );
       }
-
-      // Can't find this size
-      std::stringstream sizes;
-      for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
+      else
       {
-        if ( i )
-        {
-          sizes << ", ";
-        }
-        sizes << ftFace->available_sizes[ i ].size;
+        float fixedWidth  = static_cast< float >( ftFace->available_sizes[ fixedSizeIndex ].width );
+        float fixedHeight = static_cast< float >( ftFace->available_sizes[ fixedSizeIndex ].height );
+
+        // Indicate that the font is a fixed sized bitmap
+        FontMetrics metrics( fixedHeight, // The ascender in pixels.
+                             0.0f,
+                             fixedHeight, // The height in pixels.
+                             0.0f,
+                             0.0f );
+
+        mFontFaceCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight, hasColorTables ) );
+        id = mFontFaceCache.size();
       }
-      DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
-                       path.c_str(), actualPointSize, sizes.str().c_str() );
     }
     else
     {
       error = FT_Set_Char_Size( ftFace,
                                 0,
-                                actualPointSize,
+                                requestedPointSize,
                                 mDpiHorizontal,
                                 mDpiVertical );
 
@@ -1242,30 +1613,35 @@ 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, requestedPointSize, faceIndex, metrics ) );
-        id = mFontCache.size();
-
-        if( cacheDescription )
-        {
-          CacheFontPath( ftFace, id, requestedPointSize, path );
-        }
+        mFontFaceCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
+        id = mFontFaceCache.size();
       }
       else
       {
-        DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, actualPointSize );
+        DALI_LOG_INFO( gLogFilter, Debug::General, "  FreeType Set_Char_Size error: %d for pointSize %d\n", error, requestedPointSize );
+      }
+    }
+
+    if( 0u != id )
+    {
+      if( cacheDescription )
+      {
+        CacheFontPath( ftFace, id, requestedPointSize, path );
       }
     }
   }
   else
   {
-    DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  FreeType New_Face error: %d for [%s]\n", error, path.c_str() );
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font id : %d\n", id );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::CreateFont\n" );
+
   return id;
 }
 
-void FontClient::Plugin::ConvertBitmap( PixelData& destBitmap,
-                                        FT_Bitmap srcBitmap )
+void FontClient::Plugin::ConvertBitmap( TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap )
 {
   if( srcBitmap.width*srcBitmap.rows > 0 )
   {
@@ -1273,12 +1649,14 @@ void FontClient::Plugin::ConvertBitmap( PixelData& destBitmap,
     {
       case FT_PIXEL_MODE_GRAY:
       {
-        if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
+        if( srcBitmap.pitch == static_cast<int>( srcBitmap.width ) )
         {
-          unsigned int bufferSize( srcBitmap.width * srcBitmap.rows );
-          unsigned char* buffer = new unsigned char[bufferSize];
-          memcpy( buffer, srcBitmap.buffer,bufferSize );
-          destBitmap = PixelData::New( buffer, bufferSize, srcBitmap.width, srcBitmap.rows, Pixel::L8, PixelData::DELETE_ARRAY );
+          const unsigned int bufferSize = srcBitmap.width * srcBitmap.rows;
+          data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
+          data.width = srcBitmap.width;
+          data.height = srcBitmap.rows;
+          data.format = Pixel::L8;
+          memcpy( data.buffer, srcBitmap.buffer, bufferSize );
         }
         break;
       }
@@ -1286,19 +1664,42 @@ void FontClient::Plugin::ConvertBitmap( PixelData& 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 ) )
         {
-          unsigned int bufferSize( srcBitmap.width * srcBitmap.rows * 4 );
-          unsigned char* buffer = new unsigned char[bufferSize];
-          memcpy( buffer, srcBitmap.buffer,bufferSize );
-          destBitmap = PixelData::New( buffer, bufferSize, srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888, PixelData::DELETE_ARRAY );
+          // Set the input dimensions.
+          const ImageDimensions inputDimensions( srcBitmap.width, srcBitmap.rows );
+
+          // Set the output dimensions.
+          // If the output dimension is not given, the input dimension is set
+          // and won't be downscaling.
+          data.width = ( data.width == 0 ) ? srcBitmap.width : data.width;
+          data.height = ( data.height == 0 ) ? srcBitmap.rows : data.height;
+          const ImageDimensions desiredDimensions( data.width, data.height );
+
+          // Creates the output buffer
+          const unsigned int bufferSize = data.width * data.height * 4u;
+          data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
+
+          if( inputDimensions == desiredDimensions )
+          {
+            // There isn't downscaling.
+            memcpy( data.buffer, srcBitmap.buffer, bufferSize );
+          }
+          else
+          {
+            Dali::Internal::Platform::LanczosSample4BPP( srcBitmap.buffer,
+                                                         inputDimensions,
+                                                         data.buffer,
+                                                         desiredDimensions );
+          }
+          data.format = Pixel::BGRA8888;
         }
         break;
       }
 #endif
       default:
       {
-        DALI_LOG_ERROR( "FontClient Unable to create Bitmap of this PixelType\n" );
+        DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::ConvertBitmap. FontClient Unable to create Bitmap of this PixelType\n" );
         break;
       }
     }
@@ -1310,40 +1711,48 @@ bool FontClient::Plugin::FindFont( const FontPath& path,
                                    FaceIndex faceIndex,
                                    FontId& fontId ) const
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "                path : [%s]\n", path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  number of fonts in the cache : %d\n", mFontFaceCache.size() );
+
   fontId = 0u;
-  for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
-         endIt = mFontCache.end();
-       it != endIt;
-       ++it, ++fontId )
+  for( const auto& cacheItem : mFontFaceCache )
   {
-    const CacheItem& cacheItem = *it;
-
+    ++fontId;
     if( cacheItem.mRequestedPointSize == requestedPointSize &&
         cacheItem.mFaceIndex == faceIndex &&
         cacheItem.mPath == path )
     {
-      ++fontId;
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  font found, id : %d\n", fontId );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
+
       return true;
     }
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font not found\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
+
+  fontId = 0u;
   return false;
 }
 
 bool FontClient::Plugin::FindValidatedFont( const FontDescription& fontDescription,
                                             FontDescriptionId& validatedFontId )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindValidatedFont fontDescription family(%s)\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindValidatedFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  number of validated fonts in the cache : %d\n", mValidatedFontCache.size() );
 
   validatedFontId = 0u;
 
-  for( std::vector<FontDescriptionCacheItem>::const_iterator it = mValidatedFontCache.begin(),
-         endIt = mValidatedFontCache.end();
-       it != endIt;
-       ++it )
+  for( const auto& item : mValidatedFontCache )
   {
-    const FontDescriptionCacheItem& item = *it;
-
     if( !fontDescription.family.empty() &&
         ( fontDescription.family == item.fontDescription.family ) &&
         ( fontDescription.width == item.fontDescription.width ) &&
@@ -1352,30 +1761,33 @@ bool FontClient::Plugin::FindValidatedFont( const FontDescription& fontDescripti
     {
       validatedFontId = item.index;
 
-      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindValidatedFont validated font family(%s) font id (%u) \n", fontDescription.family.c_str(), validatedFontId );
-
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  validated font found, id : %d\n", validatedFontId );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindValidatedFont\n" );
       return true;
     }
   }
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindValidatedFont NOT VALIDATED return false\n" );
-
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  validated font not found\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindValidatedFont\n" );
   return false;
 }
 
 bool FontClient::Plugin::FindFallbackFontList( const FontDescription& fontDescription,
-                                               FontList*& fontList )
+                                               FontList*& fontList,
+                                               CharacterSetList*& characterSetList )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFallbackFontList fontDescription family(%s)\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFallbackFontList\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                 path : [%s]\n", fontDescription.path.c_str() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                width : [%s]\n", FontWidth::Name[fontDescription.width] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "               weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "                slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  number of fallback font lists in the cache : %d\n", mFallbackCache.size() );
 
-  fontList = NULL;
+  fontList = nullptr;
 
-  for( std::vector<FallbackCacheItem>::const_iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end();
-       it != endIt;
-       ++it )
+  for( const auto& item : mFallbackCache )
   {
-    const FallbackCacheItem& item = *it;
-
     if( !fontDescription.family.empty() &&
         ( fontDescription.family == item.fontDescription.family ) &&
         ( fontDescription.width == item.fontDescription.width ) &&
@@ -1383,15 +1795,16 @@ bool FontClient::Plugin::FindFallbackFontList( const FontDescription& fontDescri
         ( fontDescription.slant == item.fontDescription.slant ) )
     {
       fontList = item.fallbackFonts;
+      characterSetList = item.characterSets;
 
-      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFallbackFontList font family(%s) font-list (%p) \n", fontDescription.family.c_str(), fontList );
-
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  fallback font list found.\n" );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFontList\n" );
       return true;
     }
   }
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFallbackFontList NOT FOUND return false\n" );
-
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  fallback font list not found.\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFontList\n" );
   return false;
 }
 
@@ -1399,28 +1812,34 @@ bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
                                    PointSize26Dot6 requestedPointSize,
                                    FontId& fontId )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFont\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "    validatedFontId  : %d\n", validatedFontId );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize );
+
   fontId = 0u;
 
-  for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
-         endIt = mFontIdCache.end();
-       it != endIt;
-       ++it )
+  for( const auto& item : mFontDescriptionSizeCache )
   {
-    const FontIdCacheItem& item = *it;
-
     if( ( validatedFontId == item.validatedFontId ) &&
         ( requestedPointSize == item.requestedPointSize ) )
     {
       fontId = item.fontId;
+
+      DALI_LOG_INFO( gLogFilter, Debug::General, "  font found, id : %d\n", fontId );
+      DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
       return true;
     }
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "  font not found.\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
   return false;
 }
 
 bool FontClient::Plugin::IsScalable( const FontPath& path )
 {
+  bool isScalable = false;
+
   FT_Face ftFace;
   int error = FT_New_Face( mFreeTypeLibrary,
                            path.c_str(),
@@ -1428,9 +1847,14 @@ bool FontClient::Plugin::IsScalable( const FontPath& path )
                            &ftFace );
   if( FT_Err_Ok != error )
   {
-    DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: %s\n", path.c_str() );
+  }
+  else
+  {
+    isScalable = ftFace->face_flags & FT_FACE_FLAG_SCALABLE;
   }
-  return ( ftFace->num_fixed_sizes == 0 );
+
+  return isScalable;
 }
 
 bool FontClient::Plugin::IsScalable( const FontDescription& fontDescription )
@@ -1441,8 +1865,8 @@ bool FontClient::Plugin::IsScalable( const FontDescription& fontDescription )
   FcResult result = FcResultMatch;
 
   // match the pattern
-  FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
-  bool isScalable = true;
+  FcPattern* match = FcFontMatch( nullptr /* use default configure */, fontFamilyPattern, &result );
+  bool isScalable = false;
 
   if( match )
   {
@@ -1453,11 +1877,7 @@ bool FontClient::Plugin::IsScalable( const FontDescription& fontDescription )
   }
   else
   {
-    DALI_LOG_ERROR( "FreeType Cannot check font: %s %d %d %d\n",
-                    fontDescription.family.c_str(),
-                    fontDescription.width,
-                    fontDescription.weight,
-                    fontDescription.slant );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str() );
   }
   FcPatternDestroy( fontFamilyPattern );
   FcPatternDestroy( match );
@@ -1476,7 +1896,7 @@ void FontClient::Plugin::GetFixedSizes( const FontPath& path, Vector< PointSize2
                            &ftFace );
   if( FT_Err_Ok != error )
   {
-    DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font path : [%s]\n", path.c_str() );
   }
 
   // Fetch the number of fixed sizes available
@@ -1498,7 +1918,7 @@ void FontClient::Plugin::GetFixedSizes( const FontDescription& fontDescription,
   FcResult result = FcResultMatch;
 
   // match the pattern
-  FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
+  FcPattern* match = FcFontMatch( nullptr /* use default configure */, fontFamilyPattern, &result );
 
   if( match )
   {
@@ -1509,11 +1929,7 @@ void FontClient::Plugin::GetFixedSizes( const FontDescription& fontDescription,
   }
   else
   {
-    DALI_LOG_ERROR( "FreeType Cannot check font: %s %d %d %d\n",
-                    fontDescription.family.c_str(),
-                    fontDescription.width,
-                    fontDescription.weight,
-                    fontDescription.slant );
+    DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str() );
   }
   FcPatternDestroy( match );
   FcPatternDestroy( fontFamilyPattern );
@@ -1523,10 +1939,10 @@ void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Do
 {
   FontDescription description;
   description.path = path;
-  description.family = FontFamily( ftFace->family_name );
-  description.weight = FontWeight::NORMAL;
-  description.width = FontWidth::NORMAL;
-  description.slant = FontSlant::NORMAL;
+  description.family = std::move( 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 )
@@ -1545,20 +1961,63 @@ void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Do
     // Set the index to the vector of paths to font file names.
     validatedFontId = mFontDescriptionCache.size();
 
+    FcPattern* pattern = CreateFontFamilyPattern( description );
+
+    FcResult result = FcResultMatch;
+    FcPattern* match = FcFontMatch( nullptr, pattern, &result );
+
+    FcCharSet* characterSet = nullptr;
+    FcPatternGetCharSet( match, FC_CHARSET, 0u, &characterSet );
+
+    FcPatternDestroy( pattern );
+
+    mMatchedFcPatternCache.PushBack( match );
+
+    mFontFaceCache[id-1u].mCharacterSet = characterSet;
+
     // Add the path to the cache.
     mFontDescriptionCache.push_back( description );
+    mCharacterSetCache.PushBack( characterSet );
 
     // Cache the index and the font's description.
-    FontDescriptionCacheItem item( description,
-                                   validatedFontId );
-
-    mValidatedFontCache.push_back( item );
+    mValidatedFontCache.push_back( std::move( FontDescriptionCacheItem( std::move( description ),
+                                                                        validatedFontId) ) );
 
     // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
-                                             requestedPointSize,
-                                             id ) );
+    mFontDescriptionSizeCache.push_back( FontDescriptionSizeCacheItem( validatedFontId,
+                                                                       requestedPointSize,
+                                                                       id ) );
+  }
+}
+
+FcCharSet* FontClient::Plugin::CreateCharacterSetFromDescription( const FontDescription& description )
+{
+  FcCharSet* characterSet = nullptr;
+
+  FcPattern* pattern = CreateFontFamilyPattern( description );
+
+  if( nullptr != pattern )
+  {
+    FcResult result = FcResultMatch;
+    FcPattern* match = FcFontMatch( nullptr, pattern, &result );
+
+    FcPatternGetCharSet( match, FC_CHARSET, 0u, &characterSet );
+
+    mMatchedFcPatternCache.PushBack( match );
+
+    FcPatternDestroy( pattern );
+  }
+
+  return characterSet;
+}
+
+void FontClient::Plugin::DestroyMatchedPatterns()
+{
+  for (auto & object : mMatchedFcPatternCache)
+  {
+    FcPatternDestroy(reinterpret_cast<FcPattern*>(object));
   }
+  mMatchedFcPatternCache.Clear();
 }
 
 } // namespace Internal