[dali_2.0.51] Merge branch 'devel/master' 87/266087/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 5 Nov 2021 10:44:54 +0000 (10:44 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 5 Nov 2021 10:44:54 +0000 (10:44 +0000)
Change-Id: I2d0be61cb301520877a6cce0f240c0ed1b673515

48 files changed:
automated-tests/build.sh
automated-tests/resources/fonts/bitmap/u0030.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0031.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0032.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0033.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0034.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0035.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0036.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0037.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0038.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u0039.png [new file with mode: 0644]
automated-tests/resources/fonts/bitmap/u003a.png [new file with mode: 0644]
automated-tests/src/dali-adaptor-internal/CMakeLists.txt
automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp
automated-tests/src/dali-platform-abstraction/CMakeLists.txt
dali/devel-api/text-abstraction/font-client.h
dali/internal/accessibility/bridge/bridge-action.h
dali/internal/accessibility/bridge/bridge-application.h
dali/internal/accessibility/bridge/bridge-collection.cpp
dali/internal/accessibility/bridge/bridge-collection.h
dali/internal/accessibility/bridge/bridge-component.h
dali/internal/accessibility/bridge/bridge-editable-text.cpp
dali/internal/accessibility/bridge/bridge-editable-text.h
dali/internal/accessibility/bridge/bridge-object.cpp
dali/internal/accessibility/bridge/bridge-object.h
dali/internal/accessibility/bridge/bridge-selection.h
dali/internal/accessibility/bridge/bridge-text.cpp
dali/internal/accessibility/bridge/bridge-text.h
dali/internal/accessibility/bridge/bridge-value.h
dali/internal/text/file.list
dali/internal/text/text-abstraction/font-client-helper.cpp [deleted file]
dali/internal/text/text-abstraction/font-client-helper.h [deleted file]
dali/internal/text/text-abstraction/font-client-impl.cpp
dali/internal/text/text-abstraction/font-client-plugin-impl.cpp [deleted file]
dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/embedded-item.cpp [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/embedded-item.h [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h [moved from dali/internal/text/text-abstraction/font-client-plugin-impl.h with 81% similarity]
dali/internal/text/text-abstraction/plugin/font-client-utils.cpp [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-client-utils.h [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/font-face-cache-item.h [new file with mode: 0644]
dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h [new file with mode: 0644]
dali/public-api/dali-adaptor-version.cpp
packaging/dali-adaptor.spec

index 2f92135..6db52c3 100755 (executable)
@@ -32,7 +32,7 @@ function build
         (cd src/$1; ../../scripts/tcheadgen.sh tct-$1-core.h)
         if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
     fi
-    (cd build ; cmake .. -DMODULE=$1 ; make -j7 )
+    (cd build ; cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DMODULE=$1 ; make -j7 )
 }
 
 if [ -n "$1" ] ; then
diff --git a/automated-tests/resources/fonts/bitmap/u0030.png b/automated-tests/resources/fonts/bitmap/u0030.png
new file mode 100644 (file)
index 0000000..1b0cc3c
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0030.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0031.png b/automated-tests/resources/fonts/bitmap/u0031.png
new file mode 100644 (file)
index 0000000..2c70e9c
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0031.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0032.png b/automated-tests/resources/fonts/bitmap/u0032.png
new file mode 100644 (file)
index 0000000..2ed2d75
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0032.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0033.png b/automated-tests/resources/fonts/bitmap/u0033.png
new file mode 100644 (file)
index 0000000..2cb1673
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0033.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0034.png b/automated-tests/resources/fonts/bitmap/u0034.png
new file mode 100644 (file)
index 0000000..99d72e1
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0034.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0035.png b/automated-tests/resources/fonts/bitmap/u0035.png
new file mode 100644 (file)
index 0000000..2780eae
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0035.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0036.png b/automated-tests/resources/fonts/bitmap/u0036.png
new file mode 100644 (file)
index 0000000..62e240f
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0036.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0037.png b/automated-tests/resources/fonts/bitmap/u0037.png
new file mode 100644 (file)
index 0000000..ae3790a
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0037.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0038.png b/automated-tests/resources/fonts/bitmap/u0038.png
new file mode 100644 (file)
index 0000000..e2b0d13
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0038.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u0039.png b/automated-tests/resources/fonts/bitmap/u0039.png
new file mode 100644 (file)
index 0000000..2a3f481
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0039.png differ
diff --git a/automated-tests/resources/fonts/bitmap/u003a.png b/automated-tests/resources/fonts/bitmap/u003a.png
new file mode 100644 (file)
index 0000000..a6ca724
Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u003a.png differ
index 3fe5502..b6c2ec9 100644 (file)
@@ -51,16 +51,17 @@ PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
     dali2-core
     dali2-adaptor
     ecore
+    freetype2>=9.16.3
 )
 
+
+
 ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror )
 ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} )
 
-# Shouldn't have to do this!
-# But CMake's new auto-escape quote policy doesn't work right.
-CMAKE_POLICY(SET CMP0005 OLD)
-ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\\\"\" )
-ADD_DEFINITIONS(-DADDON_LIBS_PATH=\"\\\"${CMAKE_CURRENT_BINARY_DIR}\\\"\" )
+ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\" )
+ADD_DEFINITIONS(-DTEST_RESOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../resources\" )
+ADD_DEFINITIONS(-DADDON_LIBS_PATH=\"${CMAKE_CURRENT_BINARY_DIR}\" )
 
 
 FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
index bd868f9..208deb1 100644 (file)
 
 #include <dali-test-suite-utils.h>
 #include <dali/dali.h>
+#include <dali/devel-api/text-abstraction/bitmap-font.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
-#include <dali/internal/text/text-abstraction/font-client-helper.h>
+#include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <iostream>
 
 using namespace Dali;
 
@@ -345,4 +347,553 @@ int UtcDaliFontClientTextAtlasConstants(void)
   DALI_TEST_EQUALS(numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+using namespace Dali::TextAbstraction;
+
+int UtcDaliFontClientGetDefaultFonts(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientGetDefaultFonts ");
+
+  FontClient fontClient;
+  fontClient = FontClient::Get();
+
+  FontList fontList;
+  fontClient.GetDefaultFonts(fontList);
+
+  std::ostringstream oss;
+  oss << fontList << std::endl;
+
+  tet_printf("FontList: %s", oss.str().c_str());
+  DALI_TEST_CHECK(fontList.size() > 0);
+
+  END_TEST;
+}
+
+int UtcDaliFontClientGetSystemFonts(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientGetSystemFonts ");
+
+  FontClient fontClient;
+  fontClient = FontClient::Get();
+
+  FontList fontList;
+  fontClient.GetSystemFonts(fontList);
+
+  std::ostringstream oss;
+  oss << fontList << std::endl;
+
+  tet_printf("FontList: %s", oss.str().c_str());
+  DALI_TEST_CHECK(fontList.size() > 0);
+
+  const PointSize26Dot6 pointSize = fontClient.GetPointSize(fontList.size());
+  DALI_TEST_EQUALS(pointSize, FontClient::DEFAULT_POINT_SIZE, TEST_LOCATION);
+
+  END_TEST;
+}
+
+std::ostream& operator<<(std::ostream& o, const FontDescription& description)
+{
+  o << "Font path: " << description.path << " family: "
+    << " width : " << description.width << " weight : " << description.weight << " slant : " << description.slant << std::endl;
+  return o;
+}
+
+int UtcDaliFontClientGetDefaultPlatformFontDescription(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientGetDefaultPlatformFontDescription");
+
+  FontClient fontClient;
+  fontClient = FontClient::Get();
+
+  FontDescription fontDescription;
+  fontClient.GetDefaultPlatformFontDescription(fontDescription);
+
+  std::ostringstream oss;
+  oss << fontDescription;
+  tet_printf("%s", oss.str().c_str());
+
+  DALI_TEST_CHECK(fontDescription.path.empty() == false);
+
+  FontId fontId = fontClient.FindFallbackFont('A',
+                                              fontDescription,
+                                              FontClient::DEFAULT_POINT_SIZE,
+                                              true);
+
+  bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A');
+  DALI_TEST_EQUALS(supported, true, TEST_LOCATION);
+  END_TEST;
+}
+
+namespace
+{
+constexpr uint8_t U1               = 1u;
+constexpr uint8_t U2               = 2u;
+constexpr uint8_t U3               = 3u;
+constexpr uint8_t U4               = 4u;
+constexpr uint8_t U5               = 5u;
+constexpr uint8_t U6               = 6u;
+constexpr uint8_t U0               = 0u;
+constexpr uint8_t UTF8_LENGTH[256] = {
+  U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters)
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1,
+  U1, //
+  U1,
+  U1, //
+
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2, //
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2, // lead byte = 110x xxxx (U+0080 - U+07FF)
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2,
+  U2, //
+  U2,
+  U2, //
+
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF)
+  U3,
+  U3,
+  U3,
+  U3,
+  U3,
+  U3, //
+
+  U4,
+  U4,
+  U4,
+  U4,
+  U4,
+  U4,
+  U4,
+  U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF)
+
+  U5,
+  U5,
+  U5,
+  U5, // lead byte = 1111 10xx (U+200000 - U+3FFFFFF)
+
+  U6,
+  U6, // lead byte = 1111 110x (U+4000000 - U+7FFFFFFF)
+
+  U0,
+  U0, // Non valid.
+};
+
+constexpr uint8_t CR = 0xd;
+constexpr uint8_t LF = 0xa;
+
+uint8_t GetUtf8Length(uint8_t utf8LeadByte)
+{
+  return UTF8_LENGTH[utf8LeadByte];
+}
+
+uint32_t Utf8ToUtf32(const uint8_t* const utf8, uint32_t length, uint32_t* utf32)
+{
+  uint32_t numberOfCharacters = 0u;
+
+  const uint8_t* begin = utf8;
+  const uint8_t* end   = utf8 + length;
+
+  for(; begin < end; ++numberOfCharacters)
+  {
+    const uint8_t leadByte = *begin;
+
+    switch(UTF8_LENGTH[leadByte])
+    {
+      case U1:
+      {
+        if(CR == leadByte)
+        {
+          // Replace CR+LF or CR by LF
+          *utf32++ = LF;
+
+          // Look ahead if the next one is a LF.
+          ++begin;
+          if(begin < end)
+          {
+            if(LF == *begin)
+            {
+              ++begin;
+            }
+          }
+        }
+        else
+        {
+          *utf32++ = leadByte;
+          begin++;
+        }
+        break;
+      }
+
+      case U2:
+      {
+        uint32_t& code = *utf32++;
+        code           = leadByte & 0x1fu;
+        begin++;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        break;
+      }
+
+      case U3:
+      {
+        uint32_t& code = *utf32++;
+        code           = leadByte & 0x0fu;
+        begin++;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        break;
+      }
+
+      case U4:
+      {
+        uint32_t& code = *utf32++;
+        code           = leadByte & 0x07u;
+        begin++;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        break;
+      }
+
+      case U5:
+      {
+        uint32_t& code = *utf32++;
+        code           = leadByte & 0x03u;
+        begin++;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        break;
+      }
+
+      case U6:
+      {
+        uint32_t& code = *utf32++;
+        code           = leadByte & 0x01u;
+        begin++;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        code <<= 6u;
+        code |= *begin++ & 0x3fu;
+        break;
+      }
+
+      case U0: // Invalid case
+      {
+        begin++;
+        *utf32++ = 0x20; // Use white space
+        break;
+      }
+    }
+  }
+
+  return numberOfCharacters;
+}
+
+TextAbstraction::FontId SetupBitmapFont()
+{
+  struct GlyphDesc
+  {
+    GlyphDesc()
+    {
+    }
+    GlyphDesc(const std::string& url, const std::string& utf8)
+    {
+      this->url = url;
+      std::copy(utf8.begin(), utf8.end(), this->utf8);
+    }
+    std::string url;
+    uint8_t     utf8[4];
+  };
+  std::vector<GlyphDesc> glyphs;
+
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0030.png", ":"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0031.png", "0"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0032.png", "1"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0033.png", "2"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0034.png", "3"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0035.png", "4"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0036.png", "5"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0037.png", "6"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0038.png", "7"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0039.png", "8"});
+  glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u003a.png", "9"});
+
+  TextAbstraction::BitmapFont bitmapFont;
+  bitmapFont.glyphs.reserve(glyphs.size());
+  bitmapFont.name               = "Digits";
+  bitmapFont.underlinePosition  = 0.f;
+  bitmapFont.underlineThickness = 0.f;
+  bitmapFont.isColorFont        = true;
+
+  for(const auto& glyph : glyphs)
+  {
+    uint32_t c = 0u;
+    Utf8ToUtf32(glyph.utf8, GetUtf8Length(glyph.utf8[0u]), &c);
+    TextAbstraction::BitmapGlyph bitmapGlyph(glyph.url, c, 34.f, 0.f);
+    bitmapFont.glyphs.push_back(std::move(bitmapGlyph));
+  }
+
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  return fontClient.GetFontId(bitmapFont);
+}
+
+} // namespace
+
+int UtcDaliFontClientTestBitmapFont(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientTestBitmapFont");
+
+  FontClient fontClient;
+  fontClient = FontClient::Get();
+
+  auto bitmapFontId = SetupBitmapFont();
+
+  FontDescription fontDescription;
+  fontClient.GetDescription(bitmapFontId, fontDescription);
+  std::ostringstream oss;
+  oss << fontDescription;
+  tet_printf("Found: %d: %s", bitmapFontId, oss.str().c_str());
+
+  bool color = fontClient.IsColorGlyph(bitmapFontId, fontClient.GetGlyphIndex(bitmapFontId, '2'));
+  DALI_TEST_EQUALS(color, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(fontClient.GetPointSize(bitmapFontId), FontClient::DEFAULT_POINT_SIZE, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, '3'), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, 'a'), false, TEST_LOCATION);
+
+  END_TEST;
+}
index a7bb879..22f69f3 100644 (file)
@@ -45,10 +45,7 @@ PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
 ADD_COMPILE_OPTIONS(-O0 -ggdb --coverage -Wall -Werror)
 ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} )
 
-# Shouldn't have to do this!
-# But CMake's new auto-escape quote policy doesn't work right.
-CMAKE_POLICY(SET CMP0005 OLD)
-ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\\\"\" )
+ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\" )
 
 FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
     SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}")
index ce00dd4..b1d6317 100644 (file)
@@ -307,10 +307,11 @@ public:
 
   /**
    * @brief Retrieves a unique font identifier for a given bitmap font.
+   * If the font is not present, it will cache the given font, and give it a new font id.
    *
    * @param[in] bitmapFont A bitmap font.
    *
-   * @return A valid font identifier, or zero if no bitmap font is created.
+   * @return A valid font identifier.
    */
   FontId GetFontId(const BitmapFont& bitmapFont);
 
index 276d876..2d11264 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeAction class is to correspond with Dali::Accessibility::Action.
+ */
 class BridgeAction : public virtual BridgeBase
 {
 protected:
   BridgeAction() = default;
 
+  /**
+   * @brief Registers Action functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Action object of the currently executed DBus method call.
+   *
+   * @return The Action object
+   */
   Dali::Accessibility::Action* FindSelf() const;
 
 public:
+  /**
+   * @copydoc Dali::Accessibility::Action::GetActionName()
+   */
   DBus::ValueOrError<std::string> GetActionName(int32_t index);
+
+  /**
+   * @copydoc Dali::Accessibility::Action::GetLocalizedActionName()
+   */
   DBus::ValueOrError<std::string> GetLocalizedActionName(int32_t index);
+
+  /**
+   * @copydoc Dali::Accessibility::Action::GetActionDescription()
+   */
   DBus::ValueOrError<std::string> GetActionDescription(int32_t index);
+
+  /**
+   * @copydoc Dali::Accessibility::Action::GetActionKeyBinding()
+   */
   DBus::ValueOrError<std::string> GetActionKeyBinding(int32_t index);
-  DBus::ValueOrError<int32_t>     GetActionCount();
-  DBus::ValueOrError<bool>        DoAction(int32_t index);
-  DBus::ValueOrError<bool>        DoActionName(std::string name);
+
+  /**
+   * @copydoc Dali::Accessibility::Action::GetActionCount()
+   */
+  DBus::ValueOrError<int32_t> GetActionCount();
+
+  /**
+   * @copydoc Dali::Accessibility::Action::DoAction()
+   */
+  DBus::ValueOrError<bool> DoAction(int32_t index);
+
+  /**
+   * @copydoc Dali::Accessibility::Action::DoAction()
+   */
+  DBus::ValueOrError<bool> DoActionName(std::string name);
 };
 
 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_ACTION_H
index 21020b3..ca1e417 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
-/*
+/**
+ * @brief The BridgeApplication class is to correspond with Dali::Accessibility::Application.
+ *
  * Implementation of org.a11y.atspi.Application interface
  */
-
 class BridgeApplication : public virtual BridgeBase
 {
 protected:
   BridgeApplication() = default;
 
+  /**
+   * @brief Registers Application functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Application object of the currently executed DBus method call.
+   *
+   * @return The Application object
+   */
   Dali::Accessibility::Application* FindSelf() const;
 
 public:
index 8252465..6795674 100644 (file)
 
 using namespace Dali::Accessibility;
 
+namespace
+{
+/**
+ * @brief Enumeration used for quering Accessibility objects.
+ *
+ * Refer to MatchType enumeration.
+ */
+enum class AtspiCollection
+{
+  MATCH_INVALID,
+  MATCH_ALL,
+  MATCH_ANY,
+  MATCH_NONE,
+  MATCH_EMPTY,
+  MATCH_LAST_DEFINED,
+};
+} // anonymous namespace
+
 void BridgeCollection::RegisterInterfaces()
 {
   DBus::DBusInterfaceDescription desc{AtspiDbusInterfaceCollection};
@@ -45,20 +63,19 @@ Collection* BridgeCollection::FindSelf() const
   return collectionInterface;
 }
 
-enum
-{
-  ATSPI_Collection_MATCH_INVALID,
-  ATSPI_Collection_MATCH_ALL,
-  ATSPI_Collection_MATCH_ANY,
-  ATSPI_Collection_MATCH_NONE,
-  ATSPI_Collection_MATCH_EMPTY,
-  ATSPI_Collection_MATCH_LAST_DEFINED,
-};
-
+/**
+ * @brief The BridgeCollection::Comparer structure.
+ *
+ * Once the data is de-serialized by DBusWrapper, the data of match rule is passed
+ * to Comparer type which do the comparison against a single accessible object.
+ */
 struct BridgeCollection::Comparer
 {
   using Mode = MatchType;
 
+  /**
+   * @brief Enumeration to check the object is found first.
+   */
   enum class CompareFuncExit
   {
     FIRST_FOUND,
@@ -69,23 +86,23 @@ struct BridgeCollection::Comparer
   {
     switch(mode)
     {
-      case ATSPI_Collection_MATCH_INVALID:
+      case static_cast<int32_t>(AtspiCollection::MATCH_INVALID):
       {
         return Mode::INVALID;
       }
-      case ATSPI_Collection_MATCH_ALL:
+      case static_cast<int32_t>(AtspiCollection::MATCH_ALL):
       {
         return Mode::ALL;
       }
-      case ATSPI_Collection_MATCH_ANY:
+      case static_cast<int32_t>(AtspiCollection::MATCH_ANY):
       {
         return Mode::ANY;
       }
-      case ATSPI_Collection_MATCH_NONE:
+      case static_cast<int32_t>(AtspiCollection::MATCH_NONE):
       {
         return Mode::NONE;
       }
-      case ATSPI_Collection_MATCH_EMPTY:
+      case static_cast<int32_t>(AtspiCollection::MATCH_EMPTY):
       {
         return Mode::EMPTY;
       }
@@ -93,43 +110,46 @@ struct BridgeCollection::Comparer
     return Mode::INVALID;
   }
 
+  /**
+   * @brief The ComparerInterfaces structure
+   */
   struct ComparerInterfaces
   {
-    std::unordered_set<std::string> object;
-    std::vector<std::string>        requested;
-    Mode                            mode = Mode::INVALID;
+    std::unordered_set<std::string> mObject;
+    std::vector<std::string>        mRequested;
+    Mode                            mMode = Mode::INVALID;
 
     ComparerInterfaces(MatchRule* rule)
-    : mode(ConvertToMatchType(std::get<Index::InterfacesMatchType>(*rule)))
+    : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::INTERFACES_MATCH_TYPE)>(*rule)))
     {
-      requested = {std::get<Index::Interfaces>(*rule).begin(), std::get<Index::Interfaces>(*rule).end()};
+      mRequested = {std::get<static_cast<std::size_t>(Index::INTERFACES)>(*rule).begin(), std::get<static_cast<std::size_t>(Index::INTERFACES)>(*rule).end()};
     }
 
     void Update(Accessible* obj)
     {
-      object.clear();
+      mObject.clear();
       for(auto& interface : obj->GetInterfaces())
       {
-        object.insert(std::move(interface));
+        mObject.insert(std::move(interface));
       }
     }
 
-    bool RequestEmpty() const
+    bool IsRequestEmpty() const
     {
-      return requested.empty();
+      return mRequested.empty();
     }
 
-    bool ObjectEmpty() const
+    bool IsObjectEmpty() const
     {
-      return object.empty();
+      return mObject.empty();
     }
 
     bool Compare(CompareFuncExit exit)
     {
       bool foundAny = false;
-      for(auto& iname : requested)
+      for(auto& iname : mRequested)
       {
-        bool found = (object.find(iname) != object.end());
+        bool found = (mObject.find(iname) != mObject.end());
         if(found)
         {
           foundAny = true;
@@ -144,39 +164,43 @@ struct BridgeCollection::Comparer
     }
   }; // ComparerInterfaces struct
 
+  /**
+   * @brief The ComparerAttributes structure
+   */
   struct ComparerAttributes
   {
-    std::unordered_map<std::string, std::string> requested, object;
-    Mode                                         mode = Mode::INVALID;
+    std::unordered_map<std::string, std::string> mRequested;
+    std::unordered_map<std::string, std::string> mObject;
+    Mode                                         mMode = Mode::INVALID;
 
     ComparerAttributes(MatchRule* rule)
-    : mode(ConvertToMatchType(std::get<Index::AttributesMatchType>(*rule)))
+    : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::ATTRIBUTES_MATCH_TYPE)>(*rule)))
     {
-      requested = std::get<Index::Attributes>(*rule);
+      mRequested = std::get<static_cast<std::size_t>(Index::ATTRIBUTES)>(*rule);
     }
 
     void Update(Accessible* obj)
     {
-      object = obj->GetAttributes();
+      mObject = obj->GetAttributes();
     }
 
-    bool RequestEmpty() const
+    bool IsRequestEmpty() const
     {
-      return requested.empty();
+      return mRequested.empty();
     }
 
-    bool ObjectEmpty() const
+    bool IsObjectEmpty() const
     {
-      return object.empty();
+      return mObject.empty();
     }
 
     bool Compare(CompareFuncExit exit)
     {
       bool foundAny = false;
-      for(auto& iname : requested)
+      for(auto& iname : mRequested)
       {
-        auto it    = object.find(iname.first);
-        bool found = it != object.end() && iname.second == it->second;
+        auto it    = mObject.find(iname.first);
+        bool found = it != mObject.end() && iname.second == it->second;
         if(found)
         {
           foundAny = true;
@@ -191,38 +215,43 @@ struct BridgeCollection::Comparer
     }
   }; // ComparerAttributes struct
 
+  /**
+   * @brief The ComparerRoles structure
+   */
   struct ComparerRoles
   {
     using Roles = BitSets<4, Role>;
-    Roles requested, object;
-    Mode  mode = Mode::INVALID;
+
+    Roles mRequested;
+    Roles mObject;
+    Mode  mMode = Mode::INVALID;
 
     ComparerRoles(MatchRule* rule)
-    : mode(ConvertToMatchType(std::get<Index::RolesMatchType>(*rule)))
+    : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::ROLES_MATCH_TYPE)>(*rule)))
     {
-      requested = Roles{std::get<Index::Roles>(*rule)};
+      mRequested = Roles{std::get<static_cast<std::size_t>(Index::ROLES)>(*rule)};
     }
 
     void Update(Accessible* obj)
     {
-      object                 = {};
-      object[obj->GetRole()] = true;
-      assert(object);
+      mObject                 = {};
+      mObject[obj->GetRole()] = true;
+      assert(mObject);
     }
 
-    bool RequestEmpty() const
+    bool IsRequestEmpty() const
     {
-      return !requested;
+      return !mRequested;
     }
 
