Create glyph bitmap without copy if single color
[platform/core/uifw/dali-adaptor.git] / dali / internal / text / text-abstraction / plugin / font-client-plugin-impl.cpp
index a7e025c..6c0c264 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/imaging/common/image-operations.h>
+#include <dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h>
+#include <dali/internal/text/text-abstraction/plugin/embedded-item.h>
 #include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+#include <dali/internal/text/text-abstraction/plugin/font-face-cache-item.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/vector-wrapper.h>
 
@@ -88,11 +91,7 @@ const uint32_t ELLIPSIS_CHARACTER = 0x2026;
 using Dali::Vector;
 using namespace std;
 
-namespace Dali
-{
-namespace TextAbstraction
-{
-namespace Internal
+namespace Dali::TextAbstraction::Internal
 {
 /**
  * @brief Free the resources allocated by the FcCharSet objects.
@@ -249,58 +248,10 @@ FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem(FontDescr
 {
 }
 
-FontClient::Plugin::FontDescriptionSizeCacheItem::FontDescriptionSizeCacheItem(FontDescriptionId validatedFontId,
-                                                                               PointSize26Dot6   requestedPointSize,
-                                                                               FontId            fontId)
-: validatedFontId(validatedFontId),
-  requestedPointSize(requestedPointSize),
-  fontId(fontId)
-{
-}
-
-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),
-  mFixedSizeIndex(0),
-  mFixedWidthPixels(0.f),
-  mFixedHeightPixels(0.f),
-  mVectorFontId(0u),
-  mFontId(0u),
-  mIsFixedSizeBitmap(false),
-  mHasColorTables(false)
-{
-}
-
-FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem(FT_Face            ftFace,
-                                                         const FontPath&    path,
-                                                         PointSize26Dot6    requestedPointSize,
-                                                         FaceIndex          face,
-                                                         const FontMetrics& metrics,
-                                                         int                fixedSizeIndex,
-                                                         float              fixedWidth,
-                                                         float              fixedHeight,
-                                                         bool               hasColorTables)
-: mFreeTypeFace(ftFace),
-  mPath(path),
-  mRequestedPointSize(requestedPointSize),
-  mFaceIndex(face),
-  mMetrics(metrics),
-  mCharacterSet(nullptr),
-  mFixedSizeIndex(fixedSizeIndex),
-  mFixedWidthPixels(fixedWidth),
-  mFixedHeightPixels(fixedHeight),
-  mVectorFontId(0u),
-  mFontId(0u),
-  mIsFixedSizeBitmap(true),
-  mHasColorTables(hasColorTables)
+FontClient::Plugin::FontDescriptionSizeCacheKey::FontDescriptionSizeCacheKey(FontDescriptionId fontDescriptionId,
+                                                                             PointSize26Dot6   requestedPointSize)
+: fontDescriptionId(fontDescriptionId),
+  requestedPointSize(requestedPointSize)
 {
 }
 
@@ -346,6 +297,9 @@ FontClient::Plugin::~Plugin()
   DestroyCharacterSets(mCharacterSetCache);
   ClearCharacterSetFromFontFaceCache();
 
+  // Clear FontFaceCache here. Due to we sould deallocate FT_Faces before done freetype library
+  mFontFaceCache.clear();
+
 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
   delete mVectorFontCache;
 #endif
@@ -377,6 +331,7 @@ void FontClient::Plugin::ClearCache()
   mCharacterSetCache.Clear();
 
   mFontDescriptionSizeCache.clear();
+  mFontDescriptionSizeCache.rehash(0); // Note : unordered_map.clear() didn't deallocate memory
 
   mEllipsisCache.Clear();
   mPixelBufferCache.clear();
@@ -525,8 +480,39 @@ void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& font
       FcDefaultSubstitute(matchPattern);
 
       FcCharSet* characterSet = nullptr;
-      MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet);
+      bool       matched      = MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet);
+
+      // Caching the default font description
+      if(matched)
+      {
+        // Copy default font description info.
+        // Due to the type changed, we need to make some temperal font description.
+        FontDescription tempFontDescription = mDefaultFontDescription;
+
+        // Add the path to the cache.
+        tempFontDescription.type = FontDescription::FACE_FONT;
+        mFontDescriptionCache.push_back(tempFontDescription);
+
+        // Set the index to the vector of paths to font file names.
+        const FontDescriptionId fontDescriptionId = mFontDescriptionCache.size();
+
+        FONT_LOG_DESCRIPTION(tempFontDescription, "default platform font");
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  default font fontDescriptionId : %d\n", fontDescriptionId);
+
+        // Cache the index and the matched font's description.
+        FontDescriptionCacheItem item(tempFontDescription,
+                                      fontDescriptionId);
+
+        mValidatedFontCache.push_back(std::move(item));
+      }
+      else
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  default font validation failed for font [%s]\n", mDefaultFontDescription.family.c_str());
+      }
+
       // Decrease the reference counter of the character set as it's not stored.
+      // Note. the cached default font description will increase reference counter by
+      // mFontDescriptionCache. So we can decrease reference counter here.
       FcCharSetDestroy(characterSet);
 
       // Destroys the pattern created.
@@ -602,9 +588,9 @@ void FontClient::Plugin::GetDescription(FontId           id,
       {
         for(const auto& item : mFontDescriptionSizeCache)
         {
-          if(item.fontId == fontIdCacheItem.id)
+          if(item.second == fontIdCacheItem.index)
           {
-            fontDescription = *(mFontDescriptionCache.begin() + item.validatedFontId - 1u);
+            fontDescription = *(mFontDescriptionCache.begin() + item.first.fontDescriptionId - 1u);
 
             FONT_LOG_DESCRIPTION(fontDescription, "");
             return;
@@ -615,7 +601,7 @@ void FontClient::Plugin::GetDescription(FontId           id,
       case FontDescription::BITMAP_FONT:
       {
         fontDescription.type   = FontDescription::BITMAP_FONT;
-        fontDescription.family = mBitmapFontCache[fontIdCacheItem.id].font.name;
+        fontDescription.family = mBitmapFontCache[fontIdCacheItem.index].font.name;
         break;
       }
       default:
@@ -634,37 +620,16 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id)
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", id);
-  const FontId index = id - 1u;
 
-  if((id > 0u) &&
-     (index < mFontIdCache.Count()))
+  PointSize26Dot6               pointSize     = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(id);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  point size : %d\n", (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize);
-        return (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid font ID %d\n", id);
+    pointSize = fontCacheItem->GetPointSize();
   }
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  point size : %d\n", pointSize);
 
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  default point size : %d\n", TextAbstraction::FontClient::DEFAULT_POINT_SIZE);
-  return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  return pointSize;
 }
 
 bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character)
@@ -673,77 +638,40 @@ bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character cha
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "    font id : %d\n", fontId);
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  character : %p\n", character);
 
-  if((fontId < 1u) || (fontId > mFontIdCache.Count()))
+  bool isSupported   = false;
+  auto fontCacheItem = const_cast<FontCacheItemInterface*>(GetCachedFontItem(fontId));
+  if(fontCacheItem != nullptr)
   {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid font id. Number of items in the cache: %d\n", mFontIdCache.Count());
-    return false;
+    isSupported = fontCacheItem->IsCharacterSupported(character); // May cache
   }
 
-  --fontId;
-
-  bool isSupported = false;
-
-  const FontIdCacheItem& fontIdCacheItem = mFontIdCache[fontId];
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false"));
+  return isSupported;
+}
 
-  switch(fontIdCacheItem.type)
+const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId id) const
+{
+  const FontCacheIndex index = id - 1u;
+  if((id > 0u) && (index < mFontIdCache.Count()))
   {
-    case FontDescription::FACE_FONT:
+    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+    switch(fontIdCacheItem.type)
     {
-      if(fontIdCacheItem.id < mFontFaceCache.size())
+      case FontDescription::FACE_FONT:
       {
-        FontFaceCacheItem& cacheItem = mFontFaceCache[fontIdCacheItem.id];
-
-        if(nullptr == cacheItem.mCharacterSet)
-        {
-          // Create again the character set.
-          // It can be null if the ResetSystemDefaults() method has been called.
-
-          FontDescription description;
-          description.path   = cacheItem.mPath;
-          description.family = 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;
-          }
-
-          cacheItem.mCharacterSet = FcCharSetCopy(CreateCharacterSetFromDescription(description));
-        }
-
-        isSupported = FcCharSetHasChar(cacheItem.mCharacterSet, character);
+        return &mFontFaceCache[fontIdCacheItem.index];
       }
-      break;
-    }
-    case FontDescription::BITMAP_FONT:
-    {
-      const BitmapFont& bitmapFont = mBitmapFontCache[fontIdCacheItem.id].font;
-
-      for(const auto& glyph : bitmapFont.glyphs)
+      case FontDescription::BITMAP_FONT:
       {
-        if(glyph.utf32 == character)
-        {
-          isSupported = true;
-          break;
-        }
+        return &mBitmapFontCache[fontIdCacheItem.index];
+      }
+      default:
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
       }
-      break;
-    }
-    default:
-    {
-      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
     }
   }
-
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false"));
-  return isSupported;
+  return nullptr;
 }
 
 FontId FontClient::Plugin::FindFontForCharacter(const FontList&         fontList,
@@ -789,7 +717,7 @@ FontId FontClient::Plugin::FindFontForCharacter(const FontList&         fontList
         if((fontId > 0) &&
            (fontId - 1u < mFontIdCache.Count()))
         {
-          const FontFaceCacheItem& item = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+          const FontFaceCacheItem& item = mFontFaceCache[mFontIdCache[fontId - 1u].index];
 
           foundColor = item.mHasColorTables;
         }
@@ -937,6 +865,18 @@ FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription,
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
   FONT_LOG_DESCRIPTION(fontDescription, "");
+
+  // Special case when font Description don't have family information.
+  // In this case, we just use default description family and path.
+  const FontDescription& realFontDescription = fontDescription.family.empty() ? FontDescription(mDefaultFontDescription.path,
+                                                                                                mDefaultFontDescription.family,
+                                                                                                fontDescription.width,
+                                                                                                fontDescription.weight,
+                                                                                                fontDescription.slant,
+                                                                                                fontDescription.type)
+                                                                              : fontDescription;
+
+  FONT_LOG_DESCRIPTION(realFontDescription, "");
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "   requestedPointSize : %d\n", requestedPointSize);
 
   // This method uses three vectors which caches:
@@ -961,28 +901,28 @@ FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription,
   FontId fontId = 0u;
 
   // Check first if the font description matches with a previously loaded bitmap font.
-  if(FindBitmapFont(fontDescription.family, fontId))
+  if(FindBitmapFont(realFontDescription.family, fontId))
   {
     return fontId;
   }
 
   // Check if the font's description have been validated before.
-  FontDescriptionId validatedFontId = 0u;
+  FontDescriptionId fontDescriptionId = 0u;
 
-  if(!FindValidatedFont(fontDescription,
-                        validatedFontId))
+  if(!FindValidatedFont(realFontDescription,
+                        fontDescriptionId))
   {
     // Use font config to validate the font's description.
-    ValidateFont(fontDescription,
-                 validatedFontId);
+    ValidateFont(realFontDescription,
+                 fontDescriptionId);
   }
 
-  FontId fontFaceId = 0u;
-  // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
-  if(!FindFont(validatedFontId, requestedPointSize, fontFaceId))
+  FontCacheIndex fontCacheIndex = 0u;
+  // Check if exists a pair 'fontDescriptionId, requestedPointSize' in the cache.
+  if(!FindFont(fontDescriptionId, requestedPointSize, fontCacheIndex))
   {
     // Retrieve the font file name path.
-    const FontDescription& description = *(mFontDescriptionCache.begin() + validatedFontId - 1u);
+    const FontDescription& description = *(mFontDescriptionCache.begin() + fontDescriptionId - 1u);
 
     // Retrieve the font id. Do not cache the description as it has been already cached.
     fontId = GetFontId(description.path,
@@ -990,17 +930,15 @@ FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription,
                        faceIndex,
                        false);
 
-    fontFaceId                               = mFontIdCache[fontId - 1u].id;
-    mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(mCharacterSetCache[validatedFontId - 1u]);
+    fontCacheIndex                               = mFontIdCache[fontId - 1u].index;
+    mFontFaceCache[fontCacheIndex].mCharacterSet = FcCharSetCopy(mCharacterSetCache[fontDescriptionId - 1u]);
 
-    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
-                                                                     requestedPointSize,
-                                                                     fontFaceId));
+    // Cache the pair 'fontDescriptionId, requestedPointSize' to improve the following queries.
+    mFontDescriptionSizeCache.emplace(FontDescriptionSizeCacheKey(fontDescriptionId, requestedPointSize), fontCacheIndex);
   }
   else
   {
-    fontId = mFontFaceCache[fontFaceId].mFontId + 1u;
+    fontId = mFontFaceCache[fontCacheIndex].mFontId + 1u;
   }
 
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", fontId);
@@ -1017,39 +955,11 @@ FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
     }
   }
 
-  BitmapFontCacheItem bitmapFontCacheItem;
-  bitmapFontCacheItem.font = bitmapFont;
-  bitmapFontCacheItem.id   = mFontIdCache.Count();
-
-  // Resize the vector with the pixel buffers.
-  bitmapFontCacheItem.pixelBuffers.resize(bitmapFont.glyphs.size());
-
-  // Traverse all the glyphs and load the pixel buffer of those with ascender and descender equal to zero.
-  unsigned int index = 0u;
-  for(auto& glyph : bitmapFontCacheItem.font.glyphs)
-  {
-    Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-
-    if(EqualsZero(glyph.ascender) && EqualsZero(glyph.descender))
-    {
-      // Load the glyph.
-      pixelBuffer = LoadImageFromFile(glyph.url);
-
-      if(pixelBuffer)
-      {
-        glyph.ascender = static_cast<float>(pixelBuffer.GetHeight());
-      }
-    }
-
-    bitmapFontCacheItem.font.ascender  = std::max(glyph.ascender, bitmapFontCacheItem.font.ascender);
-    bitmapFontCacheItem.font.descender = std::min(glyph.descender, bitmapFontCacheItem.font.descender);
-
-    ++index;
-  }
+  BitmapFontCacheItem bitmapFontCacheItem(bitmapFont, mFontIdCache.Count());
 
   FontIdCacheItem fontIdCacheItem;
-  fontIdCacheItem.type = FontDescription::BITMAP_FONT;
-  fontIdCacheItem.id   = mBitmapFontCache.size();
+  fontIdCacheItem.type  = FontDescription::BITMAP_FONT;
+  fontIdCacheItem.index = mBitmapFontCache.size();
 
   mBitmapFontCache.push_back(std::move(bitmapFontCacheItem));
   mFontIdCache.PushBack(fontIdCacheItem);
@@ -1058,7 +968,7 @@ FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
 }
 
 void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
-                                      FontDescriptionId&     validatedFontId)
+                                      FontDescriptionId&     fontDescriptionId)
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
   FONT_LOG_DESCRIPTION(fontDescription, "");
@@ -1079,17 +989,17 @@ void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
     mFontDescriptionCache.push_back(description);
 
     // Set the index to the vector of paths to font file names.
-    validatedFontId = mFontDescriptionCache.size();
+    fontDescriptionId = mFontDescriptionCache.size();
 
     FONT_LOG_DESCRIPTION(description, "matched");
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validatedFontId : %d\n", validatedFontId);
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  fontDescriptionId : %d\n", fontDescriptionId);
 
     // The reference counter of the character set has already been increased in MatchFontDescriptionToPattern.
     mCharacterSetCache.PushBack(characterSet);
 
     // Cache the index and the matched font's description.
     FontDescriptionCacheItem item(description,
-                                  validatedFontId);
+                                  fontDescriptionId);
 
     mValidatedFontCache.push_back(std::move(item));
 
@@ -1100,7 +1010,7 @@ void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
     {
       // Cache the given font's description if it's different than the matched.
       FontDescriptionCacheItem item(fontDescription,
-                                    validatedFontId);
+                                    fontDescriptionId);
 
       mValidatedFontCache.push_back(std::move(item));
     }
@@ -1114,82 +1024,36 @@ void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
 void FontClient::Plugin::GetFontMetrics(FontId       fontId,
                                         FontMetrics& metrics)
 {
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0) &&
-     (index < mFontIdCache.Count()))
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-        metrics = font.mMetrics;
-
-        // Adjust the metrics if the fixed-size font should be down-scaled
-        if(font.mIsFixedSizeBitmap)
-        {
-          const float desiredFixedSize = static_cast<float>(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
-
-          if(desiredFixedSize > 0.f)
-          {
-            const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels;
-
-            metrics.ascender           = metrics.ascender * scaleFactor;
-            metrics.descender          = metrics.descender * scaleFactor;
-            metrics.height             = metrics.height * scaleFactor;
-            metrics.underlinePosition  = metrics.underlinePosition * scaleFactor;
-            metrics.underlineThickness = metrics.underlineThickness * scaleFactor;
-          }
-        }
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        const BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-        metrics.ascender           = bitmapFontCacheItem.font.ascender;
-        metrics.descender          = bitmapFontCacheItem.font.descender;
-        metrics.height             = metrics.ascender - metrics.descender;
-        metrics.underlinePosition  = bitmapFontCacheItem.font.underlinePosition;
-        metrics.underlineThickness = bitmapFontCacheItem.font.underlineThickness;
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
+    fontCacheItem->GetFontMetrics(metrics, mDpiVertical);
   }
 }
 
 GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId    fontId,
                                              Character charcode)
 {
-  GlyphIndex   glyphIndex = 0u;
-  const FontId index      = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+    return fontCacheItem->GetGlyphIndex(charcode);
+  }
 
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      FT_Face ftFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
+  return 0u;
+}
 
-      glyphIndex = FT_Get_Char_Index(ftFace, charcode);
-    }
+GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId    fontId,
+                                             Character charcode,
+                                             Character variantSelector)
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    return fontCacheItem->GetGlyphIndex(charcode, variantSelector);
   }
 
-  return glyphIndex;
+  return 0u;
 }
 
 bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array,
@@ -1209,184 +1073,22 @@ bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array,
                                           uint32_t   size,
                                           bool       horizontal)
 {
-  bool success(true);
+  bool success(false);
 
   for(unsigned int i = 0; i < size; ++i)
   {
     GlyphInfo& glyph = array[i];
 
-    FontId index = glyph.fontId - 1u;
-
-    if((glyph.fontId > 0u) &&
-       (index < mFontIdCache.Count()))
+    const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(glyph.fontId);
+    if(fontCacheItem != nullptr)
     {
-      const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-      switch(fontIdCacheItem.type)
-      {
-        case FontDescription::FACE_FONT:
-        {
-          const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-          FT_Face ftFace = font.mFreeTypeFace;
-
-#ifdef FREETYPE_BITMAP_SUPPORT
-          // Check to see if we should be loading a Fixed Size bitmap?
-          if(font.mIsFixedSizeBitmap)
-          {
-            FT_Select_Size(ftFace, font.mFixedSizeIndex); ///< @todo: needs to be investigated why it's needed to select the size again.
-            int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_COLOR);
-            if(FT_Err_Ok == error)
-            {
-              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
-              const float desiredFixedSize = static_cast<float>(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
-
-              if(desiredFixedSize > 0.f)
-              {
-                const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels;
-
-                glyph.width    = glyph.width * scaleFactor;
-                glyph.height   = glyph.height * scaleFactor;
-                glyph.advance  = glyph.advance * scaleFactor;
-                glyph.xBearing = glyph.xBearing * scaleFactor;
-                glyph.yBearing = glyph.yBearing * scaleFactor;
-
-                glyph.scaleFactor = scaleFactor;
-              }
-            }
-            else
-            {
-              DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error);
-              success = false;
-            }
-          }
-          else
-#endif
-          {
-            // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap.
-            // i.e. with the SNum-3R font.
-            // @todo: add an option to use the FT_LOAD_DEFAULT if required?
-            int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_NO_AUTOHINT);
-
-            // Keep the width of the glyph before doing the software emboldening.
-            // It will be used to calculate a scale factor to be applied to the
-            // advance as Harfbuzz doesn't apply any SW emboldening to calculate
-            // the advance of the glyph.
-            const float width = static_cast<float>(ftFace->glyph->metrics.width) * FROM_266;
-
-            if(FT_Err_Ok == error)
-            {
-              const bool isEmboldeningRequired = glyph.isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD);
-              if(isEmboldeningRequired)
-              {
-                // Does the software bold.
-                FT_GlyphSlot_Embolden(ftFace->glyph);
-              }
-
-              glyph.width  = static_cast<float>(ftFace->glyph->metrics.width) * FROM_266;
-              glyph.height = static_cast<float>(ftFace->glyph->metrics.height) * FROM_266;
-              if(horizontal)
-              {
-                glyph.xBearing += static_cast<float>(ftFace->glyph->metrics.horiBearingX) * FROM_266;
-                glyph.yBearing += static_cast<float>(ftFace->glyph->metrics.horiBearingY) * FROM_266;
-              }
-              else
-              {
-                glyph.xBearing += static_cast<float>(ftFace->glyph->metrics.vertBearingX) * FROM_266;
-                glyph.yBearing += static_cast<float>(ftFace->glyph->metrics.vertBearingY) * FROM_266;
-              }
-
-              if(isEmboldeningRequired && !Dali::EqualsZero(width))
-              {
-                // If the glyph is emboldened by software, the advance is multiplied by a
-                // scale factor to make it slightly bigger.
-                glyph.advance *= (glyph.width / width);
-              }
-
-              // Use the bounding box of the bitmap to correct the metrics.
-              // For some fonts i.e the SNum-3R the metrics need to be corrected,
-              // otherwise the glyphs 'dance' up and down depending on the
-              // font's point size.
-
-              FT_Glyph ftGlyph;
-              error = FT_Get_Glyph(ftFace->glyph, &ftGlyph);
-
-              FT_BBox bbox;
-              FT_Glyph_Get_CBox(ftGlyph, FT_GLYPH_BBOX_GRIDFIT, &bbox);
-
-              const float descender = glyph.height - glyph.yBearing;
-              glyph.height          = (bbox.yMax - bbox.yMin) * FROM_266;
-              glyph.yBearing        = glyph.height - round(descender);
-
-              // Created FT_Glyph object must be released with FT_Done_Glyph
-              FT_Done_Glyph(ftGlyph);
-            }
-            else
-            {
-              success = false;
-            }
-          }
-          break;
-        }
-        case FontDescription::BITMAP_FONT:
-        {
-          BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-          unsigned int index = 0u;
-          for(auto& item : bitmapFontCacheItem.font.glyphs)
-          {
-            if(item.utf32 == glyph.index)
-            {
-              Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-              if(!pixelBuffer)
-              {
-                pixelBuffer = LoadImageFromFile(item.url);
-              }
-
-              glyph.width       = static_cast<float>(pixelBuffer.GetWidth());
-              glyph.height      = static_cast<float>(pixelBuffer.GetHeight());
-              glyph.xBearing    = 0.f;
-              glyph.yBearing    = glyph.height + item.descender;
-              glyph.advance     = glyph.width;
-              glyph.scaleFactor = 1.f;
-              break;
-            }
-            ++index;
-          }
-
-          success = true;
-          break;
-        }
-        default:
-        {
-          DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-        }
-      }
+      success = fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal);
     }
-    else
+    // Check if it's an embedded image.
+    else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
     {
-      // Check if it's an embedded image.
-      if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
-      {
-        const EmbeddedItem& item = mEmbeddedItemCache[glyph.index - 1u];
-
-        glyph.width       = static_cast<float>(item.width);
-        glyph.height      = static_cast<float>(item.height);
-        glyph.xBearing    = 0.f;
-        glyph.yBearing    = glyph.height;
-        glyph.advance     = glyph.width;
-        glyph.scaleFactor = 1.f;
-      }
-      else
-      {
-        success = false;
-      }
+      mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph);
+      success = true;
     }
   }
 
@@ -1407,7 +1109,7 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
     if((fontId > 0u) &&
        (fontId - 1u) < mFontIdCache.Count())
     {
-      FontFaceCacheItem& font = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+      FontFaceCacheItem& font = mFontFaceCache[mFontIdCache[fontId - 1u].index];
 
       if(!font.mVectorFontId)
       {
@@ -1438,219 +1140,17 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
 
 void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
 {
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  data.isColorBitmap                          = false;
+  data.isColorEmoji                           = false;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    data.isColorBitmap = false;
-    data.isColorEmoji  = false;
-
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        // For the software italics.
-        bool isShearRequired = false;
-
-        const FontFaceCacheItem& fontFaceCacheItem = mFontFaceCache[fontIdCacheItem.id];
-        FT_Face                  ftFace            = fontFaceCacheItem.mFreeTypeFace;
-
-        FT_Error error;
-
-#ifdef FREETYPE_BITMAP_SUPPORT
-        // Check to see if this is fixed size bitmap
-        if(fontFaceCacheItem.mIsFixedSizeBitmap)
-        {
-          error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR);
-        }
-        else
-#endif
-        {
-          // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap.
-          // i.e. with the SNum-3R font.
-          // @todo: add an option to use the FT_LOAD_DEFAULT if required?
-          error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_NO_AUTOHINT);
-        }
-        if(FT_Err_Ok == error)
-        {
-          if(isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD))
-          {
-            // Does the software bold.
-            FT_GlyphSlot_Embolden(ftFace->glyph);
-          }
-
-          if(isItalicRequired && !(ftFace->style_flags & FT_STYLE_FLAG_ITALIC))
-          {
-            // Will do the software italic.
-            isShearRequired = true;
-          }
-
-          FT_Glyph glyph;
-          error = FT_Get_Glyph(ftFace->glyph, &glyph);
-
-          // Convert to bitmap if necessary
-          if(FT_Err_Ok == error)
-          {
-            if(glyph->format != FT_GLYPH_FORMAT_BITMAP)
-            {
-              int  offsetX = 0, offsetY = 0;
-              bool isOutlineGlyph = (glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0);
-
-              // Create a bitmap for the outline
-              if(isOutlineGlyph)
-              {
-                // Retrieve the horizontal and vertical distance from the current pen position to the
-                // left and top border of the glyph bitmap for a normal glyph before applying the outline.
-                if(FT_Err_Ok == error)
-                {
-                  FT_Glyph normalGlyph;
-                  error = FT_Get_Glyph(ftFace->glyph, &normalGlyph);
-
-                  error = FT_Glyph_To_Bitmap(&normalGlyph, FT_RENDER_MODE_NORMAL, 0, 1);
-                  if(FT_Err_Ok == error)
-                  {
-                    FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(normalGlyph);
-
-                    offsetX = bitmapGlyph->left;
-                    offsetY = bitmapGlyph->top;
-                  }
-
-                  // Created FT_Glyph object must be released with FT_Done_Glyph
-                  FT_Done_Glyph(normalGlyph);
-                }
-
-                // Now apply the outline
-
-                // 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 = reinterpret_cast<FT_BitmapGlyph>(glyph);
-
-                if(isOutlineGlyph)
-                {
-                  // Calculate the additional horizontal and vertical offsets needed for the position of the outline glyph
-                  data.outlineOffsetX = offsetX - bitmapGlyph->left - outlineWidth;
-                  data.outlineOffsetY = bitmapGlyph->top - offsetY - outlineWidth;
-                }
-
-                ConvertBitmap(data, bitmapGlyph->bitmap, isShearRequired);
-              }
-              else
-              {
-                DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error);
-              }
-            }
-            else
-            {
-              ConvertBitmap(data, ftFace->glyph->bitmap, isShearRequired);
-            }
-
-            data.isColorEmoji = fontFaceCacheItem.mIsFixedSizeBitmap;
-
-            // Created FT_Glyph object must be released with FT_Done_Glyph
-            FT_Done_Glyph(glyph);
-          }
-        }
-        else
-        {
-          DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error);
-        }
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-        unsigned int index = 0u;
-        for(auto& item : bitmapFontCacheItem.font.glyphs)
-        {
-          if(item.utf32 == glyphIndex)
-          {
-            Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-            if(!pixelBuffer)
-            {
-              pixelBuffer = LoadImageFromFile(item.url);
-            }
-
-            data.width  = pixelBuffer.GetWidth();
-            data.height = pixelBuffer.GetHeight();
-
-            data.isColorBitmap = bitmapFontCacheItem.font.isColorFont;
-
-            ConvertBitmap(data, data.width, data.height, pixelBuffer.GetBuffer());
-
-            // Sets the pixel format.
-            data.format = pixelBuffer.GetPixelFormat();
-            break;
-          }
-          ++index;
-        }
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
+    fontCacheItem->CreateBitmap(glyphIndex, data, outlineWidth, isItalicRequired, isBoldRequired);
   }
-  else
+  else if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
   {
-    if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
-    {
-      // It's an embedded item.
-      const EmbeddedItem& item = mEmbeddedItemCache[glyphIndex - 1u];
-
-      data.width  = item.width;
-      data.height = item.height;
-      if(0u != item.pixelBufferId)
-      {
-        Devel::PixelBuffer pixelBuffer = mPixelBufferCache[item.pixelBufferId - 1u].pixelBuffer;
-        if(pixelBuffer)
-        {
-          ConvertBitmap(data, pixelBuffer.GetWidth(), pixelBuffer.GetHeight(), pixelBuffer.GetBuffer());
-
-          // Sets the pixel format.
-          data.format = pixelBuffer.GetPixelFormat();
-        }
-      }
-      else
-      {
-        // 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[].
-
-        memset(data.buffer, 0u, bufferSize);
-
-        // Just creates a void buffer. Doesn't matter what pixel format is set as is the application code the responsible of filling it.
-      }
-    }
+    // It's an embedded item.
+    mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mPixelBufferCache, data);
   }
 }
 
@@ -1665,7 +1165,7 @@ PixelData FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex,
                         data.width,
                         data.height,
                         data.format,
-                        PixelData::DELETE_ARRAY);
+                        PixelData::FREE);
 }
 
 void FontClient::Plugin::CreateVectorBlob(FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight)
@@ -1677,8 +1177,8 @@ void FontClient::Plugin::CreateVectorBlob(FontId fontId, GlyphIndex glyphIndex,
   if((fontId > 0u) &&
      (fontId - 1u < mFontIdCache.Count()))
   {
-    const FontId       fontFaceId = mFontIdCache[fontId - 1u].id;
-    FontFaceCacheItem& font       = mFontFaceCache[fontFaceId];
+    const FontCacheIndex fontFaceId = mFontIdCache[fontId - 1u].index;
+    FontFaceCacheItem&   font       = mFontFaceCache[fontFaceId];
 
     if(!font.mVectorFontId)
     {
@@ -1719,7 +1219,7 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedP
                                       false);
 
   // Set the character index to access the glyph inside the font.
-  item.glyph.index = FT_Get_Char_Index(mFontFaceCache[mFontIdCache[item.glyph.fontId - 1u].id].mFreeTypeFace,
+  item.glyph.index = FT_Get_Char_Index(mFontFaceCache[mFontIdCache[item.glyph.fontId - 1u].index].mFreeTypeFace,
                                        ELLIPSIS_CHARACTER);
 
   GetBitmapMetrics(&item.glyph, 1u, true);
@@ -1731,62 +1231,18 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedP
 
 bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex)
 {
-  FT_Error error = -1;
-
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-#ifdef FREETYPE_BITMAP_SUPPORT
-        const FontFaceCacheItem& item   = mFontFaceCache[fontIdCacheItem.id];
-        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
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        error = FT_Err_Ok; // Will return true;
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-
-  return FT_Err_Ok == error;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  return fontCacheItem && fontCacheItem->IsColorGlyph(glyphIndex);
 }
 
 FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId)
 {
-  FT_Face fontFace = nullptr;
-
-  const FontId index = fontId - 1u;
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      fontFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
-    }
+    return fontCacheItem->GetTypeface();
   }
-  return fontFace;
+  return nullptr;
 }
 
 FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId)
@@ -2154,18 +1610,19 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
       }
       else
       {
+        FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
+
+        FontMetrics metrics(static_cast<float>(ftMetrics.ascender) * FROM_266,
+                            static_cast<float>(ftMetrics.descender) * FROM_266,
+                            static_cast<float>(ftMetrics.height) * FROM_266,
+                            static_cast<float>(ftFace->underline_position) * FROM_266,
+                            static_cast<float>(ftFace->underline_thickness) * FROM_266);
+
         const float fixedWidth  = static_cast<float>(ftFace->available_sizes[fixedSizeIndex].width);
         const 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);
-
         // Create the FreeType font face item to cache.
-        FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
+        FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
 
         // Set the index to the font's id cache.
         fontFaceCacheItem.mFontId = mFontIdCache.Count();
@@ -2175,11 +1632,11 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
         fontIdCacheItem.type = FontDescription::FACE_FONT;
 
         // Set the index to the FreeType font face cache.
-        fontIdCacheItem.id = mFontFaceCache.size();
-        fontFaceId         = fontIdCacheItem.id + 1u;
+        fontIdCacheItem.index = mFontFaceCache.size();
+        fontFaceId            = fontIdCacheItem.index + 1u;
 
         // Cache the items.
-        mFontFaceCache.push_back(fontFaceCacheItem);
+        mFontFaceCache.emplace_back(std::move(fontFaceCacheItem));
         mFontIdCache.PushBack(fontIdCacheItem);
 
         // Set the font id to be returned.
@@ -2223,7 +1680,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
                             static_cast<float>(ftFace->underline_thickness) * FROM_266);
 
         // Create the FreeType font face item to cache.
-        FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics);
+        FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics);
 
         // Set the index to the font's id cache.
         fontFaceCacheItem.mFontId = mFontIdCache.Count();
@@ -2233,11 +1690,11 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
         fontIdCacheItem.type = FontDescription::FACE_FONT;
 
         // Set the index to the FreeType font face cache.
-        fontIdCacheItem.id = mFontFaceCache.size();
-        fontFaceId         = fontIdCacheItem.id + 1u;
+        fontIdCacheItem.index = mFontFaceCache.size();
+        fontFaceId            = fontIdCacheItem.index + 1u;
 
         // Cache the items.
-        mFontFaceCache.push_back(fontFaceCacheItem);
+        mFontFaceCache.emplace_back(std::move(fontFaceCacheItem));
         mFontIdCache.PushBack(fontIdCacheItem);
 
         // Set the font id to be returned.
@@ -2295,13 +1752,13 @@ bool FontClient::Plugin::FindFont(const FontPath& path,
 }
 
 bool FontClient::Plugin::FindValidatedFont(const FontDescription& fontDescription,
-                                           FontDescriptionId&     validatedFontId)
+                                           FontDescriptionId&     fontDescriptionId)
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
   FONT_LOG_DESCRIPTION(fontDescription, "");
   DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  number of validated fonts in the cache : %d\n", mValidatedFontCache.size());
 
-  validatedFontId = 0u;
+  fontDescriptionId = 0u;
 
   for(const auto& item : mValidatedFontCache)
   {
@@ -2311,14 +1768,14 @@ bool FontClient::Plugin::FindValidatedFont(const FontDescription& fontDescriptio
        (fontDescription.weight == item.fontDescription.weight) &&
        (fontDescription.slant == item.fontDescription.slant))
     {
-      validatedFontId = item.index;
+      fontDescriptionId = item.index;
 
-      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font found, id : %d\n", validatedFontId);
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font description found, id : %d\n", fontDescriptionId);
       return true;
     }
   }
 
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font not found\n");
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font description not found\n");
   return false;
 }
 
@@ -2352,26 +1809,25 @@ bool FontClient::Plugin::FindFallbackFontList(const FontDescription& fontDescrip
   return false;
 }
 
-bool FontClient::Plugin::FindFont(FontDescriptionId validatedFontId,
+bool FontClient::Plugin::FindFont(FontDescriptionId fontDescriptionId,
                                   PointSize26Dot6   requestedPointSize,
-                                  FontId&           fontId)
+                                  FontCacheIndex&   fontCacheIndex)
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "    validatedFontId  : %d\n", validatedFontId);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "   fontDescriptionId : %d\n", fontDescriptionId);
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
 
-  fontId = 0u;
+  fontCacheIndex = 0u;
 
-  for(const auto& item : mFontDescriptionSizeCache)
+  FontDescriptionSizeCacheKey key(fontDescriptionId, requestedPointSize);
+
+  const auto& iter = mFontDescriptionSizeCache.find(key);
+  if(iter != mFontDescriptionSizeCache.cend())
   {
-    if((validatedFontId == item.validatedFontId) &&
-       (requestedPointSize == item.requestedPointSize))
-    {
-      fontId = item.fontId;
+    fontCacheIndex = iter->second;
 
-      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font found, id : %d\n", fontId);
-      return true;
-    }
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font found, index of font cache : %d\n", fontCacheIndex);
+    return true;
   }
 
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font not found.\n");
@@ -2500,28 +1956,12 @@ void FontClient::Plugin::GetFixedSizes(const FontDescription&   fontDescription,
 
 bool FontClient::Plugin::HasItalicStyle(FontId fontId) const
 {
-  bool hasItalicStyle = false;
-
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-      hasItalicStyle = 0u != (font.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC);
-    }
-  }
-  else
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
+    return fontCacheItem->HasItalicStyle();
   }
-
-  return hasItalicStyle;
+  return false;
 }
 
 void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path)
@@ -2543,9 +1983,9 @@ void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot
     description.weight = FontWeight::BOLD;
   }
 
-  FontDescriptionId validatedFontId = 0u;
+  FontDescriptionId fontDescriptionId = 0u;
   if(!FindValidatedFont(description,
-                        validatedFontId))
+                        fontDescriptionId))
   {
     FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
 
@@ -2567,19 +2007,17 @@ void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot
     mFontDescriptionCache.push_back(description);
 
     // Set the index to the vector of paths to font file names.
-    validatedFontId = mFontDescriptionCache.size();
+    fontDescriptionId = mFontDescriptionCache.size();
 
     // Increase the reference counter and add the character set to the cache.
     mCharacterSetCache.PushBack(FcCharSetCopy(characterSet));
 
     // Cache the index and the font's description.
     mValidatedFontCache.push_back(std::move(FontDescriptionCacheItem(std::move(description),
-                                                                     validatedFontId)));
+                                                                     fontDescriptionId)));
 
-    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
-                                                                     requestedPointSize,
-                                                                     fontFaceId));
+    // Cache the pair 'fontDescriptionId, requestedPointSize' to improve the following queries.
+    mFontDescriptionSizeCache.emplace(FontDescriptionSizeCacheKey(fontDescriptionId, requestedPointSize), fontFaceId);
   }
 }
 
@@ -2610,8 +2048,4 @@ void FontClient::Plugin::ClearCharacterSetFromFontFaceCache()
   }
 }
 
-} // namespace Internal
-
-} // namespace TextAbstraction
-
-} // namespace Dali
+} // namespace Dali::TextAbstraction::Internal