Refactored font-client-plugin-impl 18/265718/3
authorDavid Steele <david.steele@samsung.com>
Wed, 27 Oct 2021 12:17:54 +0000 (13:17 +0100)
committerDavid Steele <david.steele@samsung.com>
Fri, 29 Oct 2021 08:33:56 +0000 (09:33 +0100)
Refactored cached item structs into separate classes
with own methods.

FontFaceCacheItem   <|--- FontCacheItemInterface
BitmapFontCacheItem <|-+

This simplifies a lot of the hidden type lookup within the plugin
code. There is some scope for integrating EmbeddedItem into this
interface as well.

Change-Id: I7370355ff307f9aef7b19e2bbb6ed2225e7e92b6
Signed-off-by: David Steele <david.steele@samsung.com>
27 files changed:
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
dali/devel-api/text-abstraction/font-client.h
dali/internal/text/file.list
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
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h
dali/internal/text/text-abstraction/plugin/font-client-utils.cpp
dali/internal/text/text-abstraction/plugin/font-client-utils.h
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]

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 0a8e771..b6c2ec9 100644 (file)
@@ -60,6 +60,7 @@ ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror )
 ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} )
 
 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}\" )
 
 
index ce9cfab..208deb1 100644 (file)
@@ -19,6 +19,7 @@
 
 #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/plugin/font-client-utils.h>
 #include <stdint.h>
@@ -400,68 +401,499 @@ std::ostream& operator<<(std::ostream& o, const FontDescription& description)
   return o;
 }
 
-int UtcDaliFontClientFindFallbackFont(void)
+int UtcDaliFontClientGetDefaultPlatformFontDescription(void)
 {
   TestApplication application;
-  tet_infoline(" UtcDaliFontClientFindFallbackFont ");
+  tet_infoline(" UtcDaliFontClientGetDefaultPlatformFontDescription");
 
   FontClient fontClient;
   fontClient = FontClient::Get();
 
-  FontList fontList;
-  fontClient.GetSystemFonts(fontList);
-  DALI_TEST_CHECK(fontList.size() > 0);
-
-  const std::string emptyString;
-  FontDescription   fontDescription;
-  fontDescription.width  = FontWidth::NORMAL;
-  fontDescription.weight = FontWeight::NORMAL;
-  fontDescription.slant  = FontSlant::NORMAL;
-  fontDescription.type   = FontDescription::BITMAP_FONT;
+  FontDescription fontDescription;
+  fontClient.GetDefaultPlatformFontDescription(fontDescription);
 
   std::ostringstream oss;
   oss << fontDescription;
-  tet_printf("Looking for: %s", oss.str().c_str());
+  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);
-  DALI_TEST_CHECK(fontId != 0);
 
-  fontClient.GetDescription(fontId, fontDescription);
-  oss.clear();
-  oss << fontDescription;
-  tet_printf("Found: %d: %s", fontId, oss.str().c_str());
-
-  bool color = fontClient.IsColorGlyph(fontId, fontClient.GetGlyphIndex(fontId, 'A'));
-  DALI_TEST_CHECK(color || 1);
+  bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A');
+  DALI_TEST_EQUALS(supported, true, TEST_LOCATION);
   END_TEST;
 }
 
-int UtcDaliFontClientGetDefaultPlatformFontDescription(void)
+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(" UtcDaliFontClientGetDefaultPlatformFontDescription");
+  tet_infoline(" UtcDaliFontClientTestBitmapFont");
 
   FontClient fontClient;
   fontClient = FontClient::Get();
 
-  FontDescription fontDescription;
-  fontClient.GetDefaultPlatformFontDescription(fontDescription);
+  auto bitmapFontId = SetupBitmapFont();
 
+  FontDescription fontDescription;
+  fontClient.GetDescription(bitmapFontId, fontDescription);
   std::ostringstream oss;
   oss << fontDescription;
-  tet_printf("%s", oss.str().c_str());
+  tet_printf("Found: %d: %s", bitmapFontId, oss.str().c_str());
 
-  DALI_TEST_CHECK(fontDescription.path.empty() == false);
+  bool color = fontClient.IsColorGlyph(bitmapFontId, fontClient.GetGlyphIndex(bitmapFontId, '2'));
+  DALI_TEST_EQUALS(color, true, TEST_LOCATION);
 