-    bool ObjectEmpty() const
+    bool IsObjectEmpty() const
     {
-      return !object;
+      return !mObject;
     }
 
     bool Compare(CompareFuncExit exit)
     {
-      switch(mode)
+      switch(mMode)
       {
         case Mode::INVALID:
         {
@@ -231,50 +260,54 @@ struct BridgeCollection::Comparer
         case Mode::EMPTY:
         case Mode::ALL:
         {
-          return requested == (object & requested);
+          return mRequested == (mObject & mRequested);
         }
         case Mode::ANY:
         {
-          return bool(object & requested);
+          return bool(mObject & mRequested);
         }
         case Mode::NONE:
         {
-          return bool(object & requested);
+          return bool(mObject & mRequested);
         }
       }
       return false;
     }
   }; // ComparerRoles struct
 
+  /**
+   * @brief The ComparerStates structure
+   */
   struct ComparerStates
   {
-    States requested, object;
-    Mode   mode = Mode::INVALID;
+    States mRequested;
+    States mObject;
+    Mode   mMode = Mode::INVALID;
 
     ComparerStates(MatchRule* rule)
-    : mode(ConvertToMatchType(std::get<Index::StatesMatchType>(*rule)))
+    : mMode(ConvertToMatchType(std::get<static_cast<std::size_t>(Index::STATES_MATCH_TYPE)>(*rule)))
     {
-      requested = States{std::get<Index::States>(*rule)};
+      mRequested = States{std::get<static_cast<std::size_t>(Index::STATES)>(*rule)};
     }
 
     void Update(Accessible* obj)
     {
-      object = obj->GetStates();
+      mObject = obj->GetStates();
     }
 
-    bool RequestEmpty() const
+    bool IsRequestEmpty() const
     {
-      return !requested;
+      return !mRequested;
     }
 
-    bool ObjectEmpty() const
+    bool IsObjectEmpty() const
     {
-      return !object;
+      return !mObject;
     }
 
     bool Compare(CompareFuncExit exit)
     {
-      switch(mode)
+      switch(mMode)
       {
         case Mode::INVALID:
         {
@@ -283,15 +316,15 @@ struct BridgeCollection::Comparer
         case Mode::EMPTY:
         case Mode::ALL:
         {
-          return requested == (object & requested);
+          return mRequested == (mObject & mRequested);
         }
         case Mode::ANY:
         {
-          return bool(object & requested);
+          return bool(mObject & mRequested);
         }
         case Mode::NONE:
         {
-          return bool(object & requested);
+          return bool(mObject & mRequested);
         }
       }
       return false;
@@ -301,17 +334,17 @@ struct BridgeCollection::Comparer
   template<typename T>
   bool CompareFunc(T& cmp, Accessible* obj)
   {
-    if(cmp.mode == Mode::INVALID)
+    if(cmp.mMode == Mode::INVALID)
     {
       return true;
     }
 
     cmp.Update(obj);
-    switch(cmp.mode)
+    switch(cmp.mMode)
     {
       case Mode::ANY:
       {
-        if(cmp.RequestEmpty() || cmp.ObjectEmpty())
+        if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
         {
           return false;
         }
@@ -319,11 +352,11 @@ struct BridgeCollection::Comparer
       }
       case Mode::ALL:
       {
-        if(cmp.RequestEmpty())
+        if(cmp.IsRequestEmpty())
         {
           return true;
         }
-        if(cmp.ObjectEmpty())
+        if(cmp.IsObjectEmpty())
         {
           return false;
         }
@@ -331,7 +364,7 @@ struct BridgeCollection::Comparer
       }
       case Mode::NONE:
       {
-        if(cmp.RequestEmpty() || cmp.ObjectEmpty())
+        if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
         {
           return true;
         }
@@ -339,11 +372,11 @@ struct BridgeCollection::Comparer
       }
       case Mode::EMPTY:
       {
-        if(cmp.RequestEmpty() && cmp.ObjectEmpty())
+        if(cmp.IsRequestEmpty() && cmp.IsObjectEmpty())
         {
           return true;
         }
-        if(cmp.RequestEmpty() || cmp.ObjectEmpty())
+        if(cmp.IsRequestEmpty() || cmp.IsObjectEmpty())
         {
           return false;
         }
@@ -355,7 +388,7 @@ struct BridgeCollection::Comparer
       }
     }
 
-    switch(cmp.mode)
+    switch(cmp.mMode)
     {
       case Mode::EMPTY:
       case Mode::ALL:
@@ -387,7 +420,8 @@ struct BridgeCollection::Comparer
         return true;
       }
     }
-    switch(cmp.mode)
+
+    switch(cmp.mMode)
     {
       case Mode::EMPTY:
       case Mode::ALL:
@@ -407,43 +441,44 @@ struct BridgeCollection::Comparer
     return false;
   }
 
-  ComparerInterfaces interface;
-  ComparerAttributes attribute;
-  ComparerRoles      role;
-  ComparerStates     state;
-
-  Comparer(MatchRule* mr)
-  : interface(mr),
-    attribute(mr),
-    role(mr),
-    state(mr)
+  Comparer(MatchRule* rule)
+  : mInterface(rule),
+    mAttribute(rule),
+    mRole(rule),
+    mState(rule)
   {
   }
 
   bool operator()(Accessible* obj)
   {
-    return CompareFunc(interface, obj) &&
-           CompareFunc(attribute, obj) &&
-           CompareFunc(role, obj) &&
-           CompareFunc(state, obj);
+    return CompareFunc(mInterface, obj) &&
+           CompareFunc(mAttribute, obj) &&
+           CompareFunc(mRole, obj) &&
+           CompareFunc(mState, obj);
   }
+
+  ComparerInterfaces mInterface;
+  ComparerAttributes mAttribute;
+  ComparerRoles      mRole;
+  ComparerStates     mState;
 }; // BridgeCollection::Comparer struct
 
-void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& result, Comparer& cmp, size_t maxCount)
+
+void BridgeCollection::VisitNodes(Accessible* obj, std::vector<Accessible*>& result, Comparer& comparer, size_t maxCount)
 {
   if(maxCount > 0 && result.size() >= maxCount)
   {
     return;
   }
 
-  if(cmp(obj))
+  if(comparer(obj))
   {
     result.emplace_back(obj);
   }
 
   for(auto i = 0u; i < obj->GetChildCount(); ++i)
   {
-    VisitNodes(obj->GetChildAtIndex(i), result, cmp, maxCount);
+    VisitNodes(obj->GetChildAtIndex(i), result, comparer, maxCount);
   }
 }
 
index ad6153a..dc22b1f 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeCollection class is to correspond with Dali::Accessibility::Collection.
+ *
+ * Collection interface is designed to allow AT-Clients to query the tree of accessibility objects
+ * exposed by an application with a single dbus call.
+ * The query takes as an input a match rule and returns zero or more matching accessibility objects as a result.
+ *
+ * A match rule can be a combination of at least one of four criteria :
+ *  Interface, Attribute, Role, State
+ *
+ * If more than one criteria is specified, the matching rule combines them using "AND" semantics.
+ */
 class BridgeCollection : public virtual BridgeBase
 {
 private:
   struct Comparer;
-  static void VisitNodes(Dali::Accessibility::Accessible* obj, std::vector<Dali::Accessibility::Accessible*>& result, Comparer& cmp, size_t maxCount);
+
+  /**
+   * @brief Visits all nodes of Accessible object and pushes the object to 'result' container.
+   *
+   * To query the entire tree, the BridgeCollection::Comparer is used inside this method,
+   * which traverse the tree using GetChildAtIndex().
+   * @param[in] obj The Accessible object to search
+   * @param[out] result The vector container for result
+   * @param[in] comparer BridgeCollection::Comparer which do the comparison against a single accessible object
+   * @param[in] maxCount The maximum count of containing Accessible object
+   */
+  static void VisitNodes(Dali::Accessibility::Accessible* obj, std::vector<Dali::Accessibility::Accessible*>& result, Comparer& comparer, size_t maxCount);
 
 protected:
   BridgeCollection() = default;
 
+  /**
+   * @brief Registers Collection functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Collection object of the currently executed DBus method call.
+   *
+   * @return The Collection object
+   */
   Dali::Accessibility::Collection* FindSelf() const;
 
 public:
+  /**
+   * MatchRule type is a tuple that only carries data of de-serialized parameter from BridgeCollection::GetMatches dbus method.
+   */
   using MatchRule = std::tuple<
     std::array<int32_t, 2>,
     int32_t,
@@ -51,21 +85,31 @@ public:
     std::vector<std::string>,
     int32_t,
     bool>;
-  struct Index
+
+  /**
+   * @brief Enumeration for Collection Index.
+   */
+  enum class Index
   {
-    enum
-    {
-      States,
-      StatesMatchType,
-      Attributes,
-      AttributesMatchType,
-      Roles,
-      RolesMatchType,
-      Interfaces,
-      InterfacesMatchType,
-    };
+    STATES,
+    STATES_MATCH_TYPE,
+    ATTRIBUTES,
+    ATTRIBUTES_MATCH_TYPE,
+    ROLES,
+    ROLES_MATCH_TYPE,
+    INTERFACES,
+    INTERFACES_MATCH_TYPE,
   };
 
+  /**
+   * @brief Gets the matching Accessible objects with MatchRule.
+   *
+   * @param[in] rule BridgeCollection::MatchRule
+   * @param[in] sortBy SortOrder::CANONICAL or SortOrder::REVERSE_CANONICAL
+   * @param[in] count The maximum number of objects
+   * @param[in] traverse True if it is traverse, otherwise false.
+   * @return The matching Accessible objects
+   */
   DBus::ValueOrError<std::vector<Dali::Accessibility::Accessible*> > GetMatches(MatchRule rule, uint32_t sortBy, int32_t count, bool traverse);
 };
 
index 8fa2708..8688689 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeComponent class is to correspond with Dali::Accessibility::Component.
+ */
 class BridgeComponent : public virtual BridgeBase
 {
 protected:
+  /**
+   * @brief Constructor.
+   */
   BridgeComponent();
 
+  /**
+   * @brief Registers Component functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Component object of the currently executed DBus method call.
+   *
+   * @return The Component object
+   */
   Dali::Accessibility::Component* FindSelf() const;
 
 public:
-  DBus::ValueOrError<bool>                                            IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType);
-  DBus::ValueOrError<Dali::Accessibility::Accessible*>                GetAccessibleAtPoint(int32_t x, int32_t y, uint32_t coordType);
+  /**
+   * @copydoc Dali::Accessibility::Component::IsAccessibleContainingPoint()
+   */
+  DBus::ValueOrError<bool> IsAccessibleContainingPoint(int32_t x, int32_t y, uint32_t coordType);
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GetAccessibleAtPoint()
+   */
+  DBus::ValueOrError<Dali::Accessibility::Accessible*> GetAccessibleAtPoint(int32_t x, int32_t y, uint32_t coordType);
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GetExtents()
+   */
   DBus::ValueOrError<std::tuple<int32_t, int32_t, int32_t, int32_t> > GetExtents(uint32_t coordType);
-  DBus::ValueOrError<int32_t, int32_t>                                GetPosition(uint32_t coordType);
-  DBus::ValueOrError<int32_t, int32_t>                                GetSize(uint32_t coordType);
-  DBus::ValueOrError<Dali::Accessibility::ComponentLayer>             GetLayer();
-  DBus::ValueOrError<double>                                          GetAlpha();
-  DBus::ValueOrError<bool>                                            GrabFocus();
-  DBus::ValueOrError<bool>                                            GrabHighlight();
-  DBus::ValueOrError<bool>                                            ClearHighlight();
-  DBus::ValueOrError<int16_t>                                         GetMdiZOrder();
+
+  /**
+   * @brief Gets the position from the given coordinate.
+   * @param[in] coordType The enumeration with type of coordinate systems
+   * @return The X and Y position of rectangle
+   */
+  DBus::ValueOrError<int32_t, int32_t> GetPosition(uint32_t coordType);
+
+  /**
+   * @brief Gets the size from the given coordinate.
+   * @param[in] coordType The enumeration with type of coordinate systems
+   * @return The width and height of rectangle
+   */
+  DBus::ValueOrError<int32_t, int32_t> GetSize(uint32_t coordType);
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GetLayer()
+   */
+  DBus::ValueOrError<Dali::Accessibility::ComponentLayer> GetLayer();
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GetAlpha()
+   */
+  DBus::ValueOrError<double> GetAlpha();
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GrabFocus()
+   */
+  DBus::ValueOrError<bool> GrabFocus();
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GrabHighlight()
+   */
+  DBus::ValueOrError<bool> GrabHighlight();
+
+  /**
+   * @copydoc Dali::Accessibility::Component::ClearHighlight()
+   */
+  DBus::ValueOrError<bool> ClearHighlight();
+
+  /**
+   * @copydoc Dali::Accessibility::Component::GetMdiZOrder()
+   */
+  DBus::ValueOrError<int16_t> GetMdiZOrder();
 };
 
 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_COMPONENT_H
index 33ff63d..3de8dc5 100644 (file)
@@ -47,30 +47,30 @@ EditableText* BridgeEditableText::FindSelf() const
   return editableTextInterface;
 }
 
-DBus::ValueOrError<bool> BridgeEditableText::CopyText(int32_t startPos, int32_t endPos)
+DBus::ValueOrError<bool> BridgeEditableText::CopyText(int32_t startPosition, int32_t endPosition)
 {
-  return FindSelf()->CopyText(startPos, endPos);
+  return FindSelf()->CopyText(startPosition, endPosition);
 }
 
-DBus::ValueOrError<bool> BridgeEditableText::CutText(int32_t startPos, int32_t endPos)
+DBus::ValueOrError<bool> BridgeEditableText::CutText(int32_t startPosition, int32_t endPosition)
 {
-  return FindSelf()->CutText(startPos, endPos);
+  return FindSelf()->CutText(startPosition, endPosition);
 }
 
-DBus::ValueOrError<bool> BridgeEditableText::DeleteText(int32_t startPos, int32_t endPos)
+DBus::ValueOrError<bool> BridgeEditableText::DeleteText(int32_t startPosition, int32_t endPosition)
 {
-  return FindSelf()->DeleteText(startPos, endPos);
+  return FindSelf()->DeleteText(startPosition, endPosition);
 }
 
-DBus::ValueOrError<bool> BridgeEditableText::InsertText(int32_t startPos, std::string text, [[maybe_unused]] int32_t length)
+DBus::ValueOrError<bool> BridgeEditableText::InsertText(int32_t startPosition, std::string text, [[maybe_unused]] int32_t length)
 {
-  return FindSelf()->InsertText(startPos, std::move(text));
+  return FindSelf()->InsertText(startPosition, std::move(text));
 }
 
-DBus::ValueOrError<bool> BridgeEditableText::PasteText(int32_t pos)
+DBus::ValueOrError<bool> BridgeEditableText::PasteText(int32_t position)
 {
   // auto imfManager = Dali::Internal::Adaptor::ImfManager::Get();
-  // imfManager.SetCursorPosition( pos );
+  // imfManager.SetCursorPosition( position );
   // auto clipboard = Dali::Internal::Adaptor::Clipboard::Get();
   // clipboard.RequestItem();
   // return true;
index a6815d0..a123b72 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeEditableText class is to correspond with Dali::Accessibility::EditableText.
+ */
 class BridgeEditableText : public virtual BridgeBase
 {
 protected:
   BridgeEditableText() = default;
 
+  /**
+   * @brief Registers EditableText functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the EditableText object of the currently executed DBus method call.
+   *
+   * @return The EditableText object
+   */
   Dali::Accessibility::EditableText* FindSelf() const;
 
 public:
-  DBus::ValueOrError<bool> CopyText(int32_t startPos, int32_t endPos);
-  DBus::ValueOrError<bool> CutText(int32_t startPos, int32_t endPos);
-  DBus::ValueOrError<bool> DeleteText(int32_t startPos, int32_t endPos);
-  DBus::ValueOrError<bool> InsertText(int32_t startPos, std::string text, int32_t length);
-  DBus::ValueOrError<bool> PasteText(int32_t pos);
+  /**
+   * @copydoc Dali::Accessibility::EditableText::CopyText()
+   */
+  DBus::ValueOrError<bool> CopyText(int32_t startPosition, int32_t endPosition);
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::CutText()
+   */
+  DBus::ValueOrError<bool> CutText(int32_t startPosition, int32_t endPosition);
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::DeleteText()
+   */
+  DBus::ValueOrError<bool> DeleteText(int32_t startPosition, int32_t endPosition);
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::InsertText()
+   */
+  DBus::ValueOrError<bool> InsertText(int32_t startPosition, std::string text, int32_t length);
+
+  /**
+   * @brief Pastes text at position.
+   *
+   * @param[in] position The text position
+   * @return True on success, false otherwise
+   * @note Currently, this function is not implemented yet.
+   */
+  DBus::ValueOrError<bool> PasteText(int32_t position);
+
+  /**
+   * @copydoc Dali::Accessibility::EditableText::SetTextContents()
+   */
   DBus::ValueOrError<bool> SetTextContents(std::string newContents);
 };
 
index eedc5f7..34389a7 100644 (file)
@@ -40,7 +40,7 @@ BridgeObject::BridgeObject()
 void BridgeObject::RegisterInterfaces()
 {
   // DBus::DBusInterfaceDescription desc{ AtspiDbusInterfaceEventObject };
-  // stateChanged = addSignal<std::string, int, int, DBus::EldbusVariant<int>, Accessible*>(desc, "StateChanged");
+  // mStateChanged = addSignal<std::string, int, int, DBus::EldbusVariant<int>, Accessible*>(desc, "StateChanged");
   // mDbusServer.addInterface("/", desc, true);
 }
 
@@ -60,12 +60,12 @@ void BridgeObject::EmitActiveDescendantChanged(Accessible* obj, Accessible* chil
     {"", "root"});
 }
 
