/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/text/text-abstraction/font-client-impl.h>
// EXTERNAL INCLUDES
-#if !(defined(DALI_PROFILE_UBUNTU) || defined(ANDROID) || defined(WIN32) || defined(__APPLE__))
+#include <mutex>
+#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>
+// Use this macro only if need to log messages before the log function is set.
+#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
{
namespace Internal
{
-Dali::TextAbstraction::FontClient FontClient::gPreInitializedFontClient(NULL);
+Dali::TextAbstraction::FontClient FontClient::gPreCreatedFontClient(NULL);
+std::thread gPreCacheThread;
+std::thread gPreLoadThread;
+std::mutex gMutex;
+
+/* 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;
+bool gFontPreLoadAvailable = true;
FontClient::FontClient()
: mPlugin(nullptr),
}
else // create and register the object
{
- if(gPreInitializedFontClient)
+ if(gPreCacheThread.joinable())
+ {
+ gPreCacheThread.join();
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreCache thread join\n");
+ }
+
+ if(gPreLoadThread.joinable())
{
- fontClientHandle = gPreInitializedFontClient;
- gPreInitializedFontClient.Reset(); // No longer needed
+ gPreLoadThread.join();
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient PreLoad thread join\n");
+ }
+
+ if(gPreCreatedFontClient)
+ {
+ fontClientHandle = gPreCreatedFontClient;
+ gPreCreatedFontClient.Reset(); // No longer needed
}
else
{
fontClientHandle = Dali::TextAbstraction::FontClient(new FontClient);
}
+ fontClientHandle.InitDefaultFontDescription();
+
+ gFontPreCacheAvailable = false;
+ gFontPreLoadAvailable = 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);
}
}
Dali::TextAbstraction::FontClient FontClient::PreInitialize()
{
- gPreInitializedFontClient = Dali::TextAbstraction::FontClient(new FontClient);
+ // Pre-cached font client already exists or pre-cache thread already running.
+ // Font client pre-cache includes caching of the default font description.
+ if(gPreCreatedFontClient && !gFontPreCacheAvailable)
+ {
+ return gPreCreatedFontClient;
+ }
+
+ if(!gPreCreatedFontClient)
+ {
+ gPreCreatedFontClient = Dali::TextAbstraction::FontClient(new FontClient);
+ }
+
+ gPreCreatedFontClient.InitDefaultFontDescription();
+
+ return gPreCreatedFontClient;
+}
+
+void FontClient::PreCacheRun(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily)
+{
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_PRECACHE_RUN\n");
+ GetImplementation(gPreCreatedFontClient).FontPreCache(fallbackFamilyList, extraFamilyList, localeFamily);
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_PRECACHE_RUN\n");
+}
+
+void FontClient::PreLoadRun(const FontPathList& fontPathList, const FontPathList& memoryFontPathList)
+{
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "BEGIN: DALI_TEXT_FONT_PRELOAD_RUN\n");
+ GetImplementation(gPreCreatedFontClient).FontPreLoad(fontPathList, memoryFontPathList);
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "END: DALI_TEXT_FONT_PRELOAD_RUN\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 run failed, as a pre-cached font client already exists.\n");
+ return;
+ }
+
+ if(gPreCacheThread.joinable())
+ {
+ FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient pre-cache thread already running.\n");
+ }
+
+ if(!gPreCreatedFontClient)
+ {
+ gPreCreatedFontClient = Dali::TextAbstraction::FontClient(new FontClient);
+ }
+
+ gFontPreCacheAvailable = false;
- // Make DefaultFontDescription cached
- Dali::TextAbstraction::FontDescription defaultFontDescription;
- gPreInitializedFontClient.GetDefaultPlatformFontDescription(defaultFontDescription);
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient FontConfig PreCache fallbackFamilyList : %zu\n", fallbackFamilyList.size());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient FontConfig PreCache extraFamilyList : %zu\n", extraFamilyList.size());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient FontConfig PreCache localeFamily : %s\n", localeFamily.c_str());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient FontConfig PreCache useThread : %d\n", useThread);
- return gPreInitializedFontClient;
+ if(useThread)
+ {
+ gPreCacheThread = std::thread(PreCacheRun, fallbackFamilyList, extraFamilyList, localeFamily);
+ }
+ else
+ {
+ PreCacheRun(fallbackFamilyList, extraFamilyList, localeFamily);
+ }
+}
+
+void FontClient::PreLoad(const FontPathList& fontPathList, const FontPathList& memoryFontPathList, bool useThread)
+{
+ if(!gFontPreLoadAvailable)
+ {
+ FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient font pre-load run failed, as a pre-loaded font client already exists.\n");
+ return;
+ }
+
+ if(gPreLoadThread.joinable())
+ {
+ FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "FontClient font pre-load thread already running.\n");
+ return;
+ }
+
+ if(!gPreCreatedFontClient)
+ {
+ gPreCreatedFontClient = Dali::TextAbstraction::FontClient(new FontClient);
+ }
+
+ gFontPreLoadAvailable = false;
+
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient Font PreLoad fontPathList : %zu\n", fontPathList.size());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient Font PreLoad memoryFontPathList : %zu\n", memoryFontPathList.size());
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "FontClient Font PreLoad useThread : %d\n", useThread);
+
+ if(useThread)
+ {
+ gPreLoadThread = std::thread(PreLoadRun, fontPathList, memoryFontPathList);
+ }
+ else
+ {
+ PreLoadRun(fontPathList, memoryFontPathList);
+ }
}
void FontClient::ClearCache()
{
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
mPlugin->GetDefaultFonts(defaultFonts);
}
+void FontClient::FontPreCache(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily)
+{
+ CreatePlugin();
+
+ mPlugin->FontPreCache(fallbackFamilyList, extraFamilyList, localeFamily);
+}
+
+void FontClient::FontPreLoad(const FontPathList& fontPathList, const FontPathList& memoryFontPathList)
+{
+ CreatePlugin();
+
+ mPlugin->FontPreLoad(fontPathList, memoryFontPathList);
+}
+
+void FontClient::InitDefaultFontDescription()
+{
+ CreatePlugin();
+
+ mPlugin->InitDefaultFontDescription();
+}
+
void FontClient::GetDefaultPlatformFontDescription(FontDescription& fontDescription)
{
CreatePlugin();
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)
{
CreatePlugin();
- return mPlugin->GetFontId(path,
- requestedPointSize,
- faceIndex,
- true);
+ return mPlugin->GetFontIdByPath(path,
+ requestedPointSize,
+ faceIndex,
+ true);
}
FontId FontClient::GetFontId(const FontDescription& fontDescription,
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();
{
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)
return mPlugin->AddCustomFontDirectory(path);
}
+HarfBuzzFontHandle FontClient::GetHarfBuzzFont(FontId fontId)
+{
+ CreatePlugin();
+
+ return mPlugin->GetHarfBuzzFont(fontId);
+}
+
void FontClient::CreatePlugin()
{
+ std::scoped_lock lock(gMutex);
if(!mPlugin)
{
mPlugin = new Plugin(mDpiHorizontal, mDpiVertical);