-  FontId fontId = fontClient.FindFallbackFont('A',
-                                              fontDescription,
-                                              FontClient::DEFAULT_POINT_SIZE,
-                                              true);
+  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);
 
-  bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A');
-  DALI_TEST_EQUALS(supported, true, TEST_LOCATION);
   END_TEST;
 }
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 fd617e2..7f00ae6 100644 (file)
@@ -8,6 +8,9 @@ SET( adaptor_text_common_src_files
     ${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/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
index a7e025c..e438a53 100644 (file)
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/imaging/common/image-operations.h>
+#include <dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h>
+#include <dali/internal/text/text-abstraction/plugin/embedded-item.h>
 #include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
+#include <dali/internal/text/text-abstraction/plugin/font-face-cache-item.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/vector-wrapper.h>
 
@@ -88,11 +91,7 @@ const uint32_t ELLIPSIS_CHARACTER = 0x2026;
 using Dali::Vector;
 using namespace std;
 
-namespace Dali
-{
-namespace TextAbstraction
-{
-namespace Internal
+namespace Dali::TextAbstraction::Internal
 {
 /**
  * @brief Free the resources allocated by the FcCharSet objects.
@@ -258,52 +257,6 @@ FontClient::Plugin::FontDescriptionSizeCacheItem::FontDescriptionSizeCacheItem(F
 {
 }
 
-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),
@@ -634,37 +587,16 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id)
 {
   DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  font id : %d\n", id);
-  const FontId index = id - 1u;
 
-  if((id > 0u) &&
-     (index < mFontIdCache.Count()))
+  PointSize26Dot6               pointSize     = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(id);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  point size : %d\n", (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize);
-        return (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
-  {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid font ID %d\n", id);
+    pointSize = fontCacheItem->GetPointSize();
   }
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  point size : %d\n", pointSize);
 
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  default point size : %d\n", TextAbstraction::FontClient::DEFAULT_POINT_SIZE);
-  return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+  return pointSize;
 }
 
 bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character)
@@ -673,77 +605,40 @@ bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character cha
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "    font id : %d\n", fontId);
   DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  character : %p\n", character);
 
-  if((fontId < 1u) || (fontId > mFontIdCache.Count()))
+  bool isSupported   = false;
+  auto fontCacheItem = const_cast<FontCacheItemInterface*>(GetCachedFontItem(fontId));
+  if(fontCacheItem != nullptr)
   {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid font id. Number of items in the cache: %d\n", mFontIdCache.Count());
-    return false;
+    isSupported = fontCacheItem->IsCharacterSupported(character); // May cache
   }
 
-  --fontId;
-
-  bool isSupported = false;
-
-  const FontIdCacheItem& fontIdCacheItem = mFontIdCache[fontId];
+  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false"));
+  return isSupported;
+}
 
-  switch(fontIdCacheItem.type)
+const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId id) const
+{
+  const FontId index = id - 1u;
+  if((id > 0u) && (index < mFontIdCache.Count()))
   {
-    case FontDescription::FACE_FONT:
+    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+    switch(fontIdCacheItem.type)
     {
-      if(fontIdCacheItem.id < mFontFaceCache.size())
+      case FontDescription::FACE_FONT:
       {
-        FontFaceCacheItem& cacheItem = mFontFaceCache[fontIdCacheItem.id];
-
-        if(nullptr == cacheItem.mCharacterSet)
-        {
-          // Create again the character set.
-          // It can be null if the ResetSystemDefaults() method has been called.
-
-          FontDescription description;
-          description.path   = cacheItem.mPath;
-          description.family = std::move(FontFamily(cacheItem.mFreeTypeFace->family_name));
-          description.weight = FontWeight::NONE;
-          description.width  = FontWidth::NONE;
-          description.slant  = FontSlant::NONE;
-
-          // Note FreeType doesn't give too much info to build a proper font style.
-          if(cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC)
-          {
-            description.slant = FontSlant::ITALIC;
-          }
-          if(cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD)
-          {
-            description.weight = FontWeight::BOLD;
-          }
-
-          cacheItem.mCharacterSet = FcCharSetCopy(CreateCharacterSetFromDescription(description));
-        }
-
-        isSupported = FcCharSetHasChar(cacheItem.mCharacterSet, character);
+        return &mFontFaceCache[fontIdCacheItem.id];
       }
-      break;
-    }
-    case FontDescription::BITMAP_FONT:
-    {
-      const BitmapFont& bitmapFont = mBitmapFontCache[fontIdCacheItem.id].font;
-
-      for(const auto& glyph : bitmapFont.glyphs)
+      case FontDescription::BITMAP_FONT:
       {
-        if(glyph.utf32 == character)
-        {
-          isSupported = true;
-          break;
-        }
+        return &mBitmapFontCache[fontIdCacheItem.id];
+      }
+      default:
+      {
+        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
       }
-      break;
-    }
-    default:
-    {
-      DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
     }
   }
-
-  DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  is supported : %s\n", (isSupported ? "true" : "false"));
-  return isSupported;
+  return nullptr;
 }
 
 FontId FontClient::Plugin::FindFontForCharacter(const FontList&         fontList,
@@ -1017,35 +912,7 @@ FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
     }
   }
 
-  BitmapFontCacheItem bitmapFontCacheItem;
-  bitmapFontCacheItem.font = bitmapFont;
-  bitmapFontCacheItem.id   = mFontIdCache.Count();
-
-  // Resize the vector with the pixel buffers.
-  bitmapFontCacheItem.pixelBuffers.resize(bitmapFont.glyphs.size());
-
-  // Traverse all the glyphs and load the pixel buffer of those with ascender and descender equal to zero.
-  unsigned int index = 0u;
-  for(auto& glyph : bitmapFontCacheItem.font.glyphs)
-  {
-    Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-
-    if(EqualsZero(glyph.ascender) && EqualsZero(glyph.descender))
-    {
-      // Load the glyph.
-      pixelBuffer = LoadImageFromFile(glyph.url);
-
-      if(pixelBuffer)
-      {
-        glyph.ascender = static_cast<float>(pixelBuffer.GetHeight());
-      }
-    }
-
-    bitmapFontCacheItem.font.ascender  = std::max(glyph.ascender, bitmapFontCacheItem.font.ascender);
-    bitmapFontCacheItem.font.descender = std::min(glyph.descender, bitmapFontCacheItem.font.descender);
-
-    ++index;
-  }
+  BitmapFontCacheItem bitmapFontCacheItem(bitmapFont, mFontIdCache.Count());
 
   FontIdCacheItem fontIdCacheItem;
   fontIdCacheItem.type = FontDescription::BITMAP_FONT;
@@ -1114,82 +981,23 @@ void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
 void FontClient::Plugin::GetFontMetrics(FontId       fontId,
                                         FontMetrics& metrics)
 {
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-        metrics = font.mMetrics;
-
-        // Adjust the metrics if the fixed-size font should be down-scaled
-        if(font.mIsFixedSizeBitmap)
-        {
-          const float desiredFixedSize = static_cast<float>(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
-
-          if(desiredFixedSize > 0.f)
-          {
-            const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels;
-
-            metrics.ascender           = metrics.ascender * scaleFactor;
-            metrics.descender          = metrics.descender * scaleFactor;
-            metrics.height             = metrics.height * scaleFactor;
-            metrics.underlinePosition  = metrics.underlinePosition * scaleFactor;
-            metrics.underlineThickness = metrics.underlineThickness * scaleFactor;
-          }
-        }
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        const BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-        metrics.ascender           = bitmapFontCacheItem.font.ascender;
-        metrics.descender          = bitmapFontCacheItem.font.descender;
-        metrics.height             = metrics.ascender - metrics.descender;
-        metrics.underlinePosition  = bitmapFontCacheItem.font.underlinePosition;
-        metrics.underlineThickness = bitmapFontCacheItem.font.underlineThickness;
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-  else
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
+    fontCacheItem->GetFontMetrics(metrics, mDpiVertical);
   }
 }
 
 GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId    fontId,
                                              Character charcode)
 {
-  GlyphIndex   glyphIndex = 0u;
-  const FontId index      = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      FT_Face ftFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
-
-      glyphIndex = FT_Get_Char_Index(ftFace, charcode);
-    }
+    return fontCacheItem->GetGlyphIndex(charcode);
   }
 
-  return glyphIndex;
+  return 0u;
 }
 
 bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array,
@@ -1209,184 +1017,22 @@ bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array,
                                           uint32_t   size,
                                           bool       horizontal)
 {
-  bool success(true);
+  bool success(false);
 
   for(unsigned int i = 0; i < size; ++i)
   {
     GlyphInfo& glyph = array[i];
 
-    FontId index = glyph.fontId - 1u;
-
-    if((glyph.fontId > 0u) &&
-       (index < mFontIdCache.Count()))
+    const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(glyph.fontId);
+    if(fontCacheItem != nullptr)
     {
-      const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-      switch(fontIdCacheItem.type)
-      {
-        case FontDescription::FACE_FONT:
-        {
-          const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-          FT_Face ftFace = font.mFreeTypeFace;
-
-#ifdef FREETYPE_BITMAP_SUPPORT
-          // Check to see if we should be loading a Fixed Size bitmap?
-          if(font.mIsFixedSizeBitmap)
-          {
-            FT_Select_Size(ftFace, font.mFixedSizeIndex); ///< @todo: needs to be investigated why it's needed to select the size again.
-            int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_COLOR);
-            if(FT_Err_Ok == error)
-            {
-              glyph.width    = font.mFixedWidthPixels;
-              glyph.height   = font.mFixedHeightPixels;
-              glyph.advance  = font.mFixedWidthPixels;
-              glyph.xBearing = 0.0f;
-              glyph.yBearing = font.mFixedHeightPixels;
-
-              // Adjust the metrics if the fixed-size font should be down-scaled
-              const float desiredFixedSize = static_cast<float>(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
-
-              if(desiredFixedSize > 0.f)
-              {
-                const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels;
-
-                glyph.width    = glyph.width * scaleFactor;
-                glyph.height   = glyph.height * scaleFactor;
-                glyph.advance  = glyph.advance * scaleFactor;
-                glyph.xBearing = glyph.xBearing * scaleFactor;
-                glyph.yBearing = glyph.yBearing * scaleFactor;
-
-                glyph.scaleFactor = scaleFactor;
-              }
-            }
-            else
-            {
-              DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error);
-              success = false;
-            }
-          }
-          else
-#endif
-          {
-            // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap.
-            // i.e. with the SNum-3R font.
-            // @todo: add an option to use the FT_LOAD_DEFAULT if required?
-            int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_NO_AUTOHINT);
-
-            // Keep the width of the glyph before doing the software emboldening.
-            // It will be used to calculate a scale factor to be applied to the
-            // advance as Harfbuzz doesn't apply any SW emboldening to calculate
-            // the advance of the glyph.
-            const float width = static_cast<float>(ftFace->glyph->metrics.width) * FROM_266;
-
-            if(FT_Err_Ok == error)
-            {
-              const bool isEmboldeningRequired = glyph.isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD);
-              if(isEmboldeningRequired)
-              {
-                // Does the software bold.
-                FT_GlyphSlot_Embolden(ftFace->glyph);
-              }
-
-              glyph.width  = static_cast<float>(ftFace->glyph->metrics.width) * FROM_266;
-              glyph.height = static_cast<float>(ftFace->glyph->metrics.height) * FROM_266;
-              if(horizontal)
-              {
-                glyph.xBearing += static_cast<float>(ftFace->glyph->metrics.horiBearingX) * FROM_266;
-                glyph.yBearing += static_cast<float>(ftFace->glyph->metrics.horiBearingY) * FROM_266;
-              }
-              else
-              {
-                glyph.xBearing += static_cast<float>(ftFace->glyph->metrics.vertBearingX) * FROM_266;
-                glyph.yBearing += static_cast<float>(ftFace->glyph->metrics.vertBearingY) * FROM_266;
-              }
-
-              if(isEmboldeningRequired && !Dali::EqualsZero(width))
-              {
-                // If the glyph is emboldened by software, the advance is multiplied by a
-                // scale factor to make it slightly bigger.
-                glyph.advance *= (glyph.width / width);
-              }
-
-              // Use the bounding box of the bitmap to correct the metrics.
-              // For some fonts i.e the SNum-3R the metrics need to be corrected,
-              // otherwise the glyphs 'dance' up and down depending on the
-              // font's point size.
-
-              FT_Glyph ftGlyph;
-              error = FT_Get_Glyph(ftFace->glyph, &ftGlyph);
-
-              FT_BBox bbox;
-              FT_Glyph_Get_CBox(ftGlyph, FT_GLYPH_BBOX_GRIDFIT, &bbox);
-
-              const float descender = glyph.height - glyph.yBearing;
-              glyph.height          = (bbox.yMax - bbox.yMin) * FROM_266;
-              glyph.yBearing        = glyph.height - round(descender);
-
-              // Created FT_Glyph object must be released with FT_Done_Glyph
-              FT_Done_Glyph(ftGlyph);
-            }
-            else
-            {
-              success = false;
-            }
-          }
-          break;
-        }
-        case FontDescription::BITMAP_FONT:
-        {
-          BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-          unsigned int index = 0u;
-          for(auto& item : bitmapFontCacheItem.font.glyphs)
-          {
-            if(item.utf32 == glyph.index)
-            {
-              Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-              if(!pixelBuffer)
-              {
-                pixelBuffer = LoadImageFromFile(item.url);
-              }
-
-              glyph.width       = static_cast<float>(pixelBuffer.GetWidth());
-              glyph.height      = static_cast<float>(pixelBuffer.GetHeight());
-              glyph.xBearing    = 0.f;
-              glyph.yBearing    = glyph.height + item.descender;
-              glyph.advance     = glyph.width;
-              glyph.scaleFactor = 1.f;
-              break;
-            }
-            ++index;
-          }
-
-          success = true;
-          break;
-        }
-        default:
-        {
-          DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-        }
-      }
+      success = fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal);
     }
-    else
+    // Check if it's an embedded image.
+    else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
     {
-      // Check if it's an embedded image.
-      if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
-      {
-        const EmbeddedItem& item = mEmbeddedItemCache[glyph.index - 1u];
-
-        glyph.width       = static_cast<float>(item.width);
-        glyph.height      = static_cast<float>(item.height);
-        glyph.xBearing    = 0.f;
-        glyph.yBearing    = glyph.height;
-        glyph.advance     = glyph.width;
-        glyph.scaleFactor = 1.f;
-      }
-      else
-      {
-        success = false;
-      }
+      mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph);
+      success = true;
     }
   }
 
@@ -1438,219 +1084,17 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
 
 void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
 {
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  data.isColorBitmap                          = false;
+  data.isColorEmoji                           = false;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    data.isColorBitmap = false;
-    data.isColorEmoji  = false;
-
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-        // For the software italics.
-        bool isShearRequired = false;
-
-        const FontFaceCacheItem& fontFaceCacheItem = mFontFaceCache[fontIdCacheItem.id];
-        FT_Face                  ftFace            = fontFaceCacheItem.mFreeTypeFace;
-
-        FT_Error error;
-
-#ifdef FREETYPE_BITMAP_SUPPORT
-        // Check to see if this is fixed size bitmap
-        if(fontFaceCacheItem.mIsFixedSizeBitmap)
-        {
-          error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR);
-        }
-        else
-#endif
-        {
-          // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap.
-          // i.e. with the SNum-3R font.
-          // @todo: add an option to use the FT_LOAD_DEFAULT if required?
-          error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_NO_AUTOHINT);
-        }
-        if(FT_Err_Ok == error)
-        {
-          if(isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD))
-          {
-            // Does the software bold.
-            FT_GlyphSlot_Embolden(ftFace->glyph);
-          }
-
-          if(isItalicRequired && !(ftFace->style_flags & FT_STYLE_FLAG_ITALIC))
-          {
-            // Will do the software italic.
-            isShearRequired = true;
-          }
-
-          FT_Glyph glyph;
-          error = FT_Get_Glyph(ftFace->glyph, &glyph);
-
-          // Convert to bitmap if necessary
-          if(FT_Err_Ok == error)
-          {
-            if(glyph->format != FT_GLYPH_FORMAT_BITMAP)
-            {
-              int  offsetX = 0, offsetY = 0;
-              bool isOutlineGlyph = (glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0);
-
-              // Create a bitmap for the outline
-              if(isOutlineGlyph)
-              {
-                // Retrieve the horizontal and vertical distance from the current pen position to the
-                // left and top border of the glyph bitmap for a normal glyph before applying the outline.
-                if(FT_Err_Ok == error)
-                {
-                  FT_Glyph normalGlyph;
-                  error = FT_Get_Glyph(ftFace->glyph, &normalGlyph);
-
-                  error = FT_Glyph_To_Bitmap(&normalGlyph, FT_RENDER_MODE_NORMAL, 0, 1);
-                  if(FT_Err_Ok == error)
-                  {
-                    FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(normalGlyph);
-
-                    offsetX = bitmapGlyph->left;
-                    offsetY = bitmapGlyph->top;
-                  }
-
-                  // Created FT_Glyph object must be released with FT_Done_Glyph
-                  FT_Done_Glyph(normalGlyph);
-                }
-
-                // Now apply the outline
-
-                // Set up a stroker
-                FT_Stroker stroker;
-                error = FT_Stroker_New(mFreeTypeLibrary, &stroker);
-
-                if(FT_Err_Ok == error)
-                {
-                  FT_Stroker_Set(stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
-                  error = FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1);
-
-                  if(FT_Err_Ok == error)
-                  {
-                    FT_Stroker_Done(stroker);
-                  }
-                  else
-                  {
-                    DALI_LOG_ERROR("FT_Glyph_StrokeBorder Failed with error: %d\n", error);
-                  }
-                }
-                else
-                {
-                  DALI_LOG_ERROR("FT_Stroker_New Failed with error: %d\n", error);
-                }
-              }
-
-              error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
-              if(FT_Err_Ok == error)
-              {
-                FT_BitmapGlyph bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
-
-                if(isOutlineGlyph)
-                {
-                  // Calculate the additional horizontal and vertical offsets needed for the position of the outline glyph
-                  data.outlineOffsetX = offsetX - bitmapGlyph->left - outlineWidth;
-                  data.outlineOffsetY = bitmapGlyph->top - offsetY - outlineWidth;
-                }
-
-                ConvertBitmap(data, bitmapGlyph->bitmap, isShearRequired);
-              }
-              else
-              {
-                DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error);
-              }
-            }
-            else
-            {
-              ConvertBitmap(data, ftFace->glyph->bitmap, isShearRequired);
-            }
-
-            data.isColorEmoji = fontFaceCacheItem.mIsFixedSizeBitmap;
-
-            // Created FT_Glyph object must be released with FT_Done_Glyph
-            FT_Done_Glyph(glyph);
-          }
-        }
-        else
-        {
-          DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error);
-        }
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id];
-
-        unsigned int index = 0u;
-        for(auto& item : bitmapFontCacheItem.font.glyphs)
-        {
-          if(item.utf32 == glyphIndex)
-          {
-            Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index];
-            if(!pixelBuffer)
-            {
-              pixelBuffer = LoadImageFromFile(item.url);
-            }
-
-            data.width  = pixelBuffer.GetWidth();
-            data.height = pixelBuffer.GetHeight();
-
-            data.isColorBitmap = bitmapFontCacheItem.font.isColorFont;
-
-            ConvertBitmap(data, data.width, data.height, pixelBuffer.GetBuffer());
-
-            // Sets the pixel format.
-            data.format = pixelBuffer.GetPixelFormat();
-            break;
-          }
-          ++index;
-        }
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
+    fontCacheItem->CreateBitmap(glyphIndex, data, outlineWidth, isItalicRequired, isBoldRequired);
   }
-  else
+  else if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
   {
-    if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
-    {
-      // It's an embedded item.
-      const EmbeddedItem& item = mEmbeddedItemCache[glyphIndex - 1u];
-
-      data.width  = item.width;
-      data.height = item.height;
-      if(0u != item.pixelBufferId)
-      {
-        Devel::PixelBuffer pixelBuffer = mPixelBufferCache[item.pixelBufferId - 1u].pixelBuffer;
-        if(pixelBuffer)
-        {
-          ConvertBitmap(data, pixelBuffer.GetWidth(), pixelBuffer.GetHeight(), pixelBuffer.GetBuffer());
-
-          // Sets the pixel format.
-          data.format = pixelBuffer.GetPixelFormat();
-        }
-      }
-      else
-      {
-        // Creates the output buffer
-        const unsigned int bufferSize = data.width * data.height * 4u;
-        data.buffer                   = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
-
-        memset(data.buffer, 0u, bufferSize);
-
-        // Just creates a void buffer. Doesn't matter what pixel format is set as is the application code the responsible of filling it.
-      }
-    }
+    // It's an embedded item.
+    mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mPixelBufferCache, data);
   }
 }
 
@@ -1731,62 +1175,18 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedP
 
 bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex)
 {
-  FT_Error error = -1;
-
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    switch(fontIdCacheItem.type)
-    {
-      case FontDescription::FACE_FONT:
-      {
-#ifdef FREETYPE_BITMAP_SUPPORT
-        const FontFaceCacheItem& item   = mFontFaceCache[fontIdCacheItem.id];
-        FT_Face                  ftFace = item.mFreeTypeFace;
-
-        // Check to see if this is fixed size bitmap
-        if(item.mHasColorTables)
-        {
-          error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR);
-        }
-#endif
-        break;
-      }
-      case FontDescription::BITMAP_FONT:
-      {
-        error = FT_Err_Ok; // Will return true;
-        break;
-      }
-      default:
-      {
-        DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "  Invalid type of font\n");
-      }
-    }
-  }
-
-  return FT_Err_Ok == error;
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  return fontCacheItem && fontCacheItem->IsColorGlyph(glyphIndex);
 }
 
 FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId)
 {
-  FT_Face fontFace = nullptr;
-
-  const FontId index = fontId - 1u;
-  if((fontId > 0u) &&
-     (index < mFontIdCache.Count()))
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      fontFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace;
-    }
+    return fontCacheItem->GetTypeface();
   }
-  return fontFace;
+  return nullptr;
 }
 
 FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId)
@@ -2165,7 +1565,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
                             0.0f);
 
         // Create the FreeType font face item to cache.
-        FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
+        FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
 
         // Set the index to the font's id cache.
         fontFaceCacheItem.mFontId = mFontIdCache.Count();
@@ -2223,7 +1623,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
                             static_cast<float>(ftFace->underline_thickness) * FROM_266);
 
         // Create the FreeType font face item to cache.
-        FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics);
+        FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics);
 
         // Set the index to the font's id cache.
         fontFaceCacheItem.mFontId = mFontIdCache.Count();
@@ -2500,28 +1900,12 @@ void FontClient::Plugin::GetFixedSizes(const FontDescription&   fontDescription,
 
 bool FontClient::Plugin::HasItalicStyle(FontId fontId) const
 {
-  bool hasItalicStyle = false;
-
-  const FontId index = fontId - 1u;
-
-  if((fontId > 0) &&
-     (index < mFontIdCache.Count()))
-  {
-    const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
-
-    if(FontDescription::FACE_FONT == fontIdCacheItem.type)
-    {
-      const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id];
-
-      hasItalicStyle = 0u != (font.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC);
-    }
-  }
-  else
+  const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
+  if(fontCacheItem != nullptr)
   {
-    DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId);
+    return fontCacheItem->HasItalicStyle();
   }
-
-  return hasItalicStyle;
+  return false;
 }
 
 void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path)
@@ -2610,8 +1994,4 @@ void FontClient::Plugin::ClearCharacterSetFromFontFaceCache()
   }
 }
 
-} // namespace Internal
-
-} // namespace TextAbstraction
-
-} // namespace Dali
+} // namespace Dali::TextAbstraction::Internal
index a8de931..6274cdf 100644 (file)
 #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>
@@ -55,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;
@@ -115,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;
@@ -158,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.
@@ -255,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.
@@ -608,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.
index d257d53..3f9743f 100644 (file)
@@ -21,7 +21,9 @@
 
 #include <memory>
 
+#if defined(DEBUG_ENABLED)
 extern Dali::Integration::Log::Filter* gFontClientLogFilter;
+#endif
 
 namespace Dali::TextAbstraction::Internal
 {
index 4465521..f329193 100644 (file)
 
 #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
 {
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