-void BridgeObject::Emit(Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent ev)
+void BridgeObject::Emit(Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent event)
 {
   if(!IsUp()) return;
   const char* name = nullptr;
 
-  switch(ev)
+  switch(event)
   {
     case ObjectPropertyChangeEvent::NAME:
     {
index 62f7f3a..918c704 100644 (file)
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 #include <dali/public-api/math/rect.h>
 
+/**
+ * @brief The BridgeObject class is to correspond with Dali::Accessibility::Bridge.
+ */
 class BridgeObject : public virtual BridgeBase
 {
 protected:
+  /**
+   * @brief Constructor.
+   */
   BridgeObject();
 
+  /**
+   * @brief Registers Bridge functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
-  DBus::DBusInterfaceDescription::SignalId stateChanged;
-
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitActiveDescendantChanged()
+   */
   void EmitActiveDescendantChanged(Dali::Accessibility::Accessible* obj, Dali::Accessibility::Accessible* child) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitCursorMoved()
+   */
   void EmitCursorMoved(Dali::Accessibility::Accessible* obj, unsigned int cursorPosition) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitTextChanged()
+   */
   void EmitTextChanged(Dali::Accessibility::Accessible* obj, Dali::Accessibility::TextChangedState state, unsigned int position, unsigned int length, const std::string& content) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitStateChanged()
+   */
   void EmitStateChanged(Dali::Accessibility::Accessible* obj, Dali::Accessibility::State state, int newValue, int reserved) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::Emit()
+   */
   void Emit(Dali::Accessibility::Accessible* obj, Dali::Accessibility::WindowEvent event, unsigned int detail) override;
-  void Emit(Dali::Accessibility::Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent we) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::Emit()
+   */
+  void Emit(Dali::Accessibility::Accessible* obj, Dali::Accessibility::ObjectPropertyChangeEvent event) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitBoundsChanged()
+   */
   void EmitBoundsChanged(Dali::Accessibility::Accessible* obj, Dali::Rect<> rect) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::EmitMovedOutOfScreen()
+   */
   void EmitMovedOutOfScreen(Dali::Accessibility::Accessible* obj, Dali::Accessibility::ScreenRelativeMoveType type) override;
+
+protected:
+  DBus::DBusInterfaceDescription::SignalId mStateChanged;
 };
 
 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_OBJECT_H
index ceb920d..5892544 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeSelection class is to correspond with Dali::Accessibility::Selection.
+ */
 class BridgeSelection : public virtual BridgeBase
 {
 protected:
   BridgeSelection() = default;
 
+  /**
+   * @brief Registers Selection functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Selection object of the currently executed DBus method call.
+   *
+   * @return The Selection object
+   */
   Dali::Accessibility::Selection* FindSelf() const;
 
 public:
+  /**
+   * @copydoc Dali::Accessibility::Selection::GetSelectedChildrenCount()
+   */
   DBus::ValueOrError<int32_t> GetSelectedChildrenCount();
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::GetSelectedChild()
+   */
   DBus::ValueOrError<Dali::Accessibility::Accessible*> GetSelectedChild(int32_t selectedChildIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::SelectChild()
+   */
   DBus::ValueOrError<bool> SelectChild(int32_t childIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::DeselectSelectedChild()
+   */
   DBus::ValueOrError<bool> DeselectSelectedChild(int32_t selectedChildIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::IsChildSelected()
+   */
   DBus::ValueOrError<bool> IsChildSelected(int32_t childIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::SelectAll()
+   */
   DBus::ValueOrError<bool> SelectAll();
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::ClearSelection()
+   */
   DBus::ValueOrError<bool> ClearSelection();
+
+  /**
+   * @copydoc Dali::Accessibility::Selection::DeselectChild()
+   */
   DBus::ValueOrError<bool> DeselectChild(int32_t childIndex);
 };
 
index 54c87f5..1ba0073 100644 (file)
@@ -79,18 +79,18 @@ DBus::ValueOrError<std::string, int, int> BridgeText::GetTextAtOffset(int32_t of
   return {range.content, static_cast<int>(range.startOffset), static_cast<int>(range.endOffset)};
 }
 
-DBus::ValueOrError<int, int> BridgeText::GetRangeOfSelection(int32_t selectionNum)
+DBus::ValueOrError<int, int> BridgeText::GetRangeOfSelection(int32_t selectionIndex)
 {
-  auto range = FindSelf()->GetRangeOfSelection(selectionNum);
+  auto range = FindSelf()->GetRangeOfSelection(selectionIndex);
   return {static_cast<int>(range.startOffset), static_cast<int>(range.endOffset)};
 }
 
-DBus::ValueOrError<bool> BridgeText::RemoveSelection(int32_t selectionNum)
+DBus::ValueOrError<bool> BridgeText::RemoveSelection(int32_t selectionIndex)
 {
-  return FindSelf()->RemoveSelection(selectionNum);
+  return FindSelf()->RemoveSelection(selectionIndex);
 }
 
-DBus::ValueOrError<bool> BridgeText::SetRangeOfSelection(int32_t selectionNum, int32_t startOffset, int32_t endOffset)
+DBus::ValueOrError<bool> BridgeText::SetRangeOfSelection(int32_t selectionIndex, int32_t startOffset, int32_t endOffset)
 {
-  return FindSelf()->SetRangeOfSelection(selectionNum, startOffset, endOffset);
+  return FindSelf()->SetRangeOfSelection(selectionIndex, startOffset, endOffset);
 }
index 86c33d2..49e69e3 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeText class is to correspond with Dali::Accessibility::Text.
+ */
 class BridgeText : public virtual BridgeBase
 {
 protected:
   BridgeText() = default;
 
+  /**
+   * @brief Registers Text functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns the Text object of the currently executed DBus method call.
+   *
+   * @return The Text object
+   */
   Dali::Accessibility::Text* FindSelf() const;
 
 public:
-  DBus::ValueOrError<std::string>           GetText(int startOffset, int endOffset);
-  DBus::ValueOrError<int32_t>               GetCharacterCount();
-  DBus::ValueOrError<int32_t>               GetCursorOffset();
-  DBus::ValueOrError<bool>                  SetCursorOffset(int32_t offset);
+  /**
+   * @copydoc Dali::Accessibility::Text::GetText()
+   */
+  DBus::ValueOrError<std::string> GetText(int startOffset, int endOffset);
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+   */
+  DBus::ValueOrError<int32_t> GetCharacterCount();
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+   */
+  DBus::ValueOrError<int32_t> GetCursorOffset();
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+   */
+  DBus::ValueOrError<bool> SetCursorOffset(int32_t offset);
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+   */
   DBus::ValueOrError<std::string, int, int> GetTextAtOffset(int32_t offset, uint32_t boundary);
-  DBus::ValueOrError<int, int>              GetRangeOfSelection(int32_t selectionNum);
-  DBus::ValueOrError<bool>                  RemoveSelection(int32_t selectionNum);
-  DBus::ValueOrError<bool>                  SetRangeOfSelection(int32_t selectionNum, int32_t startOffset, int32_t endOffset);
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+   */
+  DBus::ValueOrError<int, int> GetRangeOfSelection(int32_t selectionIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Text::RemoveSelection()
+   */
+  DBus::ValueOrError<bool> RemoveSelection(int32_t selectionIndex);
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+   */
+  DBus::ValueOrError<bool> SetRangeOfSelection(int32_t selectionIndex, int32_t startOffset, int32_t endOffset);
 };
 
 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_TEXT_H
index 1919660..e4bfec5 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/internal/accessibility/bridge/bridge-base.h>
 
+/**
+ * @brief The BridgeValue class is to correspond with Dali::Accessibility::Value.
+ */
 class BridgeValue : public virtual BridgeBase
 {
 protected:
+  /**
+   * @brief Constructor.
+   */
   BridgeValue();
 
+  /**
+   * @brief Registers Value functions to dbus interfaces.
+   */
   void RegisterInterfaces();
 
+  /**
+   * @brief Returns Value Action object of the currently executed DBus method call.
+   *
+   * @return The Value object
+   */
   Dali::Accessibility::Value* FindSelf() const;
 
 public:
+  /**
+   * @copydoc Dali::Accessibility::Value::GetCurrent()
+   */
   double GetCurrentValue();
-  void   SetCurrentValue(double newValue);
+
+  /**
+   * @copydoc Dali::Accessibility::Value::SetCurrent()
+   */
+  void SetCurrentValue(double newValue);
+
+  /**
+   * @copydoc Dali::Accessibility::Value::GetMaximum()
+   */
   double GetMaximumValue();
+
+  /**
+   * @copydoc Dali::Accessibility::Value::GetMinimumIncrement()
+   */
   double GetMinimumIncrement();
+
+  /**
+   * @copydoc Dali::Accessibility::Value::GetMinimum()
+   */
   double GetMinimumValue();
 };
 
index 1a420de..7f00ae6 100644 (file)
@@ -3,12 +3,14 @@
 SET( adaptor_text_common_src_files
     ${adaptor_text_dir}/text-abstraction/bidirectional-support-impl.cpp
     ${adaptor_text_dir}/text-abstraction/cairo-renderer.cpp
-    ${adaptor_text_dir}/text-abstraction/font-client-helper.cpp
     ${adaptor_text_dir}/text-abstraction/font-client-impl.cpp
-    ${adaptor_text_dir}/text-abstraction/font-client-plugin-impl.cpp
     ${adaptor_text_dir}/text-abstraction/segmentation-impl.cpp
     ${adaptor_text_dir}/text-abstraction/shaping-impl.cpp
     ${adaptor_text_dir}/text-abstraction/text-renderer-impl.cpp
     ${adaptor_text_dir}/text-abstraction/hyphenation-impl.cpp
+    ${adaptor_text_dir}/text-abstraction/plugin/bitmap-font-cache-item.cpp
+    ${adaptor_text_dir}/text-abstraction/plugin/embedded-item.cpp
+    ${adaptor_text_dir}/text-abstraction/plugin/font-client-utils.cpp
+    ${adaptor_text_dir}/text-abstraction/plugin/font-client-plugin-impl.cpp
+    ${adaptor_text_dir}/text-abstraction/plugin/font-face-cache-item.cpp
 )
-
diff --git a/dali/internal/text/text-abstraction/font-client-helper.cpp b/dali/internal/text/text-abstraction/font-client-helper.cpp
deleted file mode 100644 (file)
index b5e4b91..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS  HEADER
-#include <dali/internal/text/text-abstraction/font-client-helper.h>
-
-// INTERNAL INCLUDES
-
-#include <dali/integration-api/debug.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_FONT_CLIENT_VALUE_TO_INDEX");
-#endif
-} // namespace
-
-namespace Dali
-{
-namespace TextAbstraction
-{
-namespace Internal
-{
-int ValueToIndex(int value, const int* const table, unsigned int maxIndex)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->FontClient::Plugin::ValueToIndex value(%d)\n", value);
-
-  if(NULL == table)
-  {
-    // Return an invalid index if there is no table.
-    return -1;
-  }
-
-  if(value <= table[0])
-  {
-    return 0;
-  }
-
-  if(value >= table[maxIndex])
-  {
-    return maxIndex;
-  }
-
-  for(unsigned int index = 0u; index < maxIndex; ++index)
-  {
-    const int          v1        = table[index];
-    const unsigned int indexPlus = index + 1u;
-    const int          v2        = table[indexPlus];
-    if((v1 < value) && (value <= v2))
-    {
-      const int result = ((v1 > 0) && ((value - v1) < (v2 - value))) ? index : indexPlus;
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "FontClient::Plugin::ValueToIndex result(%d)\n", result);
-      return result;
-    }
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "FontClient::Plugin::ValueToIndex exit 0 <-- \n");
-
-  return 0;
-}
-
-} // namespace Internal
-
-} // namespace TextAbstraction
-
-} // namespace Dali
diff --git a/dali/internal/text/text-abstraction/font-client-helper.h b/dali/internal/text/text-abstraction/font-client-helper.h
deleted file mode 100644 (file)
index 6916ae6..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_FONT_CLIENT_HELPER_H
-#define DALI_INTERNAL_TEXT_ABSTRACTION_FONT_CLIENT_HELPER_H
-
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace TextAbstraction
-{
-namespace Internal
-{
-/**
- * @brief Retrieves a table index for a given value.
- *
- * @param[in] value The value.
- * @param[in] table The table.
- * @param[in] maxIndex The maximum valid index of the table.
- *
- * @return The index to the closest available value
- */
-int ValueToIndex(int value, const int* const table, unsigned int maxIndex);
-
-} // namespace Internal
-
-} // namespace TextAbstraction
-
-} // namespace Dali
-
-#endif // DALI_INTERNAL_TEXT_ABSTRACTION_FONT_CLIENT_HELPER_H
index e6e93fc..70678ca 100644 (file)
@@ -25,7 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/common/singleton-service.h>
-#include <dali/internal/text/text-abstraction/font-client-plugin-impl.h>
+#include <dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h>
 
 #include <dali/devel-api/text-abstraction/glyph-info.h>
 
diff --git a/dali/internal/text/text-abstraction/font-client-plugin-impl.cpp b/dali/internal/text/text-abstraction/font-client-plugin-impl.cpp
deleted file mode 100644 (file)
index f8aa87a..0000000
+++ /dev/null
@@ -1,2968 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali/internal/text/text-abstraction/font-client-plugin-impl.h>
-
-// INTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-list.h>
-
-#include <dali/devel-api/adaptor-framework/image-loading.h>
-#include <dali/integration-api/debug.h>
-#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/font-client-helper.h>
-#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/common/vector-wrapper.h>
-
-// EXTERNAL INCLUDES
-#include <fontconfig/fontconfig.h>
-#include <algorithm>
-#include <iterator>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_FONT_CLIENT");
-#endif
-
-/**
- * Conversion from Fractional26.6 to float
- */
-const float FROM_266        = 1.0f / 64.0f;
-const float POINTS_PER_INCH = 72.f;
-
-const std::string DEFAULT_FONT_FAMILY_NAME("Tizen");
-const int         DEFAULT_FONT_WIDTH  = 100; // normal
-const int         DEFAULT_FONT_WEIGHT = 80;  // normal
-const int         DEFAULT_FONT_SLANT  = 0;   // normal
-
-const uint32_t ELLIPSIS_CHARACTER = 0x2026;
-
-// 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
-// SEMI_CONDENSED  87
-// NORMAL         100
-// SEMI_EXPANDED  113
-// EXPANDED       125
-// EXTRA_EXPANDED 150
-// ULTRA_EXPANDED 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
-// DEMI_LIGHT, SEMI_LIGHT     55
-// BOOK                       75
-// NORMAL, REGULAR            80
-// MEDIUM                    100
-// DEMI_BOLD, SEMI_BOLD      180
-// BOLD                      200
-// ULTRA_BOLD, EXTRA_BOLD    205
-// BLACK, HEAVY, EXTRA_BLACK 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);
-
-// 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;
-using namespace std;
-
-namespace Dali
-{
-namespace TextAbstraction
-{
-namespace Internal
-{
-/**
- * @brief Returns the FontWidth's enum index for the given width value.
- *
- * @param[in] width The width value.
- *
- * @return The FontWidth's enum index.
- */
-FontWidth::Type IntToWidthType(int width)
-{
-  return static_cast<FontWidth::Type>(ValueToIndex(width, FONT_WIDTH_TYPE_TO_INT, NUM_FONT_WIDTH_TYPE - 1u));
-}
-
-/**
- * @brief Returns the FontWeight's enum index for the given weight value.
- *
- * @param[in] weight The weight value.
- *
- * @return The FontWeight's enum index.
- */
-FontWeight::Type IntToWeightType(int weight)
-{
-  return static_cast<FontWeight::Type>(ValueToIndex(weight, FONT_WEIGHT_TYPE_TO_INT, NUM_FONT_WEIGHT_TYPE - 1u));
-}
-
-/**
- * @brief Returns the FontSlant's enum index for the given slant value.
- *
- * @param[in] slant The slant value.
- *
- * @return The FontSlant's enum index.
- */
-FontSlant::Type IntToSlantType(int slant)
-{
-  return static_cast<FontSlant::Type>(ValueToIndex(slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u));
-}
-
-/**
- * @brief Free the resources allocated by the FcCharSet objects.
- *
- * @param[in] characterSets The vector of character sets.
- */
-void DestroyCharacterSets(CharacterSetList& characterSets)
-{
-  for(auto& item : characterSets)
-  {
-    if(item)
-    {
-      FcCharSetDestroy(item);
-    }
-  }
-}
-
-/**
- * @brief Check if @p ftFace and @p requestedPointSize produces block that fit into atlas block
- *
- * @param[in/out] ftFace Face type object.
- * @param[in] horizontalDpi The horizontal dpi.
- * @param[in] verticalDpi The vertical dpi.
- * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
- * @param[in] requestedPointSize The requested point-size.
- * @return whether the  ftFace's block can fit into atlas
- */
-bool IsFitIntoAtlas(FT_Face& ftFace, int& error, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, const uint32_t& requestedPointSize)
-{
-  bool isFit = false;
-
-  error = FT_Set_Char_Size(ftFace,
-                           0,
-                           requestedPointSize,
-                           horizontalDpi,
-                           verticalDpi);
-
-  if(error == FT_Err_Ok)
-  {
-    //Check width and height of block for requestedPointSize
-    //If the width or height is greater than the maximum-size then decrement by one unit of point-size.
-    if(static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height && (static_cast<float>(ftFace->size->metrics.ascender) - static_cast<float>(ftFace->size->metrics.descender)) * FROM_266 <= maxSizeFitInAtlas.width)
-    {
-      isFit = true;
-    }
-  }
-
-  return isFit;
-}
-
-/**
- * @brief Search on proper @p requestedPointSize that produces block that fit into atlas block considering on @p ftFace, @p horizontalDpi, and @p verticalDpi
- *
- * @param[in/out] ftFace Face type object.
- * @param[in] horizontalDpi The horizontal dpi.
- * @param[in] verticalDpi The vertical dpi.
- * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
- * @param[in/out] requestedPointSize The requested point-size.
- * @return FreeType error code. 0 means success when requesting the nominal size (in points).
- */
-int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, uint32_t& requestedPointSize)
-{
-  //To improve performance of sequential search. This code is applying Exponential search then followed by Binary search.
-  const uint32_t& pointSizePerOneUnit = TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  bool            canFitInAtlas;
-  int             error; // FreeType error code.
-
-  canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
-  if(FT_Err_Ok != error)
-  {
-    return error;
-  }
-
-  if(!canFitInAtlas)
-  {
-    //Exponential search
-    uint32_t exponentialDecrement = 1;
-
-    while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit * exponentialDecrement)
-    {
-      requestedPointSize -= (pointSizePerOneUnit * exponentialDecrement);
-      canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
-      if(FT_Err_Ok != error)
-      {
-        return error;
-      }
-
-      exponentialDecrement *= 2;
-    }
-
-    //Binary search
-    uint32_t minPointSize;
-    uint32_t maxPointSize;
-
-    if(canFitInAtlas)
-    {
-      exponentialDecrement /= 2;
-      minPointSize = requestedPointSize;
-      maxPointSize = requestedPointSize + (pointSizePerOneUnit * exponentialDecrement);
-    }
-    else
-    {
-      minPointSize = 0;
-      maxPointSize = requestedPointSize;
-    }
-
-    while(minPointSize < maxPointSize)
-    {
-      requestedPointSize = ((maxPointSize / pointSizePerOneUnit - minPointSize / pointSizePerOneUnit) / 2) * pointSizePerOneUnit + minPointSize;
-      canFitInAtlas      = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
-      if(FT_Err_Ok != error)
-      {
-        return error;
-      }
-
-      if(canFitInAtlas)
-      {
-        if(minPointSize == requestedPointSize)
-        {
-          //Found targeted point-size
-          return error;
-        }
-
-        minPointSize = requestedPointSize;
-      }
-      else
-      {
-        maxPointSize = requestedPointSize;
-      }
-    }
-  }
-
-  return error;
-}
-
-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}
-{
-}
-
-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::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::Plugin(unsigned int horizontalDpi,
-                           unsigned int verticalDpi)
-: mFreeTypeLibrary(nullptr),
-  mDpiHorizontal(horizontalDpi),
-  mDpiVertical(verticalDpi),
-  mDefaultFontDescription(),
-  mSystemFonts(),
-  mDefaultFonts(),
-  mFontIdCache(),
-  mFontFaceCache(),
-  mValidatedFontCache(),
-  mFontDescriptionCache(),
-  mCharacterSetCache(),
-  mFontDescriptionSizeCache(),
-  mVectorFontCache(nullptr),
-  mEllipsisCache(),
-  mEmbeddedItemCache(),
-  mDefaultFontDescriptionCached(false),
-  mIsAtlasLimitationEnabled(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED),
-  mCurrentMaximumBlockSizeFitInAtlas(TextAbstraction::FontClient::MAX_SIZE_FIT_IN_ATLAS)
-
-{
-  int error = FT_Init_FreeType(&mFreeTypeLibrary);
-  if(FT_Err_Ok != 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()
-{
-  ClearFallbackCache(mFallbackCache);
-
-  // Free the resources allocated by the FcCharSet objects.
-  DestroyCharacterSets(mDefaultFontCharacterSets);
-  DestroyCharacterSets(mCharacterSetCache);
-  ClearCharacterSetFromFontFaceCache();
-
-#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
-  delete mVectorFontCache;
-#endif
-  FT_Done_FreeType(mFreeTypeLibrary);
-}
-
-void FontClient::Plugin::ClearCache()
-{
-  mDefaultFontDescription = FontDescription();
-
-  mSystemFonts.clear();
-  mDefaultFonts.clear();
-
-  DestroyCharacterSets(mDefaultFontCharacterSets);
-  mDefaultFontCharacterSets.Clear();
-
-  ClearFallbackCache(mFallbackCache);
-  mFallbackCache.clear();
-
-  mFontIdCache.Clear();
-
-  ClearCharacterSetFromFontFaceCache();
-  mFontFaceCache.clear();
-
-  mValidatedFontCache.clear();
-  mFontDescriptionCache.clear();
-
-  DestroyCharacterSets(mCharacterSetCache);
-  mCharacterSetCache.Clear();
-
-  mFontDescriptionSizeCache.clear();
-
-  mEllipsisCache.Clear();
-  mPixelBufferCache.clear();
-  mEmbeddedItemCache.Clear();
-  mBitmapFontCache.clear();
-
-  mDefaultFontDescriptionCached = false;
-}
-
-void FontClient::Plugin::SetDpi(unsigned int horizontalDpi,
-                                unsigned int verticalDpi)
-{
-  mDpiHorizontal = horizontalDpi;
-  mDpiVertical   = verticalDpi;
-}
-
-void FontClient::Plugin::ResetSystemDefaults()
-{
-  mDefaultFontDescriptionCached = false;
-}
-
-void FontClient::Plugin::SetFontList(const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::SetFontList\n");
-  DALI_LOG_INFO(gLogFilter, Debug::General, "  description; family : [%s]\n", fontDescription.family.c_str());
-  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();
-
-  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  FcResult result = FcResultMatch;
-
-  // Match the pattern.
-  FcFontSet* fontSet = FcFontSort(nullptr /* use default configure */,
-                                  fontFamilyPattern,
-                                  false /* don't trim */,
-                                  nullptr,
-                                  &result); // FcFontSort creates a font set that needs to be destroyed by calling FcFontSetDestroy.
-
-  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);
-
-    for(int i = 0u; i < fontSet->nfont; ++i)
-    {
-      FcPattern* fontPattern = fontSet->fonts[i];
-
-      FontPath path;
-
-      // Skip fonts with no path
-      if(GetFcString(fontPattern, FC_FILE, path))
-      {
-        // Retrieve the character set. Need to call FcCharSetDestroy to free the resources.
-        FcCharSet* characterSet = nullptr;
-        FcPatternGetCharSet(fontPattern, FC_CHARSET, 0u, &characterSet);
-
-        // Increase the reference counter of the character set.
-        characterSetList.PushBack(FcCharSetCopy(characterSet));
-
-        fontList.push_back(FontDescription());
-        FontDescription& newFontDescription = fontList.back();
-
-        newFontDescription.path = std::move(path);
-
-        int width  = 0;
-        int weight = 0;
-        int slant  = 0;
-        GetFcString(fontPattern, FC_FAMILY, newFontDescription.family);
-        GetFcInt(fontPattern, FC_WIDTH, width);
-        GetFcInt(fontPattern, FC_WEIGHT, weight);
-        GetFcInt(fontPattern, FC_SLANT, slant);
-        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]);
-      }
-    }
-
-    // Destroys the font set created by FcFontSort.
-    FcFontSetDestroy(fontSet);
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  No fonts found.\n");
-  }
-
-  // Destroys the pattern created by FcPatternCreate in CreateFontFamilyPattern.
-  FcPatternDestroy(fontFamilyPattern);
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::SetFontList\n");
-}
-
-void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::GetDefaultFonts\n");
-
-  if(mDefaultFonts.empty())
-  {
-    FontDescription fontDescription;
-    fontDescription.family = DEFAULT_FONT_FAMILY_NAME; // todo This could be set to the Platform font
-    fontDescription.width  = IntToWidthType(DEFAULT_FONT_WIDTH);
-    fontDescription.weight = IntToWeightType(DEFAULT_FONT_WEIGHT);
-    fontDescription.slant  = IntToSlantType(DEFAULT_FONT_SLANT);
-    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::General, "-->FontClient::Plugin::GetDefaultPlatformFontDescription\n");
-
-  if(!mDefaultFontDescriptionCached)
-  {
-    // Clear any font config stored info in the caches.
-
-    // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
-    DestroyCharacterSets(mDefaultFontCharacterSets);
-    DestroyCharacterSets(mCharacterSetCache);
-    mDefaultFontCharacterSets.Clear();
-    mCharacterSetCache.Clear();
-
-    for(auto& item : mFallbackCache)
-    {
-      // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
-      DestroyCharacterSets(*item.characterSets);
-
-      delete item.characterSets;
-      item.characterSets = nullptr;
-    }
-
-    // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
-    ClearCharacterSetFromFontFaceCache();
-
-    // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
-    FcInitReinitialize();
-
-    FcPattern* matchPattern = FcPatternCreate(); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
-
-    if(nullptr != matchPattern)
-    {
-      FcConfigSubstitute(nullptr, matchPattern, FcMatchPattern);
-      FcDefaultSubstitute(matchPattern);
-
-      FcCharSet* characterSet = nullptr;
-      MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet);
-      // Decrease the reference counter of the character set as it's not stored.
-      FcCharSetDestroy(characterSet);
-
-      // Destroys the pattern created.
-      FcPatternDestroy(matchPattern);
-    }
-
-    // Create again the character sets as they are not valid after FcInitReinitialize()
-
-    for(const auto& description : mDefaultFonts)
-    {
-      mDefaultFontCharacterSets.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
-    }
-
-    for(const auto& description : mFontDescriptionCache)
-    {
-      mCharacterSetCache.PushBack(FcCharSetCopy(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(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
-        }
-      }
-    }
-
-    mDefaultFontDescriptionCached = true;
-  }
-
-  fontDescription.path   = mDefaultFontDescription.path;
-  fontDescription.family = mDefaultFontDescription.family;
-  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::General, "-->FontClient::Plugin::GetSystemFonts\n");
-
-  if(mSystemFonts.empty())
-  {
-    InitSystemFonts();
-  }
-
-  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
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::GetDescription\n");
-  DALI_LOG_INFO(gLogFilter, Debug::General, "  font id : %d\n", id);
-  const FontId index = id - 1u;
-
-  if((id > 0u) && (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        for(const auto& item : mFontDescriptionSizeCache)
-        {
-          if(item.fontId == fontIdCacheItem.id)
-          {
-            fontDescription = *(mFontDescriptionCache.begin() + item.validatedFontId - 1u);
-
-            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;
-          }
-        }
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        fontDescription.type   = FontDescription::BITMAP_FONT;
-        fontDescription.family = mBitmapFontCache[fontIdCacheItem.id].font.name;
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::General, "  Invalid type of font\n");
-        fontDescription.type = FontDescription::INVALID;
-        fontDescription.family.clear();
-      }
-    }
-  }
-
-  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 < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::General, "  point size : %d\n", (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize);
-        DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::GetPointSize\n");
-        return (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    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;
-}
-
-bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character)
-{
-  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);
-
-  if((fontId < 1u) || (fontId > mFontIdCache.Count()))
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "  Invalid font id. Number of items in the cache: %d\n", mFontIdCache.Count());
-    DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::IsCharacterSupportedByFont\n");
-    return false;
-  }
-
-  --fontId;
-
-  bool isSupported = false;
-
-  const FontIdCacheItem& fontIdCacheItem = mFontIdCache[fontId];
-
-  switch(fontIdCacheItem.type)
-  {
-    case FontDescription::FACE_FONT:
-    {
-      if(fontIdCacheItem.id < mFontFaceCache.size())
-      {
-        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);
-      }
-      break;
-    }
-    case FontDescription::BITMAP_FONT:
-    {
-      const BitmapFont& bitmapFont = mBitmapFontCache[fontIdCacheItem.id].font;
-
-      for(const auto& glyph : bitmapFont.glyphs)
-      {
-        if(glyph.utf32 == character)
-        {
-          isSupported = true;
-          break;
-        }
-      }
-      break;
-    }
-    default:
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::General, "  Invalid type of font\n");
-    }
-  }
-
-  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;
-}
-
-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.");
-
-  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"));
-
-  FontId fontId     = 0u;
-  bool   foundColor = false;
-
-  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,
-                         0u);
-
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "     font id : %d\n", fontId);
-
-      if(preferColor)
-      {
-        if((fontId > 0) &&
-           (fontId - 1u < mFontIdCache.Count()))
-        {
-          const FontFaceCacheItem& item = mFontFaceCache[mFontIdCache[fontId - 1u].id];
-
-          foundColor = item.mHasColorTables;
-        }
-
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  foundColor : %s\n", (foundColor ? "true" : "false"));
-      }
-
-      // Keep going unless we prefer a different (color) font.
-      if(!preferColor || foundColor)
-      {
-        break;
-      }
-    }
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "  font id : %d\n", fontId);
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::FindFontForCharacter\n");
-  return fontId;
-}
-
-FontId FontClient::Plugin::FindDefaultFont(Character       charcode,
-                                           PointSize26Dot6 requestedPointSize,
-                                           bool            preferColor)
-{
-  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);
-
-  // Create the list of default fonts if it has not been created.
-  if(mDefaultFonts.empty())
-  {
-    FontDescription fontDescription;
-    fontDescription.family = DEFAULT_FONT_FAMILY_NAME;
-    fontDescription.width  = IntToWidthType(DEFAULT_FONT_WIDTH);
-    fontDescription.weight = IntToWeightType(DEFAULT_FONT_WEIGHT);
-    fontDescription.slant  = IntToSlantType(DEFAULT_FONT_SLANT);
-
-    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, 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(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;
-
-  // 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         = nullptr;
-  CharacterSetList* characterSetList = nullptr;
-
-  if(!FindFallbackFontList(fontDescription, fontList, characterSetList))
-  {
-    fontList         = new FontList;
-    characterSetList = new CharacterSetList;
-
-    SetFontList(fontDescription, *fontList, *characterSetList);
-#ifdef __APPLE__
-    FontDescription appleColorEmoji;
-    appleColorEmoji.family = "Apple Color Emoji";
-    appleColorEmoji.width  = fontDescription.width;
-    appleColorEmoji.weight = fontDescription.weight;
-    appleColorEmoji.slant  = fontDescription.slant;
-    FontList         emojiFontList;
-    CharacterSetList emojiCharSetList;
-    SetFontList(appleColorEmoji, emojiFontList, emojiCharSetList);
-
-    std::move(fontList->begin(), fontList->end(), std::back_inserter(emojiFontList));
-    emojiCharSetList.Insert(emojiCharSetList.End(), characterSetList->Begin(), characterSetList->End());
-    *fontList         = std::move(emojiFontList);
-    *characterSetList = std::move(emojiCharSetList);
-#endif
-
-    // Add the font-list to the cache.
-    mFallbackCache.push_back(std::move(FallbackCacheItem(std::move(fontDescription), fontList, characterSetList)));
-  }
-
-  if(fontList && characterSetList)
-  {
-    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,
-                                     FaceIndex       faceIndex,
-                                     bool            cacheDescription)
-{
-  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 = 0u;
-
-  if(nullptr != mFreeTypeLibrary)
-  {
-    FontId foundId = 0u;
-    if(FindFont(path, requestedPointSize, faceIndex, foundId))
-    {
-      id = foundId;
-    }
-    else
-    {
-      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,
-                                     FaceIndex              faceIndex)
-{
-  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:
-  // * The bitmap font cache
-  // * Pairs of non validated font descriptions and an index to a vector with paths to font file names.
-  // * The path to font file names.
-  // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
-
-  // 1) Checks if the font description matches with a previously loaded bitmap font.
-  //    Returns if a font is found.
-  // 2) Checks in the cache if the font's description has been validated before.
-  //    If it was it gets an index to the vector with paths to font file names. Otherwise,
-  //    retrieves using font config a path to a font file name which matches with the
-  //    font's description. The path is stored in the cache.
-  //
-  // 3) Checks in the cache if the pair 'font point size, index to the vector with paths to
-  //    font file names' exists. If exists, it gets the font id. If it doesn't it calls
-  //    the GetFontId() method with the path to the font file name and the point size to
-  //    get the font id.
-
-  // The font id to be returned.
-  FontId fontId = 0u;
-
-  // Check first if the font description matches with a previously loaded bitmap font.
-  if(FindBitmapFont(fontDescription.family, fontId))
-  {
-    return fontId;
-  }
-
-  // Check if the font's description have been validated before.
-  FontDescriptionId validatedFontId = 0u;
-
-  if(!FindValidatedFont(fontDescription,
-                        validatedFontId))
-  {
-    // Use font config to validate the font's description.
-    ValidateFont(fontDescription,
-                 validatedFontId);
-  }
-
-  FontId fontFaceId = 0u;
-  // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
-  if(!FindFont(validatedFontId, requestedPointSize, fontFaceId))
-  {
-    // Retrieve the font file name path.
-    const FontDescription& description = *(mFontDescriptionCache.begin() + validatedFontId - 1u);
-
-    // Retrieve the font id. Do not cache the description as it has been already cached.
-    fontId = GetFontId(description.path,
-                       requestedPointSize,
-                       faceIndex,
-                       false);
-
-    fontFaceId                               = mFontIdCache[fontId - 1u].id;
-    mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(mCharacterSetCache[validatedFontId - 1u]);
-
-    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
-                                                                     requestedPointSize,
-                                                                     fontFaceId));
-  }
-  else
-  {
-    fontId = mFontFaceCache[fontFaceId].mFontId + 1u;
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "  font id : %d\n", fontId);
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::GetFontId\n");
-
-  return fontId;
-}
-
-FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
-{
-  for(const auto& item : mBitmapFontCache)
-  {
-    if(bitmapFont.name == item.font.name)
-    {
-      return item.id + 1u;
-    }
-  }
-
-  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;
-  }
-
-  FontIdCacheItem fontIdCacheItem;
-  fontIdCacheItem.type = FontDescription::BITMAP_FONT;
-  fontIdCacheItem.id   = mBitmapFontCache.size();
-
-  mBitmapFontCache.push_back(std::move(bitmapFontCacheItem));
-  mFontIdCache.PushBack(fontIdCacheItem);
-
-  return bitmapFontCacheItem.id + 1u;
-}
-
-void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
-                                      FontDescriptionId&     validatedFontId)
-{
-  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;
-
-  FcCharSet* characterSet = nullptr;
-  bool       matched      = MatchFontDescriptionToPattern(fontFamilyPattern, description, &characterSet);
-  FcPatternDestroy(fontFamilyPattern);
-
-  if(matched && (nullptr != characterSet))
-  {
-    // Add the path to the cache.
-    description.type = FontDescription::FACE_FONT;
-    mFontDescriptionCache.push_back(description);
-
-    // 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);
-
-    // 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);
-
-    mValidatedFontCache.push_back(std::move(item));
-
-    if((fontDescription.family != description.family) ||
-       (fontDescription.width != description.width) ||
-       (fontDescription.weight != description.weight) ||
-       (fontDescription.slant != description.slant))
-    {
-      // Cache the given font's description if it's different than the matched.
-      FontDescriptionCacheItem item(fontDescription,
-                                    validatedFontId);
-
-      mValidatedFontCache.push_back(std::move(item));
-    }
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "  font validation failed for font [%s]\n", fontDescription.family.c_str());
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::ValidateFont\n");
-}
-
-void FontClient::Plugin::GetFontMetrics(FontId       fontId,
-                                        FontMetrics& metrics)
-{
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0) &&
-     (index < mFontIdCache.Count()))
-  {
-    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(gLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
-  }
-}
-
-GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId    fontId,
-                                             Character charcode)
-{
-  GlyphIndex   glyphIndex = 0u;
-  const FontId index      = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      FT_Face ftFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
-
-      glyphIndex = FT_Get_Char_Index(ftFace, charcode);
-    }
-  }
-
-  return glyphIndex;
-}
-
-bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array,
-                                         uint32_t   size,
-                                         GlyphType  type,
-                                         bool       horizontal)
-{
-  if(VECTOR_GLYPH == type)
-  {
-    return GetVectorMetrics(array, size, horizontal);
-  }
-
-  return GetBitmapMetrics(array, size, horizontal);
-}
-
-bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array,
-                                          uint32_t   size,
-                                          bool       horizontal)
-{
-  bool success(true);
-
-  for(unsigned int i = 0; i < size; ++i)
-  {
-    GlyphInfo& glyph = array[i];
-
-    FontId index = glyph.fontId - 1u;
-
-    if((glyph.fontId > 0u) &&
-       (index < mFontIdCache.Count()))
-    {
-      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(gLogFilter, 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(gLogFilter, Debug::General, "  Invalid type of font\n");
-        }
-      }
-    }
-    else
-    {
-      // 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;
-      }
-    }
-  }
-
-  return success;
-}
-
-bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
-                                          uint32_t   size,
-                                          bool       horizontal)
-{
-#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
-  bool success(true);
-
-  for(unsigned int i = 0u; i < size; ++i)
-  {
-    FontId fontId = array[i].fontId;
-
-    if((fontId > 0u) &&
-       (fontId - 1u) < mFontIdCache.Count())
-    {
-      FontFaceCacheItem& font = mFontFaceCache[mFontIdCache[fontId - 1u].id];
-
-      if(!font.mVectorFontId)
-      {
-        font.mVectorFontId = mVectorFontCache->GetFontId(font.mPath);
-      }
-
-      mVectorFontCache->GetGlyphMetrics(font.mVectorFontId, array[i]);
-
-      // Vector metrics are in EMs, convert to pixels
-      const float scale = (static_cast<float>(font.mRequestedPointSize) * FROM_266) * static_cast<float>(mDpiVertical) / POINTS_PER_INCH;
-      array[i].width *= scale;
-      array[i].height *= scale;
-      array[i].xBearing *= scale;
-      array[i].yBearing *= scale;
-      array[i].advance *= scale;
-    }
-    else
-    {
-      success = false;
-    }
-  }
-
-  return success;
-#else
-  return false;
-#endif
-}
-
-void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, 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 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(gLogFilter, 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(gLogFilter, 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(gLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    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.
-      }
-    }
-  }
-}
-
-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       = nullptr;
-  blobLength = 0;
-
-#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
-  if((fontId > 0u) &&
-     (fontId - 1u < mFontIdCache.Count()))
-  {
-    const FontId       fontFaceId = mFontIdCache[fontId - 1u].id;
-    FontFaceCacheItem& font       = mFontFaceCache[fontFaceId];
-
-    if(!font.mVectorFontId)
-    {
-      font.mVectorFontId = mVectorFontCache->GetFontId(font.mPath);
-    }
-
-    mVectorFontCache->GetVectorBlob(font.mVectorFontId, fontFaceId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight);
-  }
-#endif
-}
-
-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(const auto& item : mEllipsisCache)
-  {
-    if(item.requestedPointSize == requestedPointSize)
-    {
-      // 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;
-    }
-  }
-
-  // No glyph has been found. Create one.
-  mEllipsisCache.PushBack(EllipsisItem());
-  EllipsisItem& item = *(mEllipsisCache.End() - 1u);
-
-  item.requestedPointSize = requestedPointSize;
-
-  // Find a font for the ellipsis glyph.
-  item.glyph.fontId = FindDefaultFont(ELLIPSIS_CHARACTER,
-                                      requestedPointSize,
-                                      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,
-                                       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;
-
-  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(gLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-
-  return FT_Err_Ok == error;
-}
-
-FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId)
-{
-  FT_Face fontFace = nullptr;
-
-  const FontId index = fontId - 1u;
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      fontFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
-    }
-  }
-  return fontFace;
-}
-
-FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId)
-{
-  const FontId index = fontId - 1u;
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
-  {
-    return mFontIdCache[index].type;
-  }
-  return FontDescription::INVALID;
-}
-
-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()));
-}
-
-GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat)
-{
-  EmbeddedItem embeddedItem;
-
-  embeddedItem.pixelBufferId = 0u;
-  embeddedItem.width         = description.width;
-  embeddedItem.height        = description.height;
-
-  pixelFormat = Pixel::A8;
-
-  if(!description.url.empty())
-  {
-    // Check if the url is in the cache.
-    PixelBufferId index = 0u;
-
-    for(const auto& cacheItem : mPixelBufferCache)
-    {
-      ++index;
-      if(cacheItem.url == description.url)
-      {
-        // The url is in the pixel buffer cache.
-        // Set the index +1 to the vector.
-        embeddedItem.pixelBufferId = index;
-        break;
-      }
-    }
-
-    Devel::PixelBuffer pixelBuffer;
-    if(0u == embeddedItem.pixelBufferId)
-    {
-      // The pixel buffer is not in the cache. Create one and cache it.
-
-      // Load the image from the url.
-      pixelBuffer = LoadImageFromFile(description.url);
-
-      // Create the cache item.
-      PixelBufferCacheItem pixelBufferCacheItem;
-      pixelBufferCacheItem.pixelBuffer = pixelBuffer;
-      pixelBufferCacheItem.url         = description.url;
-
-      // Store the cache item in the cache.
-      mPixelBufferCache.push_back(std::move(pixelBufferCacheItem));
-
-      // Set the pixel buffer id to the embedded item.
-      embeddedItem.pixelBufferId = mPixelBufferCache.size();
-    }
-    else
-    {
-      // Retrieve the pixel buffer from the cache to set the pixel format.
-      pixelBuffer = mPixelBufferCache[embeddedItem.pixelBufferId - 1u].pixelBuffer;
-    }
-
-    if(pixelBuffer)
-    {
-      // Set the size of the embedded item if it has not been set.
-      if(0u == embeddedItem.width)
-      {
-        embeddedItem.width = static_cast<unsigned int>(pixelBuffer.GetWidth());
-      }
-
-      if(0u == embeddedItem.height)
-      {
-        embeddedItem.height = static_cast<unsigned int>(pixelBuffer.GetHeight());
-      }
-
-      // Set the pixel format.
-      pixelFormat = pixelBuffer.GetPixelFormat();
-    }
-  }
-
-  // Find if the same embeddedItem has already been created.
-  unsigned int index = 0u;
-  for(const auto& item : mEmbeddedItemCache)
-  {
-    ++index;
-    if((item.pixelBufferId == embeddedItem.pixelBufferId) &&
-       (item.width == embeddedItem.width) &&
-       (item.height == embeddedItem.height))
-    {
-      return index;
-    }
-  }
-
-  // Cache the embedded item.
-  mEmbeddedItemCache.PushBack(embeddedItem);
-
-  return mEmbeddedItemCache.Count();
-}
-//SHS
-
-void FontClient::Plugin::EnableAtlasLimitation(bool enabled)
-{
-  mIsAtlasLimitationEnabled = enabled;
-}
-
-bool FontClient::Plugin::IsAtlasLimitationEnabled() const
-{
-  return mIsAtlasLimitationEnabled;
-}
-
-Size FontClient::Plugin::GetMaximumTextAtlasSize() const
-{
-  return TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
-}
-
-Size FontClient::Plugin::GetDefaultTextAtlasSize() const
-{
-  return TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE;
-}
-
-Size FontClient::Plugin::GetCurrentMaximumBlockSizeFitInAtlas() const
-{
-  return mCurrentMaximumBlockSizeFitInAtlas;
-}
-
-bool FontClient::Plugin::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
-{
-  bool            isChanged        = false;
-  const Size&     maxTextAtlasSize = TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
-  const uint16_t& padding          = TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
-
-  if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
-  {
-    mCurrentMaximumBlockSizeFitInAtlas = currentMaximumBlockSizeFitInAtlas;
-    isChanged                          = true;
-  }
-
-  return isChanged;
-}
-
-uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
-{
-  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  ;
-}
-
-void FontClient::Plugin::InitSystemFonts()
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::InitSystemFonts\n");
-
-  FcFontSet* fontSet = GetFcFontSet(); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
-
-  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);
-
-    for(int i = 0u; i < fontSet->nfont; ++i)
-    {
-      FcPattern* fontPattern = fontSet->fonts[i];
-
-      FontPath path;
-
-      // Skip fonts with no path
-      if(GetFcString(fontPattern, FC_FILE, path))
-      {
-        mSystemFonts.push_back(FontDescription());
-        FontDescription& fontDescription = mSystemFonts.back();
-
-        fontDescription.path = std::move(path);
-
-        int width  = 0;
-        int weight = 0;
-        int slant  = 0;
-        GetFcString(fontPattern, FC_FAMILY, fontDescription.family);
-        GetFcInt(fontPattern, FC_WIDTH, width);
-        GetFcInt(fontPattern, FC_WEIGHT, weight);
-        GetFcInt(fontPattern, FC_SLANT, slant);
-        fontDescription.width  = IntToWidthType(width);
-        fontDescription.weight = IntToWeightType(weight);
-        fontDescription.slant  = IntToSlantType(slant);
-
-        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]);
-      }
-    }
-
-    // Destroys the font set created.
-    FcFontSetDestroy(fontSet);
-  }
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::InitSystemFonts\n");
-}
-
-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(nullptr /* use default configure */, pattern, &result); // Creates a new font pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  const bool matched = nullptr != match;
-  DALI_LOG_INFO(gLogFilter, Debug::General, "  pattern matched : %s\n", (matched ? "true" : "false"));
-
-  if(matched)
-  {
-    int width  = 0;
-    int weight = 0;
-    int slant  = 0;
-    GetFcString(match, FC_FILE, fontDescription.path);
-    GetFcString(match, FC_FAMILY, fontDescription.family);
-    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);
-
-    // Retrieve the character set and increase the reference counter.
-    FcPatternGetCharSet(match, FC_CHARSET, 0u, characterSet);
-    *characterSet = FcCharSetCopy(*characterSet);
-
-    // destroyed the matched pattern
-    FcPatternDestroy(match);
-
-    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::MatchFontDescriptionToPattern\n");
-  return matched;
-}
-
-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(); // FcPatternCreate creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  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()));
-
-  // 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);
-
-  // modify the config, with the mFontFamilyPatterm
-  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
-  FcDefaultSubstitute(fontFamilyPattern);
-
-  return fontFamilyPattern;
-}
-
-_FcFontSet* FontClient::Plugin::GetFcFontSet() const
-{
-  FcFontSet* fontset = nullptr;
-
-  // create a new pattern.
-  // a pattern holds a set of names, each name refers to a property of the font
-  FcPattern* pattern = FcPatternCreate();
-
-  if(nullptr != pattern)
-  {
-    // create an object set used to define which properties are to be returned in the patterns from FcFontList.
-    FcObjectSet* objectSet = FcObjectSetCreate();
-
-    if(nullptr != objectSet)
-    {
-      // build an object set from a list of property names
-      FcObjectSetAdd(objectSet, FC_FILE);
-      FcObjectSetAdd(objectSet, FC_FAMILY);
-      FcObjectSetAdd(objectSet, FC_WIDTH);
-      FcObjectSetAdd(objectSet, FC_WEIGHT);
-      FcObjectSetAdd(objectSet, FC_SLANT);
-
-      // get a list of fonts
-      // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
-      fontset = FcFontList(nullptr /* the default configuration is checked to be up to date, and used */, pattern, objectSet); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
-
-      // clear up the object set
-      FcObjectSetDestroy(objectSet);
-    }
-
-    // clear up the pattern
-    FcPatternDestroy(pattern);
-  }
-
-  return fontset;
-}
-
-bool FontClient::Plugin::GetFcString(const FcPattern* const pattern,
-                                     const char* const      n,
-                                     std::string&           string)
-{
-  FcChar8*       file   = nullptr;
-  const FcResult retVal = FcPatternGetString(pattern, n, 0u, &file);
-
-  if(FcResultMatch == retVal)
-  {
-    // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
-    string.assign(reinterpret_cast<const char*>(file));
-
-    return true;
-  }
-
-  return false;
-}
-
-bool FontClient::Plugin::GetFcInt(const _FcPattern* const pattern, const char* const n, int& intVal)
-{
-  const FcResult retVal = FcPatternGetInteger(pattern, n, 0u, &intVal);
-
-  if(FcResultMatch == retVal)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-FontId FontClient::Plugin::CreateFont(const FontPath& path,
-                                      PointSize26Dot6 requestedPointSize,
-                                      FaceIndex       faceIndex,
-                                      bool            cacheDescription)
-{
-  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;
-  int     error = FT_New_Face(mFreeTypeLibrary,
-                          path.c_str(),
-                          0,
-                          &ftFace);
-
-  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));
-    FontId     fontFaceId           = 0u;
-
-    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(!isScalable && hasFixedSizedBitmaps)
-    {
-      PointSize26Dot6 actualPointSize = 0u;
-      int             fixedSizeIndex  = 0;
-      for(; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex)
-      {
-        const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size;
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  size index : %d, size : %d\n", fixedSizeIndex, fixedSize);
-
-        if(fixedSize >= requestedPointSize)
-        {
-          actualPointSize = fixedSize;
-          break;
-        }
-      }
-
-      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;
-      }
-
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize);
-
-      // 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);
-      }
-      else
-      {
-        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);
-
-        // Set the index to the font's id cache.
-        fontFaceCacheItem.mFontId = mFontIdCache.Count();
-
-        // Create the font id item to cache.
-        FontIdCacheItem fontIdCacheItem;
-        fontIdCacheItem.type = FontDescription::FACE_FONT;
-
-        // Set the index to the FreeType font face cache.
-        fontIdCacheItem.id = mFontFaceCache.size();
-        fontFaceId         = fontIdCacheItem.id + 1u;
-
-        // Cache the items.
-        mFontFaceCache.push_back(fontFaceCacheItem);
-        mFontIdCache.PushBack(fontIdCacheItem);
-
-        // Set the font id to be returned.
-        id = mFontIdCache.Count();
-      }
-    }
-    else
-    {
-      if(mIsAtlasLimitationEnabled)
-      {
-        //There is limitation on block size to fit in predefined atlas size.
-        //If the block size cannot fit into atlas size, then the system cannot draw block.
-        //This is workaround to avoid issue in advance
-        //Decrementing point-size until arriving to maximum allowed block size.
-        auto        requestedPointSizeBackup = requestedPointSize;
-        const Size& maxSizeFitInAtlas        = GetCurrentMaximumBlockSizeFitInAtlas();
-        error                                = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
-
-        if(requestedPointSize != requestedPointSizeBackup)
-        {
-          DALI_LOG_WARNING(" The requested-point-size : %d, is reduced to point-size : %d\n", requestedPointSizeBackup, requestedPointSize);
-        }
-      }
-      else
-      {
-        error = FT_Set_Char_Size(ftFace,
-                                 0,
-                                 requestedPointSize,
-                                 mDpiHorizontal,
-                                 mDpiVertical);
-      }
-
-      if(FT_Err_Ok == error)
-      {
-        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);
-
-        // Create the FreeType font face item to cache.
-        FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics);
-
-        // Set the index to the font's id cache.
-        fontFaceCacheItem.mFontId = mFontIdCache.Count();
-
-        // Create the font id item to cache.
-        FontIdCacheItem fontIdCacheItem;
-        fontIdCacheItem.type = FontDescription::FACE_FONT;
-
-        // Set the index to the FreeType font face cache.
-        fontIdCacheItem.id = mFontFaceCache.size();
-        fontFaceId         = fontIdCacheItem.id + 1u;
-
-        // Cache the items.
-        mFontFaceCache.push_back(fontFaceCacheItem);
-        mFontIdCache.PushBack(fontIdCacheItem);
-
-        // Set the font id to be returned.
-        id = mFontIdCache.Count();
-      }
-      else
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::General, "  FreeType Set_Char_Size error: %d for pointSize %d\n", error, requestedPointSize);
-      }
-    }
-
-    if(0u != fontFaceId)
-    {
-      if(cacheDescription)
-      {
-        CacheFontPath(ftFace, fontFaceId, requestedPointSize, path);
-      }
-    }
-  }
-  else
-  {
-    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(TextAbstraction::FontClient::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer)
-{
-  // Set the input dimensions.
-  const ImageDimensions inputDimensions(srcWidth, srcHeight);
-
-  // 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) ? srcWidth : data.width;
-  data.height = (data.height == 0) ? srcHeight : 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, srcBuffer, bufferSize);
-  }
-  else
-  {
-    Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
-                                                inputDimensions,
-                                                data.buffer,
-                                                desiredDimensions);
-  }
-}
-
-void FontClient::Plugin::ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap, bool isShearRequired)
-{
-  if(srcBitmap.width * srcBitmap.rows > 0)
-  {
-    switch(srcBitmap.pixel_mode)
-    {
-      case FT_PIXEL_MODE_GRAY:
-      {
-        if(srcBitmap.pitch == static_cast<int>(srcBitmap.width))
-        {
-          uint8_t*     pixelsIn = srcBitmap.buffer;
-          unsigned int width    = srcBitmap.width;
-          unsigned     height   = srcBitmap.rows;
-
-          std::unique_ptr<uint8_t, void (*)(void*)> pixelsOutPtr(nullptr, free);
-
-          if(isShearRequired)
-          {
-            /**
-             * Glyphs' bitmaps with no slant retrieved from FreeType:
-             * __________     ____
-             * |XXXXXXXX|     |XX|
-             * |   XX   |     |XX|
-             * |   XX   |     |XX|
-             * |   XX   |     |XX|
-             * |   XX   |     |XX|
-             * |   XX   |     |XX|
-             * ----------     ----
-             *
-             * Expected glyphs' bitmaps with italic slant:
-             * ____________   ______
-             * |  XXXXXXXX|   |  XX|
-             * |     XX   |   |  XX|
-             * |    XX    |   | XX |
-             * |    XX    |   | XX |
-             * |   XX     |   |XX  |
-             * |   XX     |   |XX  |
-             * ------------   ------
-             *
-             * Glyphs' bitmaps with software italic slant retrieved from FreeType:
-             * __________     ______
-             * |XXXXXXXX|     |  XX|
-             * |   XX   |     |  XX|
-             * |  XX    |     | XX |
-             * |  XX    |     | XX |
-             * | XX     |     |XX  |
-             * | XX     |     |XX  |
-             * ----------     ------
-             *
-             * This difference in some bitmaps' width causes an overlap of some glyphs. This is the reason why a shear operation is done here instead of relying on the experimental FT_GlyphSlot_Oblique() implementation.
-             */
-            unsigned int widthOut  = 0u;
-            unsigned int heightOut = 0u;
-            uint8_t*     pixelsOut = nullptr;
-
-            Dali::Internal::Platform::HorizontalShear(pixelsIn,
-                                                      width,
-                                                      height,
-                                                      1u,
-                                                      -TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE,
-                                                      pixelsOut,
-                                                      widthOut,
-                                                      heightOut);
-
-            width    = widthOut;
-            height   = heightOut;
-            pixelsIn = pixelsOut;
-            pixelsOutPtr.reset(pixelsOut);
-          }
-
-          const unsigned int bufferSize = width * height;
-          data.buffer                   = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
-          data.width                    = width;
-          data.height                   = height;
-          data.format                   = Pixel::L8; // Sets the pixel format.
-          memcpy(data.buffer, pixelsIn, bufferSize);
-        }
-        break;
-      }
-
-#ifdef FREETYPE_BITMAP_SUPPORT
-      case FT_PIXEL_MODE_BGRA:
-      {
-        if(srcBitmap.pitch == static_cast<int>(srcBitmap.width << 2u))
-        {
-          ConvertBitmap(data, srcBitmap.width, srcBitmap.rows, srcBitmap.buffer);
-
-          // Sets the pixel format.
-          data.format = Pixel::BGRA8888;
-        }
-        break;
-      }
-#endif
-      default:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::General, "FontClient::Plugin::ConvertBitmap. FontClient Unable to create Bitmap of this PixelType\n");
-        break;
-      }
-    }
-  }
-}
-
-bool FontClient::Plugin::FindFont(const FontPath& path,
-                                  PointSize26Dot6 requestedPointSize,
-                                  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(const auto& cacheItem : mFontFaceCache)
-  {
-    if(cacheItem.mRequestedPointSize == requestedPointSize &&
-       cacheItem.mFaceIndex == faceIndex &&
-       cacheItem.mPath == path)
-    {
-      fontId = cacheItem.mFontId + 1u;
-
-      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::FindValidatedFont(const FontDescription& fontDescription,
-                                           FontDescriptionId&     validatedFontId)
-{
-  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(const auto& item : mValidatedFontCache)
-  {
-    if(!fontDescription.family.empty() &&
-       (fontDescription.family == item.fontDescription.family) &&
-       (fontDescription.width == item.fontDescription.width) &&
-       (fontDescription.weight == item.fontDescription.weight) &&
-       (fontDescription.slant == item.fontDescription.slant))
-    {
-      validatedFontId = item.index;
-
-      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::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,
-                                              CharacterSetList*&     characterSetList)
-{
-  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 = nullptr;
-
-  for(const auto& item : mFallbackCache)
-  {
-    if(!fontDescription.family.empty() &&
-       (fontDescription.family == item.fontDescription.family) &&
-       (fontDescription.width == item.fontDescription.width) &&
-       (fontDescription.weight == item.fontDescription.weight) &&
-       (fontDescription.slant == item.fontDescription.slant))
-    {
-      fontList         = item.fallbackFonts;
-      characterSetList = item.characterSets;
-
-      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::General, "  fallback font list not found.\n");
-  DALI_LOG_INFO(gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFontList\n");
-  return false;
-}
-
-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(const auto& item : mFontDescriptionSizeCache)
-  {
-    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::FindBitmapFont(const FontFamily& bitmapFont, FontId& fontId) const
-{
-  fontId = 0u;
-
-  for(const auto& item : mBitmapFontCache)
-  {
-    if(bitmapFont == item.font.name)
-    {
-      fontId = item.id + 1u;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool FontClient::Plugin::IsScalable(const FontPath& path)
-{
-  bool isScalable = false;
-
-  FT_Face ftFace;
-  int     error = FT_New_Face(mFreeTypeLibrary,
-                          path.c_str(),
-                          0,
-                          &ftFace);
-  if(FT_Err_Ok != error)
-  {
-    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 isScalable;
-}
-
-bool FontClient::Plugin::IsScalable(const FontDescription& fontDescription)
-{
-  // Create a font pattern.
-  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  FcResult result = FcResultMatch;
-
-  // match the pattern
-  FcPattern* match      = FcFontMatch(nullptr /* use default configure */, fontFamilyPattern, &result); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
-  bool       isScalable = false;
-
-  if(match)
-  {
-    // Get the path to the font file name.
-    FontPath path;
-    GetFcString(match, FC_FILE, path);
-    isScalable = IsScalable(path);
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str());
-  }
-
-  // Destroys the created patterns.
-  FcPatternDestroy(match);
-  FcPatternDestroy(fontFamilyPattern);
-
-  return isScalable;
-}
-
-void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector<PointSize26Dot6>& sizes)
-{
-  // Empty the caller container
-  sizes.Clear();
-
-  FT_Face ftFace;
-  int     error = FT_New_Face(mFreeTypeLibrary,
-                          path.c_str(),
-                          0,
-                          &ftFace);
-  if(FT_Err_Ok != error)
-  {
-    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
-  if(ftFace->num_fixed_sizes && ftFace->available_sizes)
-  {
-    for(int i = 0; i < ftFace->num_fixed_sizes; ++i)
-    {
-      sizes.PushBack(ftFace->available_sizes[i].size);
-    }
-  }
-}
-
-void FontClient::Plugin::GetFixedSizes(const FontDescription&   fontDescription,
-                                       Vector<PointSize26Dot6>& sizes)
-{
-  // Create a font pattern.
-  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  FcResult result = FcResultMatch;
-
-  // match the pattern
-  FcPattern* match = FcFontMatch(nullptr /* use default configure */, fontFamilyPattern, &result); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  if(match)
-  {
-    // Get the path to the font file name.
-    FontPath path;
-    GetFcString(match, FC_FILE, path);
-    GetFixedSizes(path, sizes);
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str());
-  }
-
-  // Destroys the created patterns.
-  FcPatternDestroy(match);
-  FcPatternDestroy(fontFamilyPattern);
-}
-
-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
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
-  }
-
-  return hasItalicStyle;
-}
-
-void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path)
-{
-  FontDescription description;
-  description.path   = path;
-  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)
-  {
-    description.slant = FontSlant::ITALIC;
-  }
-  if(ftFace->style_flags & FT_STYLE_FLAG_BOLD)
-  {
-    description.weight = FontWeight::BOLD;
-  }
-
-  FontDescriptionId validatedFontId = 0u;
-  if(!FindValidatedFont(description,
-                        validatedFontId))
-  {
-    FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
-    FcResult   result = FcResultMatch;
-    FcPattern* match  = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
-    FcCharSet* characterSet = nullptr;
-    FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
-
-    const FontId fontFaceId                  = id - 1u;
-    mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(characterSet); // Increases the reference counter.
-
-    // Destroys the created patterns.
-    FcPatternDestroy(match);
-    FcPatternDestroy(pattern);
-
-    // Add the path to the cache.
-    description.type = FontDescription::FACE_FONT;
-    mFontDescriptionCache.push_back(description);
-
-    // Set the index to the vector of paths to font file names.
-    validatedFontId = 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)));
-
-    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
-    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
-                                                                     requestedPointSize,
-                                                                     fontFaceId));
-  }
-}
-
-FcCharSet* FontClient::Plugin::CreateCharacterSetFromDescription(const FontDescription& description)
-{
-  FcCharSet* characterSet = nullptr;
-
-  FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
-  if(nullptr != pattern)
-  {
-    FcResult   result = FcResultMatch;
-    FcPattern* match  = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
-    FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
-
-    // Destroys the created patterns.
-    FcPatternDestroy(match);
-    FcPatternDestroy(pattern);
-  }
-
-  return characterSet;
-}
-
-void FontClient::Plugin::ClearFallbackCache(std::vector<FallbackCacheItem>& fallbackCache)
-{
-  for(auto& item : fallbackCache)
-  {
-    if(nullptr != item.fallbackFonts)
-    {
-      delete item.fallbackFonts;
-    }
-
-    if(nullptr != item.characterSets)
-    {
-      // Free the resources allocated by the FcCharSet objects in the 'characterSets' vector.
-      DestroyCharacterSets(*item.characterSets);
-      delete item.characterSets;
-    }
-  }
-}
-
-void FontClient::Plugin::ClearCharacterSetFromFontFaceCache()
-{
-  for(auto& item : mFontFaceCache)
-  {
-    FcCharSetDestroy(item.mCharacterSet);
-    item.mCharacterSet = nullptr;
-  }
-}
-
-} // namespace Internal
-
-} // namespace TextAbstraction
-
-} // namespace Dali
diff --git a/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp
new file mode 100644 (file)
index 0000000..e7b5d43
--- /dev/null
@@ -0,0 +1,140 @@
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h>
+
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+
+#if defined(DEBUG_ENABLED)
+extern Dali::Integration::Log::Filter* gFontClientLogFilter;
+#endif
+
+namespace Dali::TextAbstraction::Internal
+{
+BitmapFontCacheItem::BitmapFontCacheItem(const BitmapFont& bitmapFont, FontId fontId)
+: font(bitmapFont),
+  id(fontId)
+{
+  // Resize the vector with the pixel buffers.
+  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 : font.glyphs)
+  {
+    Devel::PixelBuffer& pixelBuffer = 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());
+      }
+    }
+
+    font.ascender  = std::max(glyph.ascender, font.ascender);
+    font.descender = std::min(glyph.descender, font.descender);
+
+    ++index;
+  }
+}
+
+void BitmapFontCacheItem::GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const
+{
+  metrics.ascender           = font.ascender;
+  metrics.descender          = font.descender;
+  metrics.height             = metrics.ascender - metrics.descender;
+  metrics.underlinePosition  = font.underlinePosition;
+  metrics.underlineThickness = font.underlineThickness;
+}
+
+bool BitmapFontCacheItem::GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const
+{
+  bool success(false);
+
+  unsigned int index = 0u;
+  for(auto& item : font.glyphs)
+  {
+    if(item.utf32 == glyph.index)
+    {
+      Devel::PixelBuffer& pixelBuffer = const_cast<Devel::PixelBuffer&>(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;
+      success           = true;
+      break;
+    }
+    ++index;
+  }
+  return success;
+}
+
+void BitmapFontCacheItem::CreateBitmap(
+  GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
+{
+  unsigned int index = 0u;
+  for(auto& item : font.glyphs)
+  {
+    if(item.utf32 == glyphIndex)
+    {
+      Devel::PixelBuffer& pixelBuffer = const_cast<Devel::PixelBuffer&>(pixelBuffers[index]);
+      if(!pixelBuffer)
+      {
+        pixelBuffer = LoadImageFromFile(item.url);
+      }
+
+      data.width  = pixelBuffer.GetWidth();
+      data.height = pixelBuffer.GetHeight();
+
+      data.isColorBitmap = font.isColorFont;
+
+      ConvertBitmap(data, data.width, data.height, pixelBuffer.GetBuffer());
+
+      // Sets the pixel format.
+      data.format = pixelBuffer.GetPixelFormat();
+      break;
+    }
+    ++index;
+  }
+}
+
+bool BitmapFontCacheItem::IsCharacterSupported(Character character)
+{
+  for(const auto& glyph : font.glyphs)
+  {
+    if(glyph.utf32 == character)
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+} // namespace Dali::TextAbstraction::Internal
diff --git a/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h
new file mode 100644 (file)
index 0000000..d8f083c
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H
+#define DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/text-abstraction/bitmap-font.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+
+#include <dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Dali::TextAbstraction::Internal
+{
+/**
+ * @brief Stores a bitmap font and its pixel buffers per glyph.
+ */
+struct BitmapFontCacheItem : public FontCacheItemInterface
+{
+  /**
+   * Constructor
+   *
+   * @param[in] bitmapFont The font to cache
+   * @param[in] fontId The id of the font
+   */
+  BitmapFontCacheItem(const BitmapFont& bitmapFont, FontId fontId);
+
+  /**
+   * @copydoc FontCacheItemInterface::GetFontMetrics()
+   */
+  void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::GetGlyphMetrics()
+   */
+  bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::CreateBitmap()
+   */
+  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::IsColorGlyph()
+   */
+  bool IsColorGlyph(GlyphIndex glyphIndex) const override
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::IsCharacterSupported()
+   */
+  bool IsCharacterSupported(Character character) override;
+
+  /**
+   * @copydoc FontCacheItemInterface::GetPointSize()
+   */
+  PointSize26Dot6 GetPointSize() const override
+  {
+    return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::GetGlyphIndex()
+   */
+  GlyphIndex GetGlyphIndex(Character character) const override
+  {
+    return 0u;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::GetTypeface()
+   */
+  FT_Face GetTypeface() const override
+  {
+    return nullptr;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::HasItalicStyle()
+   */
+  bool HasItalicStyle() const override
+  {
+    return false;
+  }
+
+  BitmapFont                      font;         ///< The bitmap font.
+  std::vector<Devel::PixelBuffer> pixelBuffers; ///< The pixel buffers of the glyphs.
+  FontId                          id;           ///< Index to the vector with the cache of font's ids.
+};
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif //DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H
diff --git a/dali/internal/text/text-abstraction/plugin/embedded-item.cpp b/dali/internal/text/text-abstraction/plugin/embedded-item.cpp
new file mode 100644 (file)
index 0000000..cdec41f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/text/text-abstraction/plugin/embedded-item.h>
+
+#include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+
+namespace Dali::TextAbstraction::Internal
+{
+void EmbeddedItem::GetGlyphMetrics(GlyphInfo& glyph)
+{
+  glyph.width       = static_cast<float>(width);
+  glyph.height      = static_cast<float>(height);
+  glyph.xBearing    = 0.f;
+  glyph.yBearing    = glyph.height;
+  glyph.advance     = glyph.width;
+  glyph.scaleFactor = 1.f;
+}
+
+void EmbeddedItem::CreateBitmap(const std::vector<PixelBufferCacheItem>&            pixelBufferCache,
+                                Dali::TextAbstraction::FontClient::GlyphBufferData& data)
+{
+  data.width  = width;
+  data.height = height;
+  if(0u != pixelBufferId)
+  {
+    Devel::PixelBuffer pixelBuffer = pixelBufferCache[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.
+  }
+}
+
+} // namespace Dali::TextAbstraction::Internal
diff --git a/dali/internal/text/text-abstraction/plugin/embedded-item.h b/dali/internal/text/text-abstraction/plugin/embedded-item.h
new file mode 100644 (file)
index 0000000..9785a6d
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H
+#define DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/text-abstraction/glyph-info.h>
+#include <dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h>
+
+namespace Dali::TextAbstraction::Internal
+{
+/**
+ * @brief Caches embedded items.
+ */
+struct EmbeddedItem
+{
+  /**
+   * Get metrics for glyph from image
+   * @param[in] item The embedded image
+   * @param[in,out] glyph The glyph to get metrics for
+   */
+  void GetGlyphMetrics(GlyphInfo& glyph);
+
+  /**
+   * @brief Create a glyph bitmap from an embedded item if present in the cache
+   *
+   * @param[in]  pixelBufferCache The pixel buffer cache
+   * @param[out] data The bitmap data.
+   */
+  void CreateBitmap(const std::vector<PixelBufferCacheItem>&            pixelBufferCache,
+                    Dali::TextAbstraction::FontClient::GlyphBufferData& data);
+
+  PixelBufferId pixelBufferId; ///< Index to the vector of pixel buffers
+  unsigned int  width;         ///< The desired width.
+  unsigned int  height;        ///< The desired height.
+};
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif //DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H
diff --git a/dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h b/dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h
new file mode 100644 (file)
index 0000000..805719b
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H
+#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/text-abstraction/font-metrics.h>
+#include <dali/devel-api/text-abstraction/glyph-info.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Dali::TextAbstraction::Internal
+{
+struct FontCacheItemInterface
+{
+  /**
+   * Get the font metrics
+   *
+   * @param[out] metrics The metrics struct to fill out
+   */
+  virtual void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const = 0;
+
+  /**
+   * Get glyph metrics
+   *
+   * @param[in,out] glyph The glyph to fill
+   */
+  virtual bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const = 0;
+
+  /**
+   * Create a bitmap for the given glyph
+   *
+   * @param[in] glyphIndex The index of the glyph
+   * @param[out] data The bitmap data for the glyph
+   * @param[in] outlineWidth
+   * @param[in] isItalicRequired
+   * @param[in] isBoldRequired
+   */
+  virtual void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const = 0;
+
+  /**
+   * Return true if the glyph is colored
+   *
+   * @param[in] glyphIndex The index of the glyph
+   * @return true if the glyph is colored
+   */
+  virtual bool IsColorGlyph(GlyphIndex glyphIndex) const = 0;
+
+  /**
+   * Check if the character is supported by this font
+   * @param[in] character The character to test
+   */
+  virtual bool IsCharacterSupported(Character character) = 0;
+
+  /**
+   * Get the point size of this font
+   * @return the point size
+   */
+  virtual PointSize26Dot6 GetPointSize() const = 0;
+
+  /**
+   * Get the index into this font's glyph table of the character
+   *
+   * @param[in] character to look up
+   * @return the glyph index of this character
+   */
+  virtual GlyphIndex GetGlyphIndex(Character character) const = 0;
+
+  /**
+   * Get the freetype typeface for this font.
+   */
+  virtual FT_Face GetTypeface() const = 0;
+
+  /**
+   * @return true if this font has an italic style
+   */
+  virtual bool HasItalicStyle() const = 0;
+};
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif // DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H
diff --git a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp
new file mode 100644 (file)
index 0000000..e438a53
--- /dev/null
@@ -0,0 +1,1997 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-list.h>
+
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/integration-api/debug.h>
+#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>
+
+// EXTERNAL INCLUDES
+#include <fontconfig/fontconfig.h>
+#include <algorithm>
+#include <iterator>
+
+#if defined(DEBUG_ENABLED)
+
+// Note, to turn on trace and verbose logging, use "export LOG_FONT_CLIENT=3,true"
+// Or re-define the following filter using Verbose,true instead of NoLogging,false,
+// Or, add DALI_LOG_FILTER_ENABLE_TRACE(gFontClientLogFilter) in the code below.
+
+Dali::Integration::Log::Filter* gFontClientLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_FONT_CLIENT");
+
+#define FONT_LOG_DESCRIPTION(fontDescription, prefix)                                                                            \
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, #prefix "  description; family : [%s]\n", fontDescription.family.c_str()); \
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose,                                                                            \
+                "                 path : [%s]\n"                                                                                 \
+                "                width : [%s]\n"                                                                                 \
+                "               weight : [%s]\n"                                                                                 \
+                "                slant : [%s]\n\n",                                                                              \
+                fontDescription.path.c_str(),                                                                                    \
+                FontWidth::Name[fontDescription.width],                                                                          \
+                FontWeight::Name[fontDescription.weight],                                                                        \
+                FontSlant::Name[fontDescription.slant])
+
+#define FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor) \
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General,               \
+                "           character : %p\n"                       \
+                "  requestedPointSize : %d\n"                       \
+                "         preferColor : %s\n",                      \
+                charcode,                                           \
+                requestedPointSize,                                 \
+                (preferColor ? "true" : "false"))
+
+#else
+
+#define FONT_LOG_DESCRIPTION(fontDescription, prefix)
+#define FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor)
+
+#endif
+
+namespace
+{
+/**
+ * Conversion from Fractional26.6 to float
+ */
+const float FROM_266        = 1.0f / 64.0f;
+const float POINTS_PER_INCH = 72.f;
+
+const std::string DEFAULT_FONT_FAMILY_NAME("Tizen");
+
+const uint32_t ELLIPSIS_CHARACTER = 0x2026;
+
+} // namespace
+
+using Dali::Vector;
+using namespace std;
+
+namespace Dali::TextAbstraction::Internal
+{
+/**
+ * @brief Free the resources allocated by the FcCharSet objects.
+ *
+ * @param[in] characterSets The vector of character sets.
+ */
+void DestroyCharacterSets(CharacterSetList& characterSets)
+{
+  for(auto& item : characterSets)
+  {
+    if(item)
+    {
+      FcCharSetDestroy(item);
+    }
+  }
+}
+
+/**
+ * @brief Check if @p ftFace and @p requestedPointSize produces block that fit into atlas block
+ *
+ * @param[in/out] ftFace Face type object.
+ * @param[in] horizontalDpi The horizontal dpi.
+ * @param[in] verticalDpi The vertical dpi.
+ * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
+ * @param[in] requestedPointSize The requested point-size.
+ * @return whether the  ftFace's block can fit into atlas
+ */
+bool IsFitIntoAtlas(FT_Face& ftFace, int& error, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, const uint32_t& requestedPointSize)
+{
+  bool isFit = false;
+
+  error = FT_Set_Char_Size(ftFace,
+                           0,
+                           requestedPointSize,
+                           horizontalDpi,
+                           verticalDpi);
+
+  if(error == FT_Err_Ok)
+  {
+    //Check width and height of block for requestedPointSize
+    //If the width or height is greater than the maximum-size then decrement by one unit of point-size.
+    if(static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height && (static_cast<float>(ftFace->size->metrics.ascender) - static_cast<float>(ftFace->size->metrics.descender)) * FROM_266 <= maxSizeFitInAtlas.width)
+    {
+      isFit = true;
+    }
+  }
+
+  return isFit;
+}
+
+/**
+ * @brief Search on proper @p requestedPointSize that produces block that fit into atlas block considering on @p ftFace, @p horizontalDpi, and @p verticalDpi
+ *
+ * @param[in/out] ftFace Face type object.
+ * @param[in] horizontalDpi The horizontal dpi.
+ * @param[in] verticalDpi The vertical dpi.
+ * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
+ * @param[in/out] requestedPointSize The requested point-size.
+ * @return FreeType error code. 0 means success when requesting the nominal size (in points).
+ */
+int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, uint32_t& requestedPointSize)
+{
+  //To improve performance of sequential search. This code is applying Exponential search then followed by Binary search.
+  const uint32_t& pointSizePerOneUnit = TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  bool            canFitInAtlas;
+  int             error; // FreeType error code.
+
+  canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+  if(FT_Err_Ok != error)
+  {
+    return error;
+  }
+
+  if(!canFitInAtlas)
+  {
+    //Exponential search
+    uint32_t exponentialDecrement = 1;
+
+    while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit * exponentialDecrement)
+    {
+      requestedPointSize -= (pointSizePerOneUnit * exponentialDecrement);
+      canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+      if(FT_Err_Ok != error)
+      {
+        return error;
+      }
+
+      exponentialDecrement *= 2;
+    }
+
+    //Binary search
+    uint32_t minPointSize;
+    uint32_t maxPointSize;
+
+    if(canFitInAtlas)
+    {
+      exponentialDecrement /= 2;
+      minPointSize = requestedPointSize;
+      maxPointSize = requestedPointSize + (pointSizePerOneUnit * exponentialDecrement);
+    }
+    else
+    {
+      minPointSize = 0;
+      maxPointSize = requestedPointSize;
+    }
+
+    while(minPointSize < maxPointSize)
+    {
+      requestedPointSize = ((maxPointSize / pointSizePerOneUnit - minPointSize / pointSizePerOneUnit) / 2) * pointSizePerOneUnit + minPointSize;
+      canFitInAtlas      = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+      if(FT_Err_Ok != error)
+      {
+        return error;
+      }
+
+      if(canFitInAtlas)
+      {
+        if(minPointSize == requestedPointSize)
+        {
+          //Found targeted point-size
+          return error;
+        }
+
+        minPointSize = requestedPointSize;
+      }
+      else
+      {
+        maxPointSize = requestedPointSize;
+      }
+    }
+  }
+
+  return error;
+}
+
+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}
+{
+}
+
+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::Plugin(unsigned int horizontalDpi,
+                           unsigned int verticalDpi)
+: mFreeTypeLibrary(nullptr),
+  mDpiHorizontal(horizontalDpi),
+  mDpiVertical(verticalDpi),
+  mDefaultFontDescription(),
+  mSystemFonts(),
+  mDefaultFonts(),
+  mFontIdCache(),
+  mFontFaceCache(),
+  mValidatedFontCache(),
+  mFontDescriptionCache(),
+  mCharacterSetCache(),
+  mFontDescriptionSizeCache(),
+  mVectorFontCache(nullptr),
+  mEllipsisCache(),
+  mEmbeddedItemCache(),
+  mDefaultFontDescriptionCached(false),
+  mIsAtlasLimitationEnabled(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED),
+  mCurrentMaximumBlockSizeFitInAtlas(TextAbstraction::FontClient::MAX_SIZE_FIT_IN_ATLAS)
+
+{
+  int error = FT_Init_FreeType(&mFreeTypeLibrary);
+  if(FT_Err_Ok != error)
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FreeType Init error: %d\n", error);
+  }
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  mVectorFontCache = new VectorFontCache(mFreeTypeLibrary);
+#endif
+}
+
+FontClient::Plugin::~Plugin()
+{
+  ClearFallbackCache(mFallbackCache);
+
+  // Free the resources allocated by the FcCharSet objects.
+  DestroyCharacterSets(mDefaultFontCharacterSets);
+  DestroyCharacterSets(mCharacterSetCache);
+  ClearCharacterSetFromFontFaceCache();
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  delete mVectorFontCache;
+#endif
+  FT_Done_FreeType(mFreeTypeLibrary);
+}
+
+void FontClient::Plugin::ClearCache()
+{
+  mDefaultFontDescription = FontDescription();
+
+  mSystemFonts.clear();
+  mDefaultFonts.clear();
+
+  DestroyCharacterSets(mDefaultFontCharacterSets);
+  mDefaultFontCharacterSets.Clear();
+
+  ClearFallbackCache(mFallbackCache);
+  mFallbackCache.clear();
+
+  mFontIdCache.Clear();
+
+  ClearCharacterSetFromFontFaceCache();
+  mFontFaceCache.clear();
+
+  mValidatedFontCache.clear();
+  mFontDescriptionCache.clear();
+
+  DestroyCharacterSets(mCharacterSetCache);
+  mCharacterSetCache.Clear();
+
+  mFontDescriptionSizeCache.clear();
+
+  mEllipsisCache.Clear();
+  mPixelBufferCache.clear();
+  mEmbeddedItemCache.Clear();
+  mBitmapFontCache.clear();
+
+  mDefaultFontDescriptionCached = false;
+}
+
+void FontClient::Plugin::SetDpi(unsigned int horizontalDpi,
+                                unsigned int verticalDpi)
+{
+  mDpiHorizontal = horizontalDpi;
+  mDpiVertical   = verticalDpi;
+}
+
+void FontClient::Plugin::ResetSystemDefaults()
+{
+  mDefaultFontDescriptionCached = false;
+}
+
+void FontClient::Plugin::SetFontList(const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_DESCRIPTION(fontDescription, "");
+  fontList.clear();
+
+  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  FcResult result = FcResultMatch;
+
+  // Match the pattern.
+  FcFontSet* fontSet = FcFontSort(nullptr /* use default configure */,
+                                  fontFamilyPattern,
+                                  false /* don't trim */,
+                                  nullptr,
+                                  &result); // FcFontSort creates a font set that needs to be destroyed by calling FcFontSetDestroy.
+
+  if(nullptr != fontSet)
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  number of fonts found : [%d]\n", fontSet->nfont);
+    // Reserve some space to avoid reallocations.
+    fontList.reserve(fontSet->nfont);
+
+    for(int i = 0u; i < fontSet->nfont; ++i)
+    {
+      FcPattern* fontPattern = fontSet->fonts[i];
+
+      FontPath path;
+
+      // Skip fonts with no path
+      if(GetFcString(fontPattern, FC_FILE, path))
+      {
+        // Retrieve the character set. Need to call FcCharSetDestroy to free the resources.
+        FcCharSet* characterSet = nullptr;
+        FcPatternGetCharSet(fontPattern, FC_CHARSET, 0u, &characterSet);
+
+        // Increase the reference counter of the character set.
+        characterSetList.PushBack(FcCharSetCopy(characterSet));
+
+        fontList.push_back(FontDescription());
+        FontDescription& newFontDescription = fontList.back();
+
+        newFontDescription.path = std::move(path);
+
+        int width  = 0;
+        int weight = 0;
+        int slant  = 0;
+        GetFcString(fontPattern, FC_FAMILY, newFontDescription.family);
+        GetFcInt(fontPattern, FC_WIDTH, width);
+        GetFcInt(fontPattern, FC_WEIGHT, weight);
+        GetFcInt(fontPattern, FC_SLANT, slant);
+        newFontDescription.width  = IntToWidthType(width);
+        newFontDescription.weight = IntToWeightType(weight);
+        newFontDescription.slant  = IntToSlantType(slant);
+
+        FONT_LOG_DESCRIPTION(newFontDescription, "");
+      }
+    }
+
+    // Destroys the font set created by FcFontSort.
+    FcFontSetDestroy(fontSet);
+  }
+  else
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  No fonts found.\n");
+  }
+
+  // Destroys the pattern created by FcPatternCreate in CreateFontFamilyPattern.
+  FcPatternDestroy(fontFamilyPattern);
+}
+
+void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+  if(mDefaultFonts.empty())
+  {
+    FontDescription fontDescription;
+    fontDescription.family = DEFAULT_FONT_FAMILY_NAME; // todo This could be set to the Platform font
+    fontDescription.width  = DefaultFontWidth();
+    fontDescription.weight = DefaultFontWeight();
+    fontDescription.slant  = DefaultFontSlant();
+    SetFontList(fontDescription, mDefaultFonts, mDefaultFontCharacterSets);
+  }
+
+  defaultFonts = mDefaultFonts;
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  number of default fonts : [%d]\n", mDefaultFonts.size());
+}
+
+void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& fontDescription)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+  if(!mDefaultFontDescriptionCached)
+  {
+    // Clear any font config stored info in the caches.
+
+    // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
+    DestroyCharacterSets(mDefaultFontCharacterSets);
+    DestroyCharacterSets(mCharacterSetCache);
+    mDefaultFontCharacterSets.Clear();
+    mCharacterSetCache.Clear();
+
+    for(auto& item : mFallbackCache)
+    {
+      // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
+      DestroyCharacterSets(*item.characterSets);
+
+      delete item.characterSets;
+      item.characterSets = nullptr;
+    }
+
+    // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
+    ClearCharacterSetFromFontFaceCache();
+
+    // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
+    FcInitReinitialize();
+
+    FcPattern* matchPattern = FcPatternCreate(); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
+
+    if(nullptr != matchPattern)
+    {
+      FcConfigSubstitute(nullptr, matchPattern, FcMatchPattern);
+      FcDefaultSubstitute(matchPattern);
+
+      FcCharSet* characterSet = nullptr;
+      MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet);
+      // Decrease the reference counter of the character set as it's not stored.
+      FcCharSetDestroy(characterSet);
+
+      // Destroys the pattern created.
+      FcPatternDestroy(matchPattern);
+    }
+
+    // Create again the character sets as they are not valid after FcInitReinitialize()
+
+    for(const auto& description : mDefaultFonts)
+    {
+      mDefaultFontCharacterSets.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
+    }
+
+    for(const auto& description : mFontDescriptionCache)
+    {
+      mCharacterSetCache.PushBack(FcCharSetCopy(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(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
+        }
+      }
+    }
+
+    mDefaultFontDescriptionCached = true;
+  }
+
+  fontDescription.path   = mDefaultFontDescription.path;
+  fontDescription.family = mDefaultFontDescription.family;
+  fontDescription.width  = mDefaultFontDescription.width;
+  fontDescription.weight = mDefaultFontDescription.weight;
+  fontDescription.slant  = mDefaultFontDescription.slant;
+
+  FONT_LOG_DESCRIPTION(fontDescription, "");
+}
+
+void FontClient::Plugin::GetSystemFonts(FontList& systemFonts)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+  if(mSystemFonts.empty())
+  {
+    InitSystemFonts();
+  }
+
+  systemFonts = mSystemFonts;
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  number of system fonts : [%d]\n", mSystemFonts.size());
+}
+
+void FontClient::Plugin::GetDescription(FontId           id,
+                                        FontDescription& fontDescription) const
+{
+  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()))
+  {
+    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+    switch(fontIdCacheItem.type)
+    {
+      case FontDescription::FACE_FONT:
+      {
+        for(const auto& item : mFontDescriptionSizeCache)
+        {
+          if(item.fontId == fontIdCacheItem.id)
+          {
+            fontDescription = *(mFontDescriptionCache.begin() + item.validatedFontId - 1u);
+
+            FONT_LOG_DESCRIPTION(fontDescription, "");
+            return;
+          }
+        }
+        break;
+      }
+      case FontDescription::BITMAP_FONT:
+      {
+        fontDescription.type   = FontDescription::BITMAP_FONT;
+        fontDescription.family = mBitmapFontCache[fontIdCacheItem.id].font.name;
+        break;
+      }
+      default:
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
+        fontDescription.type = FontDescription::INVALID;
+        fontDescription.family.clear();
+      }
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  No description found for the font ID %d\n", id);
+}
+
+PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", id);
+
+  PointSize26Dot6               pointSize     = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(id);
+  if(fontCacheItem != nullptr)
+  {
+    pointSize = fontCacheItem->GetPointSize();
+  }
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  point size : %d\n", pointSize);
+
+  return pointSize;
+}
+
+bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "    font id : %d\n", fontId);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  character : %p\n", character);
+
+  bool isSupported   = false;
+  auto fontCacheItem = const_cast<FontCacheItemInterface*>(GetCachedFontItem(fontId));
+  if(fontCacheItem != nullptr)
+  {
+    isSupported = fontCacheItem->IsCharacterSupported(character); // May cache
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false"));
+  return isSupported;
+}
+
+const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId id) const
+{
+  const FontId index = id - 1u;
+  if((id > 0u) && (index < mFontIdCache.Count()))
+  {
+    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+    switch(fontIdCacheItem.type)
+    {
+      case FontDescription::FACE_FONT:
+      {
+        return &mFontFaceCache[fontIdCacheItem.id];
+      }
+      case FontDescription::BITMAP_FONT:
+      {
+        return &mBitmapFontCache[fontIdCacheItem.id];
+      }
+      default:
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
+      }
+    }
+  }
+  return nullptr;
+}
+
+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.");
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "           character : %p\n", character);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "         preferColor : %s\n", (preferColor ? "true" : "false"));
+
+  FontId fontId     = 0u;
+  bool   foundColor = false;
+
+  DALI_LOG_INFO(gFontClientLogFilter, 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];
+
+    FONT_LOG_DESCRIPTION(description, "");
+
+    bool foundInRanges = false;
+    if(nullptr != characterSet)
+    {
+      foundInRanges = FcCharSetHasChar(characterSet, character);
+    }
+
+    if(foundInRanges)
+    {
+      fontId = GetFontId(description, requestedPointSize, 0u);
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "     font id : %d\n", fontId);
+
+      if(preferColor)
+      {
+        if((fontId > 0) &&
+           (fontId - 1u < mFontIdCache.Count()))
+        {
+          const FontFaceCacheItem& item = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+
+          foundColor = item.mHasColorTables;
+        }
+
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  foundColor : %s\n", (foundColor ? "true" : "false"));
+      }
+
+      // Keep going unless we prefer a different (color) font.
+      if(!preferColor || foundColor)
+      {
+        break;
+      }
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", fontId);
+  return fontId;
+}
+
+FontId FontClient::Plugin::FindDefaultFont(Character       charcode,
+                                           PointSize26Dot6 requestedPointSize,
+                                           bool            preferColor)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor);
+
+  FontId fontId(0);
+
+  // Create the list of default fonts if it has not been created.
+  if(mDefaultFonts.empty())
+  {
+    FontDescription fontDescription;
+    fontDescription.family = DEFAULT_FONT_FAMILY_NAME;
+    fontDescription.width  = DefaultFontWidth();
+    fontDescription.weight = DefaultFontWeight();
+    fontDescription.slant  = DefaultFontSlant();
+
+    SetFontList(fontDescription, mDefaultFonts, mDefaultFontCharacterSets);
+  }
+  DALI_LOG_INFO(gFontClientLogFilter, 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, mDefaultFontCharacterSets, charcode, requestedPointSize, preferColor);
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", fontId);
+  return fontId;
+}
+
+FontId FontClient::Plugin::FindFallbackFont(Character              charcode,
+                                            const FontDescription& preferredFontDescription,
+                                            PointSize26Dot6        requestedPointSize,
+                                            bool                   preferColor)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor);
+
+  // The font id to be returned.
+  FontId fontId = 0u;
+
+  FontDescription 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) ? DefaultFontWeight() : preferredFontDescription.weight);
+  fontDescription.width  = ((FontWidth::NONE == preferredFontDescription.width) ? DefaultFontWidth() : preferredFontDescription.width);
+  fontDescription.slant  = ((FontSlant::NONE == preferredFontDescription.slant) ? DefaultFontSlant() : preferredFontDescription.slant);
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  preferredFontDescription --> fontDescription\n");
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  [%s] --> [%s]\n", preferredFontDescription.family.c_str(), fontDescription.family.c_str());
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  [%s] --> [%s]\n", FontWeight::Name[preferredFontDescription.weight], FontWeight::Name[fontDescription.weight]);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  [%s] --> [%s]\n", FontWidth::Name[preferredFontDescription.width], FontWidth::Name[fontDescription.width]);
+  DALI_LOG_INFO(gFontClientLogFilter, 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         = nullptr;
+  CharacterSetList* characterSetList = nullptr;
+
+  if(!FindFallbackFontList(fontDescription, fontList, characterSetList))
+  {
+    fontList         = new FontList;
+    characterSetList = new CharacterSetList;
+
+    SetFontList(fontDescription, *fontList, *characterSetList);
+#ifdef __APPLE__
+    FontDescription appleColorEmoji;
+    appleColorEmoji.family = "Apple Color Emoji";
+    appleColorEmoji.width  = fontDescription.width;
+    appleColorEmoji.weight = fontDescription.weight;
+    appleColorEmoji.slant  = fontDescription.slant;
+    FontList         emojiFontList;
+    CharacterSetList emojiCharSetList;
+    SetFontList(appleColorEmoji, emojiFontList, emojiCharSetList);
+
+    std::move(fontList->begin(), fontList->end(), std::back_inserter(emojiFontList));
+    emojiCharSetList.Insert(emojiCharSetList.End(), characterSetList->Begin(), characterSetList->End());
+    *fontList         = std::move(emojiFontList);
+    *characterSetList = std::move(emojiCharSetList);
+#endif
+
+    // Add the font-list to the cache.
+    mFallbackCache.push_back(std::move(FallbackCacheItem(std::move(fontDescription), fontList, characterSetList)));
+  }
+
+  if(fontList && characterSetList)
+  {
+    fontId = FindFontForCharacter(*fontList, *characterSetList, charcode, requestedPointSize, preferColor);
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", fontId);
+  return fontId;
+}
+
+FontId FontClient::Plugin::GetFontId(const FontPath& path,
+                                     PointSize26Dot6 requestedPointSize,
+                                     FaceIndex       faceIndex,
+                                     bool            cacheDescription)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "                path : [%s]\n", path.c_str());
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
+
+  FontId id = 0u;
+
+  if(nullptr != mFreeTypeLibrary)
+  {
+    FontId foundId = 0u;
+    if(FindFont(path, requestedPointSize, faceIndex, foundId))
+    {
+      id = foundId;
+    }
+    else
+    {
+      id = CreateFont(path, requestedPointSize, faceIndex, cacheDescription);
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", id);
+  return id;
+}
+
+FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription,
+                                     PointSize26Dot6        requestedPointSize,
+                                     FaceIndex              faceIndex)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_DESCRIPTION(fontDescription, "");
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "   requestedPointSize : %d\n", requestedPointSize);
+
+  // This method uses three vectors which caches:
+  // * The bitmap font cache
+  // * Pairs of non validated font descriptions and an index to a vector with paths to font file names.
+  // * The path to font file names.
+  // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
+
+  // 1) Checks if the font description matches with a previously loaded bitmap font.
+  //    Returns if a font is found.
+  // 2) Checks in the cache if the font's description has been validated before.
+  //    If it was it gets an index to the vector with paths to font file names. Otherwise,
+  //    retrieves using font config a path to a font file name which matches with the
+  //    font's description. The path is stored in the cache.
+  //
+  // 3) Checks in the cache if the pair 'font point size, index to the vector with paths to
+  //    font file names' exists. If exists, it gets the font id. If it doesn't it calls
+  //    the GetFontId() method with the path to the font file name and the point size to
+  //    get the font id.
+
+  // The font id to be returned.
+  FontId fontId = 0u;
+
+  // Check first if the font description matches with a previously loaded bitmap font.
+  if(FindBitmapFont(fontDescription.family, fontId))
+  {
+    return fontId;
+  }
+
+  // Check if the font's description have been validated before.
+  FontDescriptionId validatedFontId = 0u;
+
+  if(!FindValidatedFont(fontDescription,
+                        validatedFontId))
+  {
+    // Use font config to validate the font's description.
+    ValidateFont(fontDescription,
+                 validatedFontId);
+  }
+
+  FontId fontFaceId = 0u;
+  // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
+  if(!FindFont(validatedFontId, requestedPointSize, fontFaceId))
+  {
+    // Retrieve the font file name path.
+    const FontDescription& description = *(mFontDescriptionCache.begin() + validatedFontId - 1u);
+
+    // Retrieve the font id. Do not cache the description as it has been already cached.
+    fontId = GetFontId(description.path,
+                       requestedPointSize,
+                       faceIndex,
+                       false);
+
+    fontFaceId                               = mFontIdCache[fontId - 1u].id;
+    mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(mCharacterSetCache[validatedFontId - 1u]);
+
+    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
+    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
+                                                                     requestedPointSize,
+                                                                     fontFaceId));
+  }
+  else
+  {
+    fontId = mFontFaceCache[fontFaceId].mFontId + 1u;
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", fontId);
+  return fontId;
+}
+
+FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
+{
+  for(const auto& item : mBitmapFontCache)
+  {
+    if(bitmapFont.name == item.font.name)
+    {
+      return item.id + 1u;
+    }
+  }
+
+  BitmapFontCacheItem bitmapFontCacheItem(bitmapFont, mFontIdCache.Count());
+
+  FontIdCacheItem fontIdCacheItem;
+  fontIdCacheItem.type = FontDescription::BITMAP_FONT;
+  fontIdCacheItem.id   = mBitmapFontCache.size();
+
+  mBitmapFontCache.push_back(std::move(bitmapFontCacheItem));
+  mFontIdCache.PushBack(fontIdCacheItem);
+
+  return bitmapFontCacheItem.id + 1u;
+}
+
+void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
+                                      FontDescriptionId&     validatedFontId)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_DESCRIPTION(fontDescription, "");
+
+  // Create a font pattern.
+  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription);
+
+  FontDescription description;
+
+  FcCharSet* characterSet = nullptr;
+  bool       matched      = MatchFontDescriptionToPattern(fontFamilyPattern, description, &characterSet);
+  FcPatternDestroy(fontFamilyPattern);
+
+  if(matched && (nullptr != characterSet))
+  {
+    // Add the path to the cache.
+    description.type = FontDescription::FACE_FONT;
+    mFontDescriptionCache.push_back(description);
+
+    // Set the index to the vector of paths to font file names.
+    validatedFontId = mFontDescriptionCache.size();
+
+    FONT_LOG_DESCRIPTION(description, "matched");
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validatedFontId : %d\n", validatedFontId);
+
+    // 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);
+
+    mValidatedFontCache.push_back(std::move(item));
+
+    if((fontDescription.family != description.family) ||
+       (fontDescription.width != description.width) ||
+       (fontDescription.weight != description.weight) ||
+       (fontDescription.slant != description.slant))
+    {
+      // Cache the given font's description if it's different than the matched.
+      FontDescriptionCacheItem item(fontDescription,
+                                    validatedFontId);
+
+      mValidatedFontCache.push_back(std::move(item));
+    }
+  }
+  else
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font validation failed for font [%s]\n", fontDescription.family.c_str());
+  }
+}
+
+void FontClient::Plugin::GetFontMetrics(FontId       fontId,
+                                        FontMetrics& metrics)
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    fontCacheItem->GetFontMetrics(metrics, mDpiVertical);
+  }
+}
+
+GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId    fontId,
+                                             Character charcode)
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    return fontCacheItem->GetGlyphIndex(charcode);
+  }
+
+  return 0u;
+}
+
+bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array,
+                                         uint32_t   size,
+                                         GlyphType  type,
+                                         bool       horizontal)
+{
+  if(VECTOR_GLYPH == type)
+  {
+    return GetVectorMetrics(array, size, horizontal);
+  }
+
+  return GetBitmapMetrics(array, size, horizontal);
+}
+
+bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array,
+                                          uint32_t   size,
+                                          bool       horizontal)
+{
+  bool success(false);
+
+  for(unsigned int i = 0; i < size; ++i)
+  {
+    GlyphInfo& glyph = array[i];
+
+    const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(glyph.fontId);
+    if(fontCacheItem != nullptr)
+    {
+      success = fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal);
+    }
+    // Check if it's an embedded image.
+    else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
+    {
+      mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph);
+      success = true;
+    }
+  }
+
+  return success;
+}
+
+bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
+                                          uint32_t   size,
+                                          bool       horizontal)
+{
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  bool success(true);
+
+  for(unsigned int i = 0u; i < size; ++i)
+  {
+    FontId fontId = array[i].fontId;
+
+    if((fontId > 0u) &&
+       (fontId - 1u) < mFontIdCache.Count())
+    {
+      FontFaceCacheItem& font = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+
+      if(!font.mVectorFontId)
+      {
+        font.mVectorFontId = mVectorFontCache->GetFontId(font.mPath);
+      }
+
+      mVectorFontCache->GetGlyphMetrics(font.mVectorFontId, array[i]);
+
+      // Vector metrics are in EMs, convert to pixels
+      const float scale = (static_cast<float>(font.mRequestedPointSize) * FROM_266) * static_cast<float>(mDpiVertical) / POINTS_PER_INCH;
+      array[i].width *= scale;
+      array[i].height *= scale;
+      array[i].xBearing *= scale;
+      array[i].yBearing *= scale;
+      array[i].advance *= scale;
+    }
+    else
+    {
+      success = false;
+    }
+  }
+
+  return success;
+#else
+  return false;
+#endif
+}
+
+void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+{
+  data.isColorBitmap                          = false;
+  data.isColorEmoji                           = false;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    fontCacheItem->CreateBitmap(glyphIndex, data, outlineWidth, isItalicRequired, isBoldRequired);
+  }
+  else if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
+  {
+    // It's an embedded item.
+    mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mPixelBufferCache, data);
+  }
+}
+
+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       = nullptr;
+  blobLength = 0;
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+  if((fontId > 0u) &&
+     (fontId - 1u < mFontIdCache.Count()))
+  {
+    const FontId       fontFaceId = mFontIdCache[fontId - 1u].id;
+    FontFaceCacheItem& font       = mFontFaceCache[fontFaceId];
+
+    if(!font.mVectorFontId)
+    {
+      font.mVectorFontId = mVectorFontCache->GetFontId(font.mPath);
+    }
+
+    mVectorFontCache->GetVectorBlob(font.mVectorFontId, fontFaceId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight);
+  }
+#endif
+}
+
+const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedPointSize)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize %d.\n", requestedPointSize);
+
+  // First look into the cache if there is an ellipsis glyph for the requested point size.
+  for(const auto& item : mEllipsisCache)
+  {
+    if(item.requestedPointSize == requestedPointSize)
+    {
+      // Use the glyph in the cache.
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  glyph id %d found in the cache.\n", item.glyph.index);
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "      font %d.\n", item.glyph.fontId);
+      return item.glyph;
+    }
+  }
+
+  // No glyph has been found. Create one.
+  mEllipsisCache.PushBack(EllipsisItem());
+  EllipsisItem& item = *(mEllipsisCache.End() - 1u);
+
+  item.requestedPointSize = requestedPointSize;
+
+  // Find a font for the ellipsis glyph.
+  item.glyph.fontId = FindDefaultFont(ELLIPSIS_CHARACTER,
+                                      requestedPointSize,
+                                      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,
+                                       ELLIPSIS_CHARACTER);
+
+  GetBitmapMetrics(&item.glyph, 1u, true);
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  glyph id %d found in the cache.\n", item.glyph.index);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "      font %d.\n", item.glyph.fontId);
+  return item.glyph;
+}
+
+bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex)
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  return fontCacheItem && fontCacheItem->IsColorGlyph(glyphIndex);
+}
+
+FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId)
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    return fontCacheItem->GetTypeface();
+  }
+  return nullptr;
+}
+
+FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId)
+{
+  const FontId index = fontId - 1u;
+  if((fontId > 0u) &&
+     (index < mFontIdCache.Count()))
+  {
+    return mFontIdCache[index].type;
+  }
+  return FontDescription::INVALID;
+}
+
+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()));
+}
+
+GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat)
+{
+  EmbeddedItem embeddedItem;
+
+  embeddedItem.pixelBufferId = 0u;
+  embeddedItem.width         = description.width;
+  embeddedItem.height        = description.height;
+
+  pixelFormat = Pixel::A8;
+
+  if(!description.url.empty())
+  {
+    // Check if the url is in the cache.
+    PixelBufferId index = 0u;
+
+    for(const auto& cacheItem : mPixelBufferCache)
+    {
+      ++index;
+      if(cacheItem.url == description.url)
+      {
+        // The url is in the pixel buffer cache.
+        // Set the index +1 to the vector.
+        embeddedItem.pixelBufferId = index;
+        break;
+      }
+    }
+
+    Devel::PixelBuffer pixelBuffer;
+    if(0u == embeddedItem.pixelBufferId)
+    {
+      // The pixel buffer is not in the cache. Create one and cache it.
+
+      // Load the image from the url.
+      pixelBuffer = LoadImageFromFile(description.url);
+
+      // Create the cache item.
+      PixelBufferCacheItem pixelBufferCacheItem;
+      pixelBufferCacheItem.pixelBuffer = pixelBuffer;
+      pixelBufferCacheItem.url         = description.url;
+
+      // Store the cache item in the cache.
+      mPixelBufferCache.push_back(std::move(pixelBufferCacheItem));
+
+      // Set the pixel buffer id to the embedded item.
+      embeddedItem.pixelBufferId = mPixelBufferCache.size();
+    }
+    else
+    {
+      // Retrieve the pixel buffer from the cache to set the pixel format.
+      pixelBuffer = mPixelBufferCache[embeddedItem.pixelBufferId - 1u].pixelBuffer;
+    }
+
+    if(pixelBuffer)
+    {
+      // Set the size of the embedded item if it has not been set.
+      if(0u == embeddedItem.width)
+      {
+        embeddedItem.width = static_cast<unsigned int>(pixelBuffer.GetWidth());
+      }
+
+      if(0u == embeddedItem.height)
+      {
+        embeddedItem.height = static_cast<unsigned int>(pixelBuffer.GetHeight());
+      }
+
+      // Set the pixel format.
+      pixelFormat = pixelBuffer.GetPixelFormat();
+    }
+  }
+
+  // Find if the same embeddedItem has already been created.
+  unsigned int index = 0u;
+  for(const auto& item : mEmbeddedItemCache)
+  {
+    ++index;
+    if((item.pixelBufferId == embeddedItem.pixelBufferId) &&
+       (item.width == embeddedItem.width) &&
+       (item.height == embeddedItem.height))
+    {
+      return index;
+    }
+  }
+
+  // Cache the embedded item.
+  mEmbeddedItemCache.PushBack(embeddedItem);
+
+  return mEmbeddedItemCache.Count();
+}
+
+void FontClient::Plugin::EnableAtlasLimitation(bool enabled)
+{
+  mIsAtlasLimitationEnabled = enabled;
+}
+
+bool FontClient::Plugin::IsAtlasLimitationEnabled() const
+{
+  return mIsAtlasLimitationEnabled;
+}
+
+Size FontClient::Plugin::GetMaximumTextAtlasSize() const
+{
+  return TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::Plugin::GetDefaultTextAtlasSize() const
+{
+  return TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::Plugin::GetCurrentMaximumBlockSizeFitInAtlas() const
+{
+  return mCurrentMaximumBlockSizeFitInAtlas;
+}
+
+bool FontClient::Plugin::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+{
+  bool            isChanged        = false;
+  const Size&     maxTextAtlasSize = TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
+  const uint16_t& padding          = TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+
+  if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
+  {
+    mCurrentMaximumBlockSizeFitInAtlas = currentMaximumBlockSizeFitInAtlas;
+    isChanged                          = true;
+  }
+
+  return isChanged;
+}
+
+uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
+{
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  ;
+}
+
+void FontClient::Plugin::InitSystemFonts()
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+  FcFontSet* fontSet = GetFcFontSet(); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
+
+  if(fontSet)
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  number of system fonts : %d\n", fontSet->nfont);
+
+    // Reserve some space to avoid reallocations.
+    mSystemFonts.reserve(fontSet->nfont);
+
+    for(int i = 0u; i < fontSet->nfont; ++i)
+    {
+      FcPattern* fontPattern = fontSet->fonts[i];
+
+      FontPath path;
+
+      // Skip fonts with no path
+      if(GetFcString(fontPattern, FC_FILE, path))
+      {
+        mSystemFonts.push_back(FontDescription());
+        FontDescription& fontDescription = mSystemFonts.back();
+
+        fontDescription.path = std::move(path);
+
+        int width  = 0;
+        int weight = 0;
+        int slant  = 0;
+        GetFcString(fontPattern, FC_FAMILY, fontDescription.family);
+        GetFcInt(fontPattern, FC_WIDTH, width);
+        GetFcInt(fontPattern, FC_WEIGHT, weight);
+        GetFcInt(fontPattern, FC_SLANT, slant);
+        fontDescription.width  = IntToWidthType(width);
+        fontDescription.weight = IntToWeightType(weight);
+        fontDescription.slant  = IntToSlantType(slant);
+
+        FONT_LOG_DESCRIPTION(fontDescription, "");
+      }
+    }
+
+    // Destroys the font set created.
+    FcFontSetDestroy(fontSet);
+  }
+}
+
+bool FontClient::Plugin::MatchFontDescriptionToPattern(FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+  FcResult   result = FcResultMatch;
+  FcPattern* match  = FcFontMatch(nullptr /* use default configure */, pattern, &result); // Creates a new font pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  const bool matched = nullptr != match;
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  pattern matched : %s\n", (matched ? "true" : "false"));
+
+  if(matched)
+  {
+    int width  = 0;
+    int weight = 0;
+    int slant  = 0;
+    GetFcString(match, FC_FILE, fontDescription.path);
+    GetFcString(match, FC_FAMILY, fontDescription.family);
+    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);
+
+    // Retrieve the character set and increase the reference counter.
+    FcPatternGetCharSet(match, FC_CHARSET, 0u, characterSet);
+    *characterSet = FcCharSetCopy(*characterSet);
+
+    // destroyed the matched pattern
+    FcPatternDestroy(match);
+    FONT_LOG_DESCRIPTION(fontDescription, "");
+  }
+  return matched;
+}
+
+_FcFontSet* FontClient::Plugin::GetFcFontSet() const
+{
+  FcFontSet* fontset = nullptr;
+
+  // create a new pattern.
+  // a pattern holds a set of names, each name refers to a property of the font
+  FcPattern* pattern = FcPatternCreate();
+
+  if(nullptr != pattern)
+  {
+    // create an object set used to define which properties are to be returned in the patterns from FcFontList.
+    FcObjectSet* objectSet = FcObjectSetCreate();
+
+    if(nullptr != objectSet)
+    {
+      // build an object set from a list of property names
+      FcObjectSetAdd(objectSet, FC_FILE);
+      FcObjectSetAdd(objectSet, FC_FAMILY);
+      FcObjectSetAdd(objectSet, FC_WIDTH);
+      FcObjectSetAdd(objectSet, FC_WEIGHT);
+      FcObjectSetAdd(objectSet, FC_SLANT);
+
+      // get a list of fonts
+      // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
+      fontset = FcFontList(nullptr /* the default configuration is checked to be up to date, and used */, pattern, objectSet); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
+
+      // clear up the object set
+      FcObjectSetDestroy(objectSet);
+    }
+
+    // clear up the pattern
+    FcPatternDestroy(pattern);
+  }
+
+  return fontset;
+}
+
+bool FontClient::Plugin::GetFcString(const FcPattern* const pattern,
+                                     const char* const      n,
+                                     std::string&           string)
+{
+  FcChar8*       file   = nullptr;
+  const FcResult retVal = FcPatternGetString(pattern, n, 0u, &file);
+
+  if(FcResultMatch == retVal)
+  {
+    // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
+    string.assign(reinterpret_cast<const char*>(file));
+
+    return true;
+  }
+
+  return false;
+}
+
+bool FontClient::Plugin::GetFcInt(const _FcPattern* const pattern, const char* const n, int& intVal)
+{
+  const FcResult retVal = FcPatternGetInteger(pattern, n, 0u, &intVal);
+
+  if(FcResultMatch == retVal)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+FontId FontClient::Plugin::CreateFont(const FontPath& path,
+                                      PointSize26Dot6 requestedPointSize,
+                                      FaceIndex       faceIndex,
+                                      bool            cacheDescription)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "                path : [%s]\n", path.c_str());
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
+
+  FontId id = 0u;
+
+  // Create & cache new font face
+  FT_Face ftFace;
+  int     error = FT_New_Face(mFreeTypeLibrary,
+                          path.c_str(),
+                          0,
+                          &ftFace);
+
+  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));
+    FontId     fontFaceId           = 0u;
+
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "            isScalable : [%s]\n", (isScalable ? "true" : "false"));
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  hasFixedSizedBitmaps : [%s]\n", (hasFixedSizedBitmaps ? "true" : "false"));
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "        hasColorTables : [%s]\n", (hasColorTables ? "true" : "false"));
+
+    // Check to see if the font contains fixed sizes?
+    if(!isScalable && hasFixedSizedBitmaps)
+    {
+      PointSize26Dot6 actualPointSize = 0u;
+      int             fixedSizeIndex  = 0;
+      for(; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex)
+      {
+        const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size;
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  size index : %d, size : %d\n", fixedSizeIndex, fixedSize);
+
+        if(fixedSize >= requestedPointSize)
+        {
+          actualPointSize = fixedSize;
+          break;
+        }
+      }
+
+      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;
+      }
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize);
+
+      // Tell Freetype to use this size
+      error = FT_Select_Size(ftFace, fixedSizeIndex);
+      if(FT_Err_Ok != error)
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FreeType Select_Size error: %d\n", error);
+      }
+      else
+      {
+        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(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
+
+        // Set the index to the font's id cache.
+        fontFaceCacheItem.mFontId = mFontIdCache.Count();
+
+        // Create the font id item to cache.
+        FontIdCacheItem fontIdCacheItem;
+        fontIdCacheItem.type = FontDescription::FACE_FONT;
+
+        // Set the index to the FreeType font face cache.
+        fontIdCacheItem.id = mFontFaceCache.size();
+        fontFaceId         = fontIdCacheItem.id + 1u;
+
+        // Cache the items.
+        mFontFaceCache.push_back(fontFaceCacheItem);
+        mFontIdCache.PushBack(fontIdCacheItem);
+
+        // Set the font id to be returned.
+        id = mFontIdCache.Count();
+      }
+    }
+    else
+    {
+      if(mIsAtlasLimitationEnabled)
+      {
+        //There is limitation on block size to fit in predefined atlas size.
+        //If the block size cannot fit into atlas size, then the system cannot draw block.
+        //This is workaround to avoid issue in advance
+        //Decrementing point-size until arriving to maximum allowed block size.
+        auto        requestedPointSizeBackup = requestedPointSize;
+        const Size& maxSizeFitInAtlas        = GetCurrentMaximumBlockSizeFitInAtlas();
+        error                                = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
+
+        if(requestedPointSize != requestedPointSizeBackup)
+        {
+          DALI_LOG_WARNING(" The requested-point-size : %d, is reduced to point-size : %d\n", requestedPointSizeBackup, requestedPointSize);
+        }
+      }
+      else
+      {
+        error = FT_Set_Char_Size(ftFace,
+                                 0,
+                                 requestedPointSize,
+                                 mDpiHorizontal,
+                                 mDpiVertical);
+      }
+
+      if(FT_Err_Ok == error)
+      {
+        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);
+
+        // Create the FreeType font face item to cache.
+        FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics);
+
+        // Set the index to the font's id cache.
+        fontFaceCacheItem.mFontId = mFontIdCache.Count();
+
+        // Create the font id item to cache.
+        FontIdCacheItem fontIdCacheItem;
+        fontIdCacheItem.type = FontDescription::FACE_FONT;
+
+        // Set the index to the FreeType font face cache.
+        fontIdCacheItem.id = mFontFaceCache.size();
+        fontFaceId         = fontIdCacheItem.id + 1u;
+
+        // Cache the items.
+        mFontFaceCache.push_back(fontFaceCacheItem);
+        mFontIdCache.PushBack(fontIdCacheItem);
+
+        // Set the font id to be returned.
+        id = mFontIdCache.Count();
+      }
+      else
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  FreeType Set_Char_Size error: %d for pointSize %d\n", error, requestedPointSize);
+      }
+    }
+
+    if(0u != fontFaceId)
+    {
+      if(cacheDescription)
+      {
+        CacheFontPath(ftFace, fontFaceId, requestedPointSize, path);
+      }
+    }
+  }
+  else
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  FreeType New_Face error: %d for [%s]\n", error, path.c_str());
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", id);
+  return id;
+}
+
+bool FontClient::Plugin::FindFont(const FontPath& path,
+                                  PointSize26Dot6 requestedPointSize,
+                                  FaceIndex       faceIndex,
+                                  FontId&         fontId) const
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "                path : [%s]\n", path.c_str());
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  number of fonts in the cache : %d\n", mFontFaceCache.size());
+
+  fontId = 0u;
+  for(const auto& cacheItem : mFontFaceCache)
+  {
+    if(cacheItem.mRequestedPointSize == requestedPointSize &&
+       cacheItem.mFaceIndex == faceIndex &&
+       cacheItem.mPath == path)
+    {
+      fontId = cacheItem.mFontId + 1u;
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font found, id : %d\n", fontId);
+      return true;
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font not found\n");
+  return false;
+}
+
+bool FontClient::Plugin::FindValidatedFont(const FontDescription& fontDescription,
+                                           FontDescriptionId&     validatedFontId)
+{
+  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;
+
+  for(const auto& item : mValidatedFontCache)
+  {
+    if(!fontDescription.family.empty() &&
+       (fontDescription.family == item.fontDescription.family) &&
+       (fontDescription.width == item.fontDescription.width) &&
+       (fontDescription.weight == item.fontDescription.weight) &&
+       (fontDescription.slant == item.fontDescription.slant))
+    {
+      validatedFontId = item.index;
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font found, id : %d\n", validatedFontId);
+      return true;
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  validated font not found\n");
+  return false;
+}
+
+bool FontClient::Plugin::FindFallbackFontList(const FontDescription& fontDescription,
+                                              FontList*&             fontList,
+                                              CharacterSetList*&     characterSetList)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  FONT_LOG_DESCRIPTION(fontDescription, "");
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "  number of fallback font lists in the cache : %d\n", mFallbackCache.size());
+
+  fontList = nullptr;
+
+  for(const auto& item : mFallbackCache)
+  {
+    if(!fontDescription.family.empty() &&
+       (fontDescription.family == item.fontDescription.family) &&
+       (fontDescription.width == item.fontDescription.width) &&
+       (fontDescription.weight == item.fontDescription.weight) &&
+       (fontDescription.slant == item.fontDescription.slant))
+    {
+      fontList         = item.fallbackFonts;
+      characterSetList = item.characterSets;
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  fallback font list found.\n");
+      return true;
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  fallback font list not found.\n");
+  return false;
+}
+
+bool FontClient::Plugin::FindFont(FontDescriptionId validatedFontId,
+                                  PointSize26Dot6   requestedPointSize,
+                                  FontId&           fontId)
+{
+  DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "    validatedFontId  : %d\n", validatedFontId);
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  requestedPointSize : %d\n", requestedPointSize);
+
+  fontId = 0u;
+
+  for(const auto& item : mFontDescriptionSizeCache)
+  {
+    if((validatedFontId == item.validatedFontId) &&
+       (requestedPointSize == item.requestedPointSize))
+    {
+      fontId = item.fontId;
+
+      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font found, id : %d\n", fontId);
+      return true;
+    }
+  }
+
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font not found.\n");
+  return false;
+}
+
+bool FontClient::Plugin::FindBitmapFont(const FontFamily& bitmapFont, FontId& fontId) const
+{
+  fontId = 0u;
+
+  for(const auto& item : mBitmapFontCache)
+  {
+    if(bitmapFont == item.font.name)
+    {
+      fontId = item.id + 1u;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool FontClient::Plugin::IsScalable(const FontPath& path)
+{
+  bool isScalable = false;
+
+  FT_Face ftFace;
+  int     error = FT_New_Face(mFreeTypeLibrary,
+                          path.c_str(),
+                          0,
+                          &ftFace);
+  if(FT_Err_Ok != error)
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: %s\n", path.c_str());
+  }
+  else
+  {
+    isScalable = ftFace->face_flags & FT_FACE_FLAG_SCALABLE;
+  }
+
+  return isScalable;
+}
+
+bool FontClient::Plugin::IsScalable(const FontDescription& fontDescription)
+{
+  // Create a font pattern.
+  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  FcResult result = FcResultMatch;
+
+  // match the pattern
+  FcPattern* match      = FcFontMatch(nullptr /* use default configure */, fontFamilyPattern, &result); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
+  bool       isScalable = false;
+
+  if(match)
+  {
+    // Get the path to the font file name.
+    FontPath path;
+    GetFcString(match, FC_FILE, path);
+    isScalable = IsScalable(path);
+  }
+  else
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str());
+  }
+
+  // Destroys the created patterns.
+  FcPatternDestroy(match);
+  FcPatternDestroy(fontFamilyPattern);
+
+  return isScalable;
+}
+
+void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector<PointSize26Dot6>& sizes)
+{
+  // Empty the caller container
+  sizes.Clear();
+
+  FT_Face ftFace;
+  int     error = FT_New_Face(mFreeTypeLibrary,
+                          path.c_str(),
+                          0,
+                          &ftFace);
+  if(FT_Err_Ok != error)
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font path : [%s]\n", path.c_str());
+  }
+
+  // Fetch the number of fixed sizes available
+  if(ftFace->num_fixed_sizes && ftFace->available_sizes)
+  {
+    for(int i = 0; i < ftFace->num_fixed_sizes; ++i)
+    {
+      sizes.PushBack(ftFace->available_sizes[i].size);
+    }
+  }
+}
+
+void FontClient::Plugin::GetFixedSizes(const FontDescription&   fontDescription,
+                                       Vector<PointSize26Dot6>& sizes)
+{
+  // Create a font pattern.
+  FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  FcResult result = FcResultMatch;
+
+  // match the pattern
+  FcPattern* match = FcFontMatch(nullptr /* use default configure */, fontFamilyPattern, &result); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  if(match)
+  {
+    // Get the path to the font file name.
+    FontPath path;
+    GetFcString(match, FC_FILE, path);
+    GetFixedSizes(path, sizes);
+  }
+  else
+  {
+    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str());
+  }
+
+  // Destroys the created patterns.
+  FcPatternDestroy(match);
+  FcPatternDestroy(fontFamilyPattern);
+}
+
+bool FontClient::Plugin::HasItalicStyle(FontId fontId) const
+{
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
+  {
+    return fontCacheItem->HasItalicStyle();
+  }
+  return false;
+}
+
+void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path)
+{
+  FontDescription description;
+  description.path   = path;
+  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)
+  {
+    description.slant = FontSlant::ITALIC;
+  }
+  if(ftFace->style_flags & FT_STYLE_FLAG_BOLD)
+  {
+    description.weight = FontWeight::BOLD;
+  }
+
+  FontDescriptionId validatedFontId = 0u;
+  if(!FindValidatedFont(description,
+                        validatedFontId))
+  {
+    FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
+
+    FcResult   result = FcResultMatch;
+    FcPattern* match  = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
+
+    FcCharSet* characterSet = nullptr;
+    FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
+
+    const FontId fontFaceId                  = id - 1u;
+    mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(characterSet); // Increases the reference counter.
+
+    // Destroys the created patterns.
+    FcPatternDestroy(match);
+    FcPatternDestroy(pattern);
+
+    // Add the path to the cache.
+    description.type = FontDescription::FACE_FONT;
+    mFontDescriptionCache.push_back(description);
+
+    // Set the index to the vector of paths to font file names.
+    validatedFontId = 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)));
+
+    // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
+    mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
+                                                                     requestedPointSize,
+                                                                     fontFaceId));
+  }
+}
+
+void FontClient::Plugin::ClearFallbackCache(std::vector<FallbackCacheItem>& fallbackCache)
+{
+  for(auto& item : fallbackCache)
+  {
+    if(nullptr != item.fallbackFonts)
+    {
+      delete item.fallbackFonts;
+    }
+
+    if(nullptr != item.characterSets)
+    {
+      // Free the resources allocated by the FcCharSet objects in the 'characterSets' vector.
+      DestroyCharacterSets(*item.characterSets);
+      delete item.characterSets;
+    }
+  }
+}
+
+void FontClient::Plugin::ClearCharacterSetFromFontFaceCache()
+{
+  for(auto& item : mFontFaceCache)
+  {
+    FcCharSetDestroy(item.mCharacterSet);
+    item.mCharacterSet = nullptr;
+  }
+}
+
+} // namespace Dali::TextAbstraction::Internal
 #include <dali/devel-api/text-abstraction/font-metrics.h>
 #include <dali/devel-api/text-abstraction/glyph-info.h>
 #include <dali/internal/text/text-abstraction/font-client-impl.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-face-cache-item.h>
