Fix performance down if DefaultFontDescription not prepared
[platform/core/uifw/dali-adaptor.git] / dali / internal / text / text-abstraction / font-client-impl.cpp
index d708d85..5e2b258 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/internal/text/text-abstraction/font-client-impl.h>
 
 // EXTERNAL INCLUDES
-#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32) || defined(__APPLE__))
+#include <thread>
+#if defined(VCONF_ENABLED)
 #include <vconf.h>
 #endif
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/common/singleton-service.h>
-#include <dali/internal/text/text-abstraction/font-client-plugin-impl.h>
+#include <dali/internal/system/common/logging.h>
+#include <dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h>
+#include <dali/internal/window-system/common/window-system.h>
 
 #include <dali/devel-api/text-abstraction/glyph-info.h>
 
+#define FONT_LOG_MESSAGE(level, format, ...)                                    \
+  do                                                                            \
+  {                                                                             \
+    char buffer[256];                                                           \
+    int  result = std::snprintf(buffer, sizeof(buffer), format, ##__VA_ARGS__); \
+    if(result >= static_cast<int>(sizeof(buffer)))                              \
+    {                                                                           \
+      std::string log("Font log message is too long to fit in the buffer.\n");  \
+      Dali::TizenPlatform::LogMessage(Dali::Integration::Log::ERROR, log);      \
+      break;                                                                    \
+    }                                                                           \
+    std::string log(buffer);                                                    \
+    Dali::TizenPlatform::LogMessage(level, log);                                \
+  } while(0)
+
 namespace Dali
 {
 namespace TextAbstraction
@@ -36,6 +54,12 @@ namespace TextAbstraction
 namespace Internal
 {
 Dali::TextAbstraction::FontClient FontClient::gPreInitializedFontClient(NULL);
+Dali::TextAbstraction::FontClient FontClient::gPreCachedFontClient(NULL);
+std::thread                       gPreCacheThread;
+/* TODO: This is to prevent duplicate calls of font pre-cache.
+ * We may support this later, but currently we can't guarantee the behaviour
+ * if there is a pre-cache call from the user after the font client has been created. */
+bool gFontPreCacheAvailable = true;
 
 FontClient::FontClient()
 : mPlugin(nullptr),
@@ -66,14 +90,41 @@ Dali::TextAbstraction::FontClient FontClient::Get()
     }
     else // create and register the object
     {
+      if(gPreCacheThread.joinable())
+      {
+        gPreCacheThread.join();
+        FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache thread join\n");
+      }
+
       if(gPreInitializedFontClient)
       {
         fontClientHandle = gPreInitializedFontClient;
         gPreInitializedFontClient.Reset(); // No longer needed
       }
+      else if(gPreCachedFontClient)
+      {
+        // TODO: Currently font pre-caching is not available in the candidate process.
+        fontClientHandle = gPreCachedFontClient;
+        gPreCachedFontClient.Reset(); // No longer needed
+      }
       else
       {
         fontClientHandle = Dali::TextAbstraction::FontClient(new FontClient);
+
+        // Make DefaultFontDescription cached
+        Dali::TextAbstraction::FontDescription defaultFontDescription;
+        fontClientHandle.GetDefaultPlatformFontDescription(defaultFontDescription);
+      }
+
+      gFontPreCacheAvailable = false;
+
+      uint32_t horizontalDpi, verticalDpi;
+      fontClientHandle.GetDpi(horizontalDpi, verticalDpi);
+      if(horizontalDpi == 0u || verticalDpi == 0u)
+      {
+        horizontalDpi = verticalDpi = 0u;
+        Dali::Internal::Adaptor::WindowSystem::GetDpi(horizontalDpi, verticalDpi);
+        fontClientHandle.SetDpi(horizontalDpi, verticalDpi);
       }
 
       service.Register(typeid(fontClientHandle), fontClientHandle);
@@ -94,6 +145,53 @@ Dali::TextAbstraction::FontClient FontClient::PreInitialize()
   return gPreInitializedFontClient;
 }
 
+void FontClient::PreCacheRun(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily)
+{
+  if(!gPreCachedFontClient)
+  {
+    FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_PRECACHE_RUN\n");
+    Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient(new FontClient);
+    GetImplementation(fontClient).FontPreCache(fallbackFamilyList, extraFamilyList, localeFamily);
+    gPreCachedFontClient   = fontClient;
+    gFontPreCacheAvailable = false;
+    FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_PRECACHE_RUN\n");
+  }
+  else
+  {
+    FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache run failed, as a pre-cached font client already exists.\n");
+  }
+}
+
+void FontClient::PreCache(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily, bool useThread)
+{
+  if(!gFontPreCacheAvailable)
+  {
+    FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache has been completed or the font client has already been created.\n");
+    return;
+  }
+
+  FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache fallbackFamilyList : %zu\n", fallbackFamilyList.size());
+  FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache extraFamilyList    : %zu\n", extraFamilyList.size());
+  FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache localeFamily       : %s\n", localeFamily.c_str());
+  FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache useThread          : %d\n", useThread);
+
+  if(gPreCacheThread.joinable())
+  {
+    FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache thread already running.\n");
+  }
+  else
+  {
+    if(useThread)
+    {
+      gPreCacheThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily);
+    }
+    else
+    {
+      PreCacheRun(fallbackFamilyList, extraFamilyList, localeFamily);
+    }
+  }
+}
+
 void FontClient::ClearCache()
 {
   if(mPlugin)
@@ -124,7 +222,7 @@ int FontClient::GetDefaultFontSize()
 {
   int fontSize(-1);
 
-#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32) || defined(__APPLE__))
+#if defined(VCONF_ENABLED)
   vconf_get_int(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, &fontSize);
 #endif
 
@@ -145,6 +243,13 @@ void FontClient::GetDefaultFonts(FontList& defaultFonts)
   mPlugin->GetDefaultFonts(defaultFonts);
 }
 
+void FontClient::FontPreCache(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily)
+{
+  CreatePlugin();
+
+  mPlugin->FontPreCache(fallbackFamilyList, extraFamilyList, localeFamily);
+}
+
 void FontClient::GetDefaultPlatformFontDescription(FontDescription& fontDescription)
 {
   CreatePlugin();
@@ -152,18 +257,18 @@ void FontClient::GetDefaultPlatformFontDescription(FontDescription& fontDescript
   mPlugin->GetDefaultPlatformFontDescription(fontDescription);
 }
 
-void FontClient::GetDescription(FontId id, FontDescription& fontDescription)
+void FontClient::GetDescription(FontId fontId, FontDescription& fontDescription)
 {
   CreatePlugin();
 
-  mPlugin->GetDescription(id, fontDescription);
+  mPlugin->GetDescription(fontId, fontDescription);
 }
 
-PointSize26Dot6 FontClient::GetPointSize(FontId id)
+PointSize26Dot6 FontClient::GetPointSize(FontId fontId)
 {
   CreatePlugin();
 
-  return mPlugin->GetPointSize(id);
+  return mPlugin->GetPointSize(fontId);
 }
 
 bool FontClient::IsCharacterSupportedByFont(FontId fontId, Character character)
@@ -246,10 +351,10 @@ FontId FontClient::GetFontId(const FontPath& path, PointSize26Dot6 requestedPoin
 {
   CreatePlugin();
 
-  return mPlugin->GetFontId(path,
-                            requestedPointSize,
-                            faceIndex,
-                            true);
+  return mPlugin->GetFontIdByPath(path,
+                                  requestedPointSize,
+                                  faceIndex,
+                                  true);
 }
 
 FontId FontClient::GetFontId(const FontDescription& fontDescription,
@@ -284,6 +389,13 @@ GlyphIndex FontClient::GetGlyphIndex(FontId fontId, Character charcode)
   return mPlugin->GetGlyphIndex(fontId, charcode);
 }
 
+GlyphIndex FontClient::GetGlyphIndex(FontId fontId, Character charcode, Character variantSelector)
+{
+  CreatePlugin();
+
+  return mPlugin->GetGlyphIndex(fontId, charcode, variantSelector);
+}
+
 bool FontClient::GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type, bool horizontal)
 {
   CreatePlugin();
@@ -291,7 +403,7 @@ bool FontClient::GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type
   return mPlugin->GetGlyphMetrics(array, size, type, horizontal);
 }
 
-void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth)
 {
   CreatePlugin();
 
@@ -387,7 +499,8 @@ uint32_t FontClient::GetNumberOfPointsPerOneUnitOfPointSize() const
   {
     return mPlugin->GetNumberOfPointsPerOneUnitOfPointSize();
   }
-  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  ;
 }
 
 FT_FaceRec_* FontClient::GetFreetypeFace(FontId fontId)
@@ -411,6 +524,13 @@ bool FontClient::AddCustomFontDirectory(const FontPath& path)
   return mPlugin->AddCustomFontDirectory(path);
 }
 
+HarfBuzzFontHandle FontClient::GetHarfBuzzFont(FontId fontId)
+{
+  CreatePlugin();
+
+  return mPlugin->GetHarfBuzzFont(fontId);
+}
+
 void FontClient::CreatePlugin()
 {
   if(!mPlugin)