+#include <dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h>
 
 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
 #include <third-party/glyphy/vector-font-cache.h>
@@ -35,7 +39,6 @@ class VectorFontCache;
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
-#include FT_OUTLINE_H
 #include FT_STROKER_H
 #include FT_SYNTHESIS_H
 
@@ -56,11 +59,6 @@ namespace Internal
 typedef uint32_t FontDescriptionId;
 
 /**
- * @brief Type used for indices addressing the vector with pixel buffers.
- */
-typedef uint32_t PixelBufferId;
-
-/**
  * @brief Vector of character sets.
  */
 typedef Vector<_FcCharSet*> CharacterSetList;
@@ -116,42 +114,6 @@ struct FontClient::Plugin
     FontId            fontId;             ///< The font identifier.
   };
 
-  /**
-   * @brief Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'.
-   */
-  struct FontFaceCacheItem
-  {
-    FontFaceCacheItem(FT_Face            ftFace,
-                      const FontPath&    path,
-                      PointSize26Dot6    requestedPointSize,
-                      FaceIndex          face,
-                      const FontMetrics& metrics);
-
-    FontFaceCacheItem(FT_Face            ftFace,
-                      const FontPath&    path,
-                      PointSize26Dot6    requestedPointSize,
-                      FaceIndex          face,
-                      const FontMetrics& metrics,
-                      int                fixedSizeIndex,
-                      float              fixedWidth,
-                      float              fixedHeight,
-                      bool               hasColorTables);
-
-    FT_Face         mFreeTypeFace;          ///< The FreeType face.
-    FontPath        mPath;                  ///< The path to the font file name.
-    PointSize26Dot6 mRequestedPointSize;    ///< The font point size.
-    FaceIndex       mFaceIndex;             ///< The face index.
-    FontMetrics     mMetrics;               ///< The font metrics.
-    _FcCharSet*     mCharacterSet;          ///< Pointer with the range of characters.
-    int             mFixedSizeIndex;        ///< Index to the fixed size table for the requested size.
-    float           mFixedWidthPixels;      ///< The height in pixels (fixed size bitmaps only)
-    float           mFixedHeightPixels;     ///< The height in pixels (fixed size bitmaps only)
-    unsigned int    mVectorFontId;          ///< The ID of the equivalent vector-based font
-    FontId          mFontId;                ///< Index to the vector with the cache of font's ids.
-    bool            mIsFixedSizeBitmap : 1; ///< Whether the font has fixed size bitmaps.
-    bool            mHasColorTables : 1;    ///< Whether the font has color tables.
-  };
-
   struct EllipsisItem
   {
     PointSize26Dot6 requestedPointSize;
@@ -159,35 +121,6 @@ struct FontClient::Plugin
   };
 
   /**
-   * @brief Caches pixel buffers.
-   */
-  struct PixelBufferCacheItem
-  {
-    Devel::PixelBuffer pixelBuffer; ///< The pixel buffer loaded from the url.
-    std::string        url;         ///< The url.
-  };
-
-  /**
-   * @brief Caches embedded items.
-   */
-  struct EmbeddedItem
-  {
-    PixelBufferId pixelBufferId; ///< Index to the vector of pixel buffers
-    unsigned int  width;         ///< The desired width.
-    unsigned int  height;        ///< The desired height.
-  };
-
-  /**
-   * @brief Stores a bitmap font and its pixel buffers per glyph.
-   */
-  struct BitmapFontCacheItem
-  {
-    BitmapFont                      font;         ///< The bitmap font.
-    std::vector<Devel::PixelBuffer> pixelBuffers; ///< The pixel buffers of the glyphs.
-    FontId                          id;           ///< Index to the vector with the cache of font's ids.
-  };
-
-  /**
    * Constructor.
    *
    * Initializes the FreeType library.
@@ -256,6 +189,13 @@ struct FontClient::Plugin
   bool IsCharacterSupportedByFont(FontId fontId, Character character);
 
   /**
+   * Get the cached font item for the given font
+   * @param[in] id The font id to search for
+   * @return the matching cached font item
+   */
+  const FontCacheItemInterface* GetCachedFontItem(FontId id) const;
+
+  /**
    * @brief Finds within the @p fontList a font which support the @p carcode.
    *
    * @param[in] fontList A list of font paths, family, width, weight and slant.
@@ -461,17 +401,6 @@ private:
   bool MatchFontDescriptionToPattern(_FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, _FcCharSet** characterSet);
 
   /**
-   * @brief Creates a font family pattern used to match fonts.
-   *
-   * @note Need to call FcPatternDestroy to free the resources.
-   *
-   * @param[in] fontDescription The font to cache.
-   *
-   * @return The pattern.
-   */
-  _FcPattern* CreateFontFamilyPattern(const FontDescription& fontDescription) const;
-
-  /**
    * @brief Retrieves the fonts present in the platform.
    *
    * @note Need to call FcFontSetDestroy to free the allocated resources.
@@ -518,25 +447,6 @@ private:
                     bool            cacheDescription);
 
   /**
-   * @brief Copy the color bitmap given in @p srcBuffer to @p data.
-   *
-   * @param[out] data The bitmap data.
-   * @param[in] srcWidth The width of the bitmap.
-   * @param[in] srcHeight The height of the bitmap.
-   * @param[in] srcBuffer The buffer of the bitmap.
-   */
-  void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer);
-
-  /**
-   * @brief Copy the FreeType bitmap to the given buffer.
-   *
-   * @param[out] data The bitmap data.
-   * @param[in] srcBitmap The FreeType bitmap.
-   * @param[in] isShearRequired Whether the bitmap needs a shear transform (for software italics).
-   */
-  void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap, bool isShearRequired);
-
-  /**
    * @brief Finds in the cache if there is a triplet with the path to the font file name, the font point size and the face index.
    * If there is one , if writes the font identifier in the param @p fontId.
    *
@@ -627,17 +537,6 @@ private:
   void CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path);
 
   /**
-   * @brief Creates a character set from a given font's @p description.
-   *
-   * @note Need to call FcCharSetDestroy to free the resources.
-   *
-   * @param[in] description The font's description.
-   *
-   * @return A character set.
-   */
-  _FcCharSet* CreateCharacterSetFromDescription(const FontDescription& description);
-
-  /**
    * @brief Free the resources allocated in the fallback cache.
    *
    * @param[in] fallbackCache The fallback cache.
@@ -650,10 +549,8 @@ private:
   void ClearCharacterSetFromFontFaceCache();
 
 private:
-  // Declared private and left undefined to avoid copies.
-  Plugin(const Plugin&);
-  // Declared private and left undefined to avoid copies.
-  Plugin& operator=(const Plugin&);
+  Plugin(const Plugin&) = delete;
+  Plugin& operator=(const Plugin&) = delete;
 
 private:
   FT_Library mFreeTypeLibrary; ///< A handle to a FreeType library instance.
diff --git a/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp b/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp
new file mode 100644 (file)
index 0000000..3f9743f
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+
+#include <dali/integration-api/debug.h>
+#include <dali/internal/imaging/common/image-operations.h>
+
+#include <memory>
+
+#if defined(DEBUG_ENABLED)
+extern Dali::Integration::Log::Filter* gFontClientLogFilter;
+#endif
+
+namespace Dali::TextAbstraction::Internal
+{
+namespace
+{
+// 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
+// SEMI_CONDENSED  87
+// NORMAL         100
+// SEMI_EXPANDED  113
+// EXPANDED       125
+// EXTRA_EXPANDED 150
+// ULTRA_EXPANDED 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
+// DEMI_LIGHT, SEMI_LIGHT     55
+// BOOK                       75
+// NORMAL, REGULAR            80
+// MEDIUM                    100
+// DEMI_BOLD, SEMI_BOLD      180
+// BOLD                      200
+// ULTRA_BOLD, EXTRA_BOLD    205
+// BLACK, HEAVY, EXTRA_BLACK 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);
+
+// 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
+
+/**
+ * @brief Returns the FontWidth's enum index for the given width value.
+ *
+ * @param[in] width The width value.
+ *
+ * @return The FontWidth's enum index.
+ */
+const FontWidth::Type IntToWidthType(int width)
+{
+  return static_cast<FontWidth::Type>(ValueToIndex(width, FONT_WIDTH_TYPE_TO_INT, NUM_FONT_WIDTH_TYPE - 1u));
+}
+
+/**
+ * @brief Returns the FontWeight's enum index for the given weight value.
+ *
+ * @param[in] weight The weight value.
+ *
+ * @return The FontWeight's enum index.
+ */
+const FontWeight::Type IntToWeightType(int weight)
+{
+  return static_cast<FontWeight::Type>(ValueToIndex(weight, FONT_WEIGHT_TYPE_TO_INT, NUM_FONT_WEIGHT_TYPE - 1u));
+}
+
+/**
+ * @brief Returns the FontSlant's enum index for the given slant value.
+ *
+ * @param[in] slant The slant value.
+ *
+ * @return The FontSlant's enum index.
+ */
+const FontSlant::Type IntToSlantType(int slant)
+{
+  return static_cast<FontSlant::Type>(ValueToIndex(slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u));
+}
+
+const int DEFAULT_FONT_WIDTH(100);
+const int DEFAULT_FONT_WEIGHT(80);
+const int DEFAULT_FONT_SLANT(0);
+
+const FontWidth::Type DefaultFontWidth()
+{
+  return IntToWidthType(DEFAULT_FONT_WIDTH);
+}
+const FontWeight::Type DefaultFontWeight()
+{
+  return IntToWeightType(DEFAULT_FONT_WEIGHT);
+}
+const FontSlant::Type DefaultFontSlant()
+{
+  return IntToSlantType(DEFAULT_FONT_SLANT);
+}
+
+/**
+ * @brief Copy the color bitmap given in @p srcBuffer to @p data.
+ *
+ * @param[out] data The bitmap data.
+ * @param[in] srcWidth The width of the bitmap.
+ * @param[in] srcHeight The height of the bitmap.
+ * @param[in] srcBuffer The buffer of the bitmap.
+ */
+void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer)
+{
+  // Set the input dimensions.
+  const ImageDimensions inputDimensions(srcWidth, srcHeight);
+
+  // 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) ? srcWidth : data.width;
+  data.height = (data.height == 0) ? srcHeight : 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, srcBuffer, bufferSize);
+  }
+  else
+  {
+    Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
+                                                inputDimensions,
+                                                data.buffer,
+                                                desiredDimensions);
+  }
+}
+
+/**
+ * @brief Copy the FreeType bitmap to the given buffer.
+ *
+ * @param[out] data The bitmap data.
+ * @param[in] srcBitmap The FreeType bitmap.
+ * @param[in] isShearRequired Whether the bitmap needs a shear transform (for software italics).
+ */
+void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap, bool isShearRequired)
+{
+  if(srcBitmap.width * srcBitmap.rows > 0)
+  {
+    switch(srcBitmap.pixel_mode)
+    {
+      case FT_PIXEL_MODE_GRAY:
+      {
+        if(srcBitmap.pitch == static_cast<int>(srcBitmap.width))
+        {
+          uint8_t*     pixelsIn = srcBitmap.buffer;
+          unsigned int width    = srcBitmap.width;
+          unsigned     height   = srcBitmap.rows;
+
+          std::unique_ptr<uint8_t, void (*)(void*)> pixelsOutPtr(nullptr, free);
+
+          if(isShearRequired)
+          {
+            /**
+             * Glyphs' bitmaps with no slant retrieved from FreeType:
+             * __________     ____
+             * |XXXXXXXX|     |XX|
+             * |   XX   |     |XX|
+             * |   XX   |     |XX|
+             * |   XX   |     |XX|
+             * |   XX   |     |XX|
+             * |   XX   |     |XX|
+             * ----------     ----
+             *
+             * Expected glyphs' bitmaps with italic slant:
+             * ____________   ______
+             * |  XXXXXXXX|   |  XX|
+             * |     XX   |   |  XX|
+             * |    XX    |   | XX |
+             * |    XX    |   | XX |
+             * |   XX     |   |XX  |
+             * |   XX     |   |XX  |
+             * ------------   ------
+             *
+             * Glyphs' bitmaps with software italic slant retrieved from FreeType:
+             * __________     ______
+             * |XXXXXXXX|     |  XX|
+             * |   XX   |     |  XX|
+             * |  XX    |     | XX |
+             * |  XX    |     | XX |
+             * | XX     |     |XX  |
+             * | XX     |     |XX  |
+             * ----------     ------
+             *
+             * This difference in some bitmaps' width causes an overlap of some glyphs. This is the reason why a shear operation is done here instead of relying on the experimental FT_GlyphSlot_Oblique() implementation.
+             */
+            unsigned int widthOut  = 0u;
+            unsigned int heightOut = 0u;
+            uint8_t*     pixelsOut = nullptr;
+
+            Dali::Internal::Platform::HorizontalShear(pixelsIn,
+                                                      width,
+                                                      height,
+                                                      1u,
+                                                      -TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE,
+                                                      pixelsOut,
+                                                      widthOut,
+                                                      heightOut);
+
+            width    = widthOut;
+            height   = heightOut;
+            pixelsIn = pixelsOut;
+            pixelsOutPtr.reset(pixelsOut);
+          }
+
+          const unsigned int bufferSize = width * height;
+          data.buffer                   = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
+          data.width                    = width;
+          data.height                   = height;
+          data.format                   = Pixel::L8; // Sets the pixel format.
+          memcpy(data.buffer, pixelsIn, bufferSize);
+        }
+        break;
+      }
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+      case FT_PIXEL_MODE_BGRA:
+      {
+        if(srcBitmap.pitch == static_cast<int>(srcBitmap.width << 2u))
+        {
+          ConvertBitmap(data, srcBitmap.width, srcBitmap.rows, srcBitmap.buffer);
+
+          // Sets the pixel format.
+          data.format = Pixel::BGRA8888;
+        }
+        break;
+      }
+#endif
+      default:
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::ConvertBitmap. FontClient Unable to create Bitmap of this PixelType\n");
+        break;
+      }
+    }
+  }
+}
+
+FcPattern* CreateFontFamilyPattern(const FontDescription& fontDescription)
+{
+  // 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(); // FcPatternCreate creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  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()));
+
+  // 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);
+
+  // modify the config, with the mFontFamilyPatterm
+  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
+  FcDefaultSubstitute(fontFamilyPattern);
+
+  return fontFamilyPattern;
+}
+
+FcCharSet* CreateCharacterSetFromDescription(const FontDescription& description)
+{
+  FcCharSet* characterSet = nullptr;
+
+  FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
+
+  if(nullptr != pattern)
+  {
+    FcResult   result = FcResultMatch;
+    FcPattern* match  = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
+
+    FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
+
+    // Destroys the created patterns.
+    FcPatternDestroy(match);
+    FcPatternDestroy(pattern);
+  }
+
+  return characterSet;
+}
+
+} // namespace Dali::TextAbstraction::Internal
diff --git a/dali/internal/text/text-abstraction/plugin/font-client-utils.h b/dali/internal/text/text-abstraction/plugin/font-client-utils.h
new file mode 100644 (file)
index 0000000..f329193
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef DALI_TEST_ABSTRACTION_INTERNAL_FONT_CLIENT_UTILS_H
+#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_CLIENT_UTILS_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+// EXTERNAL INCLUDES
+#include <fontconfig/fontconfig.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_OUTLINE_H
+#include FT_STROKER_H
+#include FT_SYNTHESIS_H
+
+namespace Dali::TextAbstraction::Internal
+{
+void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data,
+                   unsigned int                                  srcWidth,
+                   unsigned int                                  srcHeight,
+                   const unsigned char* const                    srcBuffer);
+
+void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data,
+                   FT_Bitmap                                     srcBitmap,
+                   bool                                          isShearRequired);
+
+/**
+ * @brief Creates a font family pattern used to match fonts.
+ *
+ * @note Need to call FcPatternDestroy to free the resources.
+ *
+ * @param[in] fontDescription The font to cache.
+ *
+ * @return The pattern.
+ */
+FcPattern* CreateFontFamilyPattern(const FontDescription& fontDescription);
+
+/**
+ * @brief Creates a character set from a given font's @p description.
+ *
+ * @note Need to call FcCharSetDestroy to free the resources.
+ *
+ * @param[in] description The font's description.
+ *
+ * @return A character set.
+ */
+FcCharSet* CreateCharacterSetFromDescription(const FontDescription& description);
+
+constexpr int ValueToIndex(int value, const int* const table, unsigned int maxIndex)
+{
+  if(nullptr == table)
+  {
+    // Return an invalid index if there is no table.
+    return -1;
+  }
+
+  if(value <= table[0])
+  {
+    return 0;
+  }
+
+  if(value >= table[maxIndex])
+  {
+    return maxIndex;
+  }
+
+  for(unsigned int index = 0u; index < maxIndex; ++index)
+  {
+    const int          v1        = table[index];
+    const unsigned int indexPlus = index + 1u;
+    const int          v2        = table[indexPlus];
+    if((v1 < value) && (value <= v2))
+    {
+      const int result = ((v1 > 0) && ((value - v1) < (v2 - value))) ? index : indexPlus;
+      return result;
+    }
+  }
+  return 0;
+}
+
+/**
+ * @brief Returns the FontWidth's enum index for the given width value.
+ *
+ * @param[in] width The width value.
+ *
+ * @return The FontWidth's enum index.
+ */
+const FontWidth::Type IntToWidthType(int width);
+
+/**
+ * @brief Returns the FontWeight's enum index for the given weight value.
+ *
+ * @param[in] weight The weight value.
+ *
+ * @return The FontWeight's enum index.
+ */
+const FontWeight::Type IntToWeightType(int weight);
+
+/**
+ * @brief Returns the FontSlant's enum index for the given slant value.
+ *
+ * @param[in] slant The slant value.
+ *
+ * @return The FontSlant's enum index.
+ */
+const FontSlant::Type IntToSlantType(int slant);
+
+const FontWidth::Type  DefaultFontWidth();
+const FontWeight::Type DefaultFontWeight();
+const FontSlant::Type  DefaultFontSlant();
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif // DALI_TEST_ABSTRACTION_INTERNAL_FONT_CLIENT_UTILS_H
diff --git a/dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp
new file mode 100644 (file)
index 0000000..5608b03
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/integration-api/debug.h>
+#include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+#include <dali/internal/text/text-abstraction/plugin/font-face-cache-item.h>
+
+#if defined(DEBUG_ENABLED)
+extern Dali::Integration::Log::Filter* gFontClientLogFilter;
+#endif
+
+namespace Dali::TextAbstraction::Internal
+{
+const float FROM_266        = 1.0f / 64.0f;
+const float POINTS_PER_INCH = 72.f;
+
+FontFaceCacheItem::FontFaceCacheItem(FT_Library&        freeTypeLibrary,
+                                     FT_Face            ftFace,
+                                     const FontPath&    path,
+                                     PointSize26Dot6    requestedPointSize,
+                                     FaceIndex          face,
+                                     const FontMetrics& metrics)
+: mFreeTypeLibrary(freeTypeLibrary),
+  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)
+{
+}
+
+FontFaceCacheItem::FontFaceCacheItem(FT_Library&        freeTypeLibrary,
+                                     FT_Face            ftFace,
+                                     const FontPath&    path,
+                                     PointSize26Dot6    requestedPointSize,
+                                     FaceIndex          face,
+                                     const FontMetrics& metrics,
+                                     int                fixedSizeIndex,
+                                     float              fixedWidth,
+                                     float              fixedHeight,
+                                     bool               hasColorTables)
+: mFreeTypeLibrary(freeTypeLibrary),
+  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)
+{
+}
+
+void FontFaceCacheItem::GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const
+{
+  metrics = mMetrics;
+
+  // Adjust the metrics if the fixed-size font should be down-scaled
+  if(mIsFixedSizeBitmap)
+  {
+    const float desiredFixedSize = static_cast<float>(mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * dpiVertical;
+
+    if(desiredFixedSize > 0.f)
+    {
+      const float scaleFactor = desiredFixedSize / 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;
+    }
+  }
+}
+
+bool FontFaceCacheItem::GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const
+{
+  bool success(true);
+
+  FT_Face ftFace = mFreeTypeFace;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+  // Check to see if we should be loading a Fixed Size bitmap?
+  if(mIsFixedSizeBitmap)
+  {
+    FT_Select_Size(ftFace, 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    = mFixedWidthPixels;
+      glyph.height   = mFixedHeightPixels;
+      glyph.advance  = mFixedWidthPixels;
+      glyph.xBearing = 0.0f;
+      glyph.yBearing = mFixedHeightPixels;
+
+      // Adjust the metrics if the fixed-size font should be down-scaled
+      const float desiredFixedSize = static_cast<float>(mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * dpiVertical;
+
+      if(desiredFixedSize > 0.f)
+      {
+        const float scaleFactor = desiredFixedSize / 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;
+    }
+  }
+  return success;
+}
+
+/**
+ * @brief Create a bitmap representation of a glyph from a face font
+ *
+ * @param[in]  glyphIndex        The index of a glyph within the specified font.
+ * @param[in]  isItalicRequired  Whether the glyph requires italic style.
+ * @param[in]  isBoldRequired    Whether the glyph requires bold style.
+ * @param[out] data              The bitmap data.
+ * @param[in]  outlineWidth      The width of the glyph outline in pixels.
+ */
+void FontFaceCacheItem::CreateBitmap(
+  GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
+{
+  FT_Face  ftFace = mFreeTypeFace;
+  FT_Error error;
+  // For the software italics.
+  bool isShearRequired = false;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+  // Check to see if this is fixed size bitmap
+  if(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 = 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);
+  }
+}
+
+bool FontFaceCacheItem::IsColorGlyph(GlyphIndex glyphIndex) const
+{
+  FT_Error error = -1;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+  // Check to see if this is fixed size bitmap
+  if(mHasColorTables)
+  {
+    error = FT_Load_Glyph(mFreeTypeFace, glyphIndex, FT_LOAD_COLOR);
+  }
+#endif
+  return FT_Err_Ok == error;
+}
+
+/**
+ * Check if the character is supported by this font
+ * @param[in] character The character to test
+ */
+bool FontFaceCacheItem::IsCharacterSupported(Character character)
+{
+  if(nullptr == mCharacterSet)
+  {
+    // Create again the character set.
+    // It can be null if the ResetSystemDefaults() method has been called.
+
+    FontDescription description;
+    description.path   = mPath;
+    description.family = std::move(FontFamily(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(mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC)
+    {
+      description.slant = FontSlant::ITALIC;
+    }
+    if(mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD)
+    {
+      description.weight = FontWeight::BOLD;
+    }
+
+    mCharacterSet = FcCharSetCopy(CreateCharacterSetFromDescription(description));
+  }
+
+  return FcCharSetHasChar(mCharacterSet, character);
+}
+
+GlyphIndex FontFaceCacheItem::GetGlyphIndex(Character character) const
+{
+  return FT_Get_Char_Index(mFreeTypeFace, character);
+}
+
+} // namespace Dali::TextAbstraction::Internal
diff --git a/dali/internal/text/text-abstraction/plugin/font-face-cache-item.h b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.h
new file mode 100644 (file)
index 0000000..4a13d32
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H
+#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// INTERNAL INCLUDES
+
+#include <dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h>
+
+// EXTERNAL INCLUDES
+#include <fontconfig/fontconfig.h>
+
+// EXTERNAL INCLUDES
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_OUTLINE_H
+#include FT_STROKER_H
+#include FT_SYNTHESIS_H
+
+namespace Dali::TextAbstraction::Internal
+{
+/**
+ * @brief Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'.
+ */
+struct FontFaceCacheItem : public FontCacheItemInterface
+{
+  FontFaceCacheItem(FT_Library&        freeTypeLibrary,
+                    FT_Face            ftFace,
+                    const FontPath&    path,
+                    PointSize26Dot6    requestedPointSize,
+                    FaceIndex          face,
+                    const FontMetrics& metrics);
+
+  FontFaceCacheItem(FT_Library&        freeTypeLibrary,
+                    FT_Face            ftFace,
+                    const FontPath&    path,
+                    PointSize26Dot6    requestedPointSize,
+                    FaceIndex          face,
+                    const FontMetrics& metrics,
+                    int                fixedSizeIndex,
+                    float              fixedWidth,
+                    float              fixedHeight,
+                    bool               hasColorTables);
+
+  /**
+   * @copydoc FontCacheItemInterface::GetFontMetrics()
+   */
+  void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::GetGlyphMetrics()
+   */
+  bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::CreateBitmap()
+   */
+  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::IsColorGlyph()
+   */
+  bool IsColorGlyph(GlyphIndex glyphIndex) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::IsCharacterSupported()
+   */
+  bool IsCharacterSupported(Character character) override;
+
+  /**
+   * @copydoc FontCacheItemInterface::GetPointSize()
+   */
+  PointSize26Dot6 GetPointSize() const override
+  {
+    return mRequestedPointSize;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::GetGlyphIndex()
+   */
+  GlyphIndex GetGlyphIndex(Character character) const override;
+
+  /**
+   * @copydoc FontCacheItemInterface::GetTypeface()
+   */
+  FT_Face GetTypeface() const override
+  {
+    return mFreeTypeFace;
+  }
+
+  /**
+   * @copydoc FontCacheItemInterface::HasItalicStyle()
+   */
+  bool HasItalicStyle() const override
+  {
+    return (0u != (mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC));
+  }
+
+  FT_Library&     mFreeTypeLibrary;       ///< A handle to a FreeType library instance.
+  FT_Face         mFreeTypeFace;          ///< The FreeType face.
+  FontPath        mPath;                  ///< The path to the font file name.
+  PointSize26Dot6 mRequestedPointSize;    ///< The font point size.
+  FaceIndex       mFaceIndex;             ///< The face index.
+  FontMetrics     mMetrics;               ///< The font metrics.
+  _FcCharSet*     mCharacterSet;          ///< Pointer with the range of characters.
+  int             mFixedSizeIndex;        ///< Index to the fixed size table for the requested size.
+  float           mFixedWidthPixels;      ///< The height in pixels (fixed size bitmaps only)
+  float           mFixedHeightPixels;     ///< The height in pixels (fixed size bitmaps only)
+  unsigned int    mVectorFontId;          ///< The ID of the equivalent vector-based font
+  FontId          mFontId;                ///< Index to the vector with the cache of font's ids.
+  bool            mIsFixedSizeBitmap : 1; ///< Whether the font has fixed size bitmaps.
+  bool            mHasColorTables : 1;    ///< Whether the font has color tables.
+};
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif //DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H
diff --git a/dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h b/dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h
new file mode 100644 (file)
index 0000000..28086b6
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H
+#define DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Dali::TextAbstraction::Internal
+{
+/**
+ * @brief Type used for indices addressing the vector with pixel buffers.
+ */
+typedef uint32_t PixelBufferId;
+
+/**
+ * @brief Caches pixel buffers.
+ */
+struct PixelBufferCacheItem
+{
+  Devel::PixelBuffer pixelBuffer; ///< The pixel buffer loaded from the url.
+  std::string        url;         ///< The url.
+};
+
+} // namespace Dali::TextAbstraction::Internal
+
+#endif //DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H
index ba68d93..b4b44b2 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const unsigned int ADAPTOR_MAJOR_VERSION = 2;
 const unsigned int ADAPTOR_MINOR_VERSION = 0;
-const unsigned int ADAPTOR_MICRO_VERSION = 50;
+const unsigned int ADAPTOR_MICRO_VERSION = 51;
 const char* const  ADAPTOR_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 236a88c..51d32c8 100644 (file)
@@ -17,7 +17,7 @@
 
 Name:       dali2-adaptor
 Summary:    The DALi Tizen Adaptor
-Version:    2.0.50
+Version:    2.0.51
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT