/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// INTERNAL INCLUDES
#include <dali/devel-api/text-abstraction/font-list.h>
-
-#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/trace.h>
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/imaging/common/image-operations.h>
+#include <dali/internal/system/common/logging.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-plugin-cache-handler.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 <algorithm>
#include <iterator>
+// 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)
+
#if defined(DEBUG_ENABLED)
// Note, to turn on trace and verbose logging, use "export LOG_FONT_CLIENT=3,true"
namespace
{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FONT_PERFORMANCE_MARKER, false);
+
/**
* Conversion from Fractional26.6 to float
*/
const float FROM_266 = 1.0f / 64.0f;
const float POINTS_PER_INCH = 72.f;
-const std::string DEFAULT_FONT_FAMILY_NAME("Tizen");
-
const uint32_t ELLIPSIS_CHARACTER = 0x2026;
} // namespace
using Dali::Vector;
-using namespace std;
namespace Dali::TextAbstraction::Internal
{
-/**
- * @brief Free the resources allocated by the FcCharSet objects.
- *
- * @param[in] characterSets The vector of character sets.
- */
-void DestroyCharacterSets(CharacterSetList& characterSets)
+namespace
{
- for(auto& item : characterSets)
- {
- if(item)
- {
- FcCharSetDestroy(item);
- }
- }
-}
-
/**
* @brief Check if @p ftFace and @p requestedPointSize produces block that fit into atlas block
*
error = FT_Set_Char_Size(ftFace,
0,
- requestedPointSize,
+ FT_F26Dot6(requestedPointSize),
horizontalDpi,
verticalDpi);
return error;
}
-FontClient::Plugin::FallbackCacheItem::FallbackCacheItem(FontDescription&& font, FontList* fallbackFonts, CharacterSetList* characterSets)
-: fontDescription{std::move(font)},
- fallbackFonts{fallbackFonts},
- characterSets{characterSets}
-{
-}
-
-FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem(const FontDescription& fontDescription,
- FontDescriptionId index)
-: fontDescription{fontDescription},
- index{index}
-{
-}
-
-FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem(FontDescription&& fontDescription,
- FontDescriptionId index)
-: fontDescription{std::move(fontDescription)},
- index{index}
-{
-}
-
-FontClient::Plugin::FontDescriptionSizeCacheItem::FontDescriptionSizeCacheItem(FontDescriptionId validatedFontId,
- PointSize26Dot6 requestedPointSize,
- FontId fontId)
-: validatedFontId(validatedFontId),
- requestedPointSize(requestedPointSize),
- fontId(fontId)
-{
-}
+} // namespace
FontClient::Plugin::Plugin(unsigned int horizontalDpi,
unsigned int verticalDpi)
: mFreeTypeLibrary(nullptr),
mDpiHorizontal(horizontalDpi),
mDpiVertical(verticalDpi),
- mDefaultFontDescription(),
- mSystemFonts(),
- mDefaultFonts(),
- mFontIdCache(),
- mFontFaceCache(),
- mValidatedFontCache(),
- mFontDescriptionCache(),
- mCharacterSetCache(),
- mFontDescriptionSizeCache(),
- mVectorFontCache(nullptr),
- mEllipsisCache(),
- mEmbeddedItemCache(),
- mDefaultFontDescriptionCached(false),
mIsAtlasLimitationEnabled(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED),
- mCurrentMaximumBlockSizeFitInAtlas(TextAbstraction::FontClient::MAX_SIZE_FIT_IN_ATLAS)
-
+ mCurrentMaximumBlockSizeFitInAtlas(TextAbstraction::FontClient::MAX_SIZE_FIT_IN_ATLAS),
+ mVectorFontCache(nullptr),
+ mCacheHandler(new CacheHandler())
{
int error = FT_Init_FreeType(&mFreeTypeLibrary);
if(FT_Err_Ok != error)
FontClient::Plugin::~Plugin()
{
- ClearFallbackCache(mFallbackCache);
-
- // Free the resources allocated by the FcCharSet objects.
- DestroyCharacterSets(mDefaultFontCharacterSets);
- DestroyCharacterSets(mCharacterSetCache);
- ClearCharacterSetFromFontFaceCache();
+ // Delete cache hanlder before remove mFreeTypeLibrary
+ delete mCacheHandler;
#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
delete mVectorFontCache;
#endif
+
FT_Done_FreeType(mFreeTypeLibrary);
}
-void FontClient::Plugin::ClearCache()
+void FontClient::Plugin::ClearCache() const
{
- mDefaultFontDescription = FontDescription();
-
- mSystemFonts.clear();
- mDefaultFonts.clear();
-
- DestroyCharacterSets(mDefaultFontCharacterSets);
- mDefaultFontCharacterSets.Clear();
-
- ClearFallbackCache(mFallbackCache);
- mFallbackCache.clear();
-
- mFontIdCache.Clear();
-
- ClearCharacterSetFromFontFaceCache();
- mFontFaceCache.clear();
-
- mValidatedFontCache.clear();
- mFontDescriptionCache.clear();
-
- DestroyCharacterSets(mCharacterSetCache);
- mCharacterSetCache.Clear();
-
- mFontDescriptionSizeCache.clear();
-
- mEllipsisCache.Clear();
- mPixelBufferCache.clear();
- mEmbeddedItemCache.Clear();
- mBitmapFontCache.clear();
+ mCacheHandler->ClearCache();
+}
- mDefaultFontDescriptionCached = false;
+void FontClient::Plugin::ClearCacheOnLocaleChanged() const
+{
+ mCacheHandler->ClearCacheOnLocaleChanged();
}
void FontClient::Plugin::SetDpi(unsigned int horizontalDpi,
mDpiVertical = verticalDpi;
}
-void FontClient::Plugin::ResetSystemDefaults()
+void FontClient::Plugin::ResetSystemDefaults() const
{
- mDefaultFontDescriptionCached = false;
+ mCacheHandler->ResetSystemDefaults();
}
-void FontClient::Plugin::SetFontList(const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList)
+void FontClient::Plugin::CacheFontDataFromFile(const std::string& fontPath) const
{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- FONT_LOG_DESCRIPTION(fontDescription, "");
- fontList.clear();
-
- FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
-
- FcResult result = FcResultMatch;
-
- // Match the pattern.
- FcFontSet* fontSet = FcFontSort(nullptr /* use default configure */,
- fontFamilyPattern,
- false /* don't trim */,
- nullptr,
- &result); // FcFontSort creates a font set that needs to be destroyed by calling FcFontSetDestroy.
+ if(fontPath.empty())
+ {
+ return;
+ }
- if(nullptr != fontSet)
+ if(mCacheHandler->FindFontData(fontPath))
{
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of fonts found : [%d]\n", fontSet->nfont);
- // Reserve some space to avoid reallocations.
- fontList.reserve(fontSet->nfont);
+ // Font data is already cached, no need to reload
+ return;
+ }
- for(int i = 0u; i < fontSet->nfont; ++i)
- {
- FcPattern* fontPattern = fontSet->fonts[i];
+ Dali::Vector<uint8_t> fontDataBuffer;
+ std::streampos dataSize = 0;
+ if(!mCacheHandler->LoadFontDataFromFile(fontPath, fontDataBuffer, dataSize))
+ {
+ fontDataBuffer.Clear();
+ FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "Failed to load font data : %s\n", fontPath.c_str());
+ return;
+ }
- FontPath path;
+ // Cache font data
+ mCacheHandler->CacheFontData(fontPath, fontDataBuffer, dataSize);
+}
- // Skip fonts with no path
- if(GetFcString(fontPattern, FC_FILE, path))
- {
- // Retrieve the character set. Need to call FcCharSetDestroy to free the resources.
- FcCharSet* characterSet = nullptr;
- FcPatternGetCharSet(fontPattern, FC_CHARSET, 0u, &characterSet);
-
- // Increase the reference counter of the character set.
- characterSetList.PushBack(FcCharSetCopy(characterSet));
-
- fontList.push_back(FontDescription());
- FontDescription& newFontDescription = fontList.back();
-
- newFontDescription.path = std::move(path);
-
- int width = 0;
- int weight = 0;
- int slant = 0;
- GetFcString(fontPattern, FC_FAMILY, newFontDescription.family);
- GetFcInt(fontPattern, FC_WIDTH, width);
- GetFcInt(fontPattern, FC_WEIGHT, weight);
- GetFcInt(fontPattern, FC_SLANT, slant);
- newFontDescription.width = IntToWidthType(width);
- newFontDescription.weight = IntToWeightType(weight);
- newFontDescription.slant = IntToSlantType(slant);
-
- FONT_LOG_DESCRIPTION(newFontDescription, "");
- }
- }
+void FontClient::Plugin::CacheFontFaceFromFile(const std::string& fontPath) const
+{
+ if(fontPath.empty())
+ {
+ return;
+ }
- // Destroys the font set created by FcFontSort.
- FcFontSetDestroy(fontSet);
+ if(mCacheHandler->FindFontFace(fontPath))
+ {
+ // Font face is already cached, no need to reload
+ return;
}
- else
+
+ FT_Face ftFace;
+ int error = FT_New_Face(mFreeTypeLibrary, fontPath.c_str(), 0, &ftFace);
+ if(FT_Err_Ok != error)
{
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " No fonts found.\n");
+ FONT_LOG_MESSAGE(Dali::Integration::Log::ERROR, "Failed to load font face : %s\n", fontPath.c_str());
+ return;
}
- // Destroys the pattern created by FcPatternCreate in CreateFontFamilyPattern.
- FcPatternDestroy(fontFamilyPattern);
+ // Cache font face
+ mCacheHandler->CacheFontFace(fontPath, ftFace);
+ FONT_LOG_MESSAGE(Dali::Integration::Log::INFO, "PreLoad font new face : %s\n", fontPath.c_str());
}
-void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts)
+void FontClient::Plugin::FontPreLoad(const FontPathList& fontPathList, const FontPathList& memoryFontPathList) const
{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
-
- if(mDefaultFonts.empty())
+ for(const auto& fontPath : fontPathList)
{
- FontDescription fontDescription;
- fontDescription.family = DEFAULT_FONT_FAMILY_NAME; // todo This could be set to the Platform font
- fontDescription.width = DefaultFontWidth();
- fontDescription.weight = DefaultFontWeight();
- fontDescription.slant = DefaultFontSlant();
- SetFontList(fontDescription, mDefaultFonts, mDefaultFontCharacterSets);
+ CacheFontFaceFromFile(fontPath);
}
- defaultFonts = mDefaultFonts;
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of default fonts : [%d]\n", mDefaultFonts.size());
+ for(const auto& memoryFontPath : memoryFontPathList)
+ {
+ CacheFontDataFromFile(memoryFontPath);
+ }
}
-void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& fontDescription)
+void FontClient::Plugin::FontPreCache(const FontFamilyList& fallbackFamilyList, const FontFamilyList& extraFamilyList, const FontFamily& localeFamily) const
{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+ mCacheHandler->InitDefaultFontDescription();
- if(!mDefaultFontDescriptionCached)
- {
- // Clear any font config stored info in the caches.
+ FontFamilyList familyList;
+ familyList.reserve(extraFamilyList.size() + 1);
- // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
- DestroyCharacterSets(mDefaultFontCharacterSets);
- DestroyCharacterSets(mCharacterSetCache);
- mDefaultFontCharacterSets.Clear();
- mCharacterSetCache.Clear();
+ for(const auto& fallbackFont : fallbackFamilyList)
+ {
+ FontList* fontList = nullptr;
+ CharacterSetList* characterSetList = nullptr;
+ FontDescriptionId fontDescriptionId = 0u;
+ FontDescription fontDescription;
+ fontDescription.family = FontFamily(fallbackFont);
+ fontDescription.weight = DefaultFontWeight();
+ fontDescription.width = DefaultFontWidth();
+ fontDescription.slant = DefaultFontSlant();
- for(auto& item : mFallbackCache)
+ if(!mCacheHandler->FindFallbackFontList(fontDescription, fontList, characterSetList))
{
- // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects.
- DestroyCharacterSets(*item.characterSets);
-
- delete item.characterSets;
- item.characterSets = nullptr;
+ FontDescription copiedFontDescription = fontDescription;
+ mCacheHandler->CacheFallbackFontList(std::move(copiedFontDescription), fontList, characterSetList);
}
-
- // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
- ClearCharacterSetFromFontFaceCache();
-
- // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
- FcInitReinitialize();
-
- FcPattern* matchPattern = FcPatternCreate(); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy.
-
- if(nullptr != matchPattern)
+ if(!mCacheHandler->FindValidatedFont(fontDescription, fontDescriptionId))
{
- FcConfigSubstitute(nullptr, matchPattern, FcMatchPattern);
- FcDefaultSubstitute(matchPattern);
-
- FcCharSet* characterSet = nullptr;
- MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet);
- // Decrease the reference counter of the character set as it's not stored.
- FcCharSetDestroy(characterSet);
-
- // Destroys the pattern created.
- FcPatternDestroy(matchPattern);
+ mCacheHandler->ValidateFont(fontDescription, fontDescriptionId);
}
- // Create again the character sets as they are not valid after FcInitReinitialize()
-
- for(const auto& description : mDefaultFonts)
+ if(extraFamilyList.empty() && localeFamily.empty())
{
- mDefaultFontCharacterSets.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
+ continue;
}
- for(const auto& description : mFontDescriptionCache)
+ familyList.clear();
+ familyList.insert(familyList.end(), extraFamilyList.begin(), extraFamilyList.end());
+ if(!localeFamily.empty())
{
- mCharacterSetCache.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
+ familyList.push_back(localeFamily);
}
- for(auto& item : mFallbackCache)
+ for(const auto& font : *fontList)
{
- if(nullptr != item.fallbackFonts)
+ auto it = std::find(familyList.begin(), familyList.end(), font.family);
+ if(it != familyList.end())
{
- if(nullptr == item.characterSets)
+ if(!mCacheHandler->FindValidatedFont(font, fontDescriptionId))
{
- item.characterSets = new CharacterSetList;
- }
-
- for(const auto& description : *(item.fallbackFonts))
- {
- item.characterSets->PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description)));
+ mCacheHandler->ValidateFont(font, fontDescriptionId);
}
+ familyList.erase(it);
}
}
-
- mDefaultFontDescriptionCached = true;
}
+}
+
+void FontClient::Plugin::InitDefaultFontDescription() const
+{
+ mCacheHandler->InitDefaultFontDescription();
+}
+
+void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& fontDescription) const
+{
+ DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- fontDescription.path = mDefaultFontDescription.path;
- fontDescription.family = mDefaultFontDescription.family;
- fontDescription.width = mDefaultFontDescription.width;
- fontDescription.weight = mDefaultFontDescription.weight;
- fontDescription.slant = mDefaultFontDescription.slant;
+ mCacheHandler->InitDefaultFontDescription();
+ fontDescription = mCacheHandler->mDefaultFontDescription;
FONT_LOG_DESCRIPTION(fontDescription, "");
}
-void FontClient::Plugin::GetSystemFonts(FontList& systemFonts)
+void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- if(mSystemFonts.empty())
- {
- InitSystemFonts();
- }
+ mCacheHandler->InitDefaultFonts();
+ defaultFonts = mCacheHandler->mDefaultFonts;
- systemFonts = mSystemFonts;
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : [%d]\n", mSystemFonts.size());
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of default fonts : [%d]\n", mCacheHandler->mDefaultFonts.size());
}
-void FontClient::Plugin::GetDescription(FontId id,
+void FontClient::Plugin::GetSystemFonts(FontList& systemFonts) const
+{
+ DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+ mCacheHandler->InitSystemFonts();
+ systemFonts = mCacheHandler->mSystemFonts;
+
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : [%d]\n", mCacheHandler->mSystemFonts.size());
+}
+
+void FontClient::Plugin::GetDescription(FontId fontId,
FontDescription& fontDescription) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", id);
- const FontId index = id - 1u;
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
- if((id > 0u) && (index < mFontIdCache.Count()))
+ if((fontId > 0u) && (fontId - 1u < mCacheHandler->mFontIdCache.size()))
{
- const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+ const auto& fontIdCacheItem = mCacheHandler->mFontIdCache[fontId - 1u];
switch(fontIdCacheItem.type)
{
case FontDescription::FACE_FONT:
{
- for(const auto& item : mFontDescriptionSizeCache)
+ for(const auto& item : mCacheHandler->mFontDescriptionSizeCache)
{
- if(item.fontId == fontIdCacheItem.id)
+ if(item.second == fontIdCacheItem.index)
{
- fontDescription = *(mFontDescriptionCache.begin() + item.validatedFontId - 1u);
+ fontDescription = *(mCacheHandler->mFontDescriptionCache.begin() + item.first.fontDescriptionId - 1u);
FONT_LOG_DESCRIPTION(fontDescription, "");
return;
case FontDescription::BITMAP_FONT:
{
fontDescription.type = FontDescription::BITMAP_FONT;
- fontDescription.family = mBitmapFontCache[fontIdCacheItem.id].font.name;
+ fontDescription.family = mCacheHandler->mBitmapFontCache[fontIdCacheItem.index].font.name;
break;
}
default:
}
}
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " No description found for the font ID %d\n", id);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " No description found for the font id %d\n", fontId);
}
-PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id)
+PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId fontId) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", id);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
- const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(id);
+ const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
if(fontCacheItem != nullptr)
{
pointSize = fontCacheItem->GetPointSize();
return pointSize;
}
-bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character)
+bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
return isSupported;
}
-const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId id) const
+const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId fontId) const
{
- const FontId index = id - 1u;
- if((id > 0u) && (index < mFontIdCache.Count()))
+ if((fontId > 0u) && (fontId - 1u < mCacheHandler->mFontIdCache.size()))
{
- const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index];
+ const auto& fontIdCacheItem = mCacheHandler->mFontIdCache[fontId - 1u];
switch(fontIdCacheItem.type)
{
case FontDescription::FACE_FONT:
{
- return &mFontFaceCache[fontIdCacheItem.id];
+ return &mCacheHandler->mFontFaceCache[fontIdCacheItem.index];
}
case FontDescription::BITMAP_FONT:
{
- return &mBitmapFontCache[fontIdCacheItem.id];
+ return &mCacheHandler->mBitmapFontCache[fontIdCacheItem.index];
}
default:
{
const CharacterSetList& characterSetList,
Character character,
PointSize26Dot6 requestedPointSize,
- bool preferColor)
+ bool preferColor) const
{
DALI_ASSERT_DEBUG((fontList.size() == characterSetList.Count()) && "FontClient::Plugin::FindFontForCharacter. Different number of fonts and character sets.");
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
if(preferColor)
{
- if((fontId > 0) &&
- (fontId - 1u < mFontIdCache.Count()))
+ if((fontId > 0) && (fontId - 1u < mCacheHandler->mFontIdCache.size()))
{
- const FontFaceCacheItem& item = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+ const FontFaceCacheItem& item = mCacheHandler->mFontFaceCache[mCacheHandler->mFontIdCache[fontId - 1u].index];
foundColor = item.mHasColorTables;
}
FontId FontClient::Plugin::FindDefaultFont(Character charcode,
PointSize26Dot6 requestedPointSize,
- bool preferColor)
+ bool preferColor) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor);
FontId fontId(0);
// Create the list of default fonts if it has not been created.
- if(mDefaultFonts.empty())
- {
- FontDescription fontDescription;
- fontDescription.family = DEFAULT_FONT_FAMILY_NAME;
- fontDescription.width = DefaultFontWidth();
- fontDescription.weight = DefaultFontWeight();
- fontDescription.slant = DefaultFontSlant();
-
- SetFontList(fontDescription, mDefaultFonts, mDefaultFontCharacterSets);
- }
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " number of default fonts : %d\n", mDefaultFonts.size());
+ mCacheHandler->InitDefaultFonts();
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " number of default fonts : %d\n", mCacheHandler->mDefaultFonts.size());
// Traverse the list of default fonts.
// Check for each default font if supports the character.
- fontId = FindFontForCharacter(mDefaultFonts, mDefaultFontCharacterSets, charcode, requestedPointSize, preferColor);
+ fontId = FindFontForCharacter(mCacheHandler->mDefaultFonts, mCacheHandler->mDefaultFontCharacterSets, charcode, requestedPointSize, preferColor);
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
return fontId;
FontId FontClient::Plugin::FindFallbackFont(Character charcode,
const FontDescription& preferredFontDescription,
PointSize26Dot6 requestedPointSize,
- bool preferColor)
+ bool preferColor) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor);
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_FIND_FALLBACKFONT");
+
// The font id to be returned.
FontId fontId = 0u;
FontDescription fontDescription;
// Fill the font description with the preferred font description and complete with the defaults.
- fontDescription.family = preferredFontDescription.family.empty() ? DEFAULT_FONT_FAMILY_NAME : preferredFontDescription.family;
+ fontDescription.family = preferredFontDescription.family.empty() ? DefaultFontFamily() : preferredFontDescription.family;
fontDescription.weight = ((FontWeight::NONE == preferredFontDescription.weight) ? DefaultFontWeight() : preferredFontDescription.weight);
fontDescription.width = ((FontWidth::NONE == preferredFontDescription.width) ? DefaultFontWidth() : preferredFontDescription.width);
fontDescription.slant = ((FontSlant::NONE == preferredFontDescription.slant) ? DefaultFontSlant() : preferredFontDescription.slant);
DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " [%s] --> [%s]\n", FontWidth::Name[preferredFontDescription.width], FontWidth::Name[fontDescription.width]);
DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " [%s] --> [%s]\n", FontSlant::Name[preferredFontDescription.slant], FontSlant::Name[fontDescription.slant]);
+#if defined(TRACE_ENABLED)
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+ {
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_FIND_FALLBACKFONT : %s -> %s\n", preferredFontDescription.family.c_str(), fontDescription.family.c_str());
+ }
+#endif
+
// Check first if the font's description has been queried before.
FontList* fontList = nullptr;
CharacterSetList* characterSetList = nullptr;
- if(!FindFallbackFontList(fontDescription, fontList, characterSetList))
+ if(!mCacheHandler->FindFallbackFontList(fontDescription, fontList, characterSetList))
{
- fontList = new FontList;
- characterSetList = new CharacterSetList;
-
- SetFontList(fontDescription, *fontList, *characterSetList);
-#ifdef __APPLE__
- FontDescription appleColorEmoji;
- appleColorEmoji.family = "Apple Color Emoji";
- appleColorEmoji.width = fontDescription.width;
- appleColorEmoji.weight = fontDescription.weight;
- appleColorEmoji.slant = fontDescription.slant;
- FontList emojiFontList;
- CharacterSetList emojiCharSetList;
- SetFontList(appleColorEmoji, emojiFontList, emojiCharSetList);
-
- std::move(fontList->begin(), fontList->end(), std::back_inserter(emojiFontList));
- emojiCharSetList.Insert(emojiCharSetList.End(), characterSetList->Begin(), characterSetList->End());
- *fontList = std::move(emojiFontList);
- *characterSetList = std::move(emojiCharSetList);
-#endif
-
- // Add the font-list to the cache.
- mFallbackCache.push_back(std::move(FallbackCacheItem(std::move(fontDescription), fontList, characterSetList)));
+ mCacheHandler->CacheFallbackFontList(std::move(fontDescription), fontList, characterSetList);
}
if(fontList && characterSetList)
return fontId;
}
-FontId FontClient::Plugin::GetFontId(const FontPath& path,
- PointSize26Dot6 requestedPointSize,
- FaceIndex faceIndex,
- bool cacheDescription)
+FontId FontClient::Plugin::GetFontIdByPath(const FontPath& path,
+ PointSize26Dot6 requestedPointSize,
+ FaceIndex faceIndex,
+ bool cacheDescription) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " path : [%s]\n", path.c_str());
if(nullptr != mFreeTypeLibrary)
{
FontId foundId = 0u;
- if(FindFont(path, requestedPointSize, faceIndex, foundId))
+ if(mCacheHandler->FindFontByPath(path, requestedPointSize, faceIndex, foundId))
{
id = foundId;
}
FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription,
PointSize26Dot6 requestedPointSize,
- FaceIndex faceIndex)
+ FaceIndex faceIndex) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
FONT_LOG_DESCRIPTION(fontDescription, "");
+
+ // Special case when font Description don't have family information.
+ // In this case, we just use default description family and path.
+ const FontDescription& realFontDescription = fontDescription.family.empty() ? FontDescription(mCacheHandler->mDefaultFontDescription.path,
+ mCacheHandler->mDefaultFontDescription.family,
+ fontDescription.width,
+ fontDescription.weight,
+ fontDescription.slant,
+ fontDescription.type)
+ : fontDescription;
+
+ FONT_LOG_DESCRIPTION(realFontDescription, "");
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize);
// This method uses three vectors which caches:
FontId fontId = 0u;
// Check first if the font description matches with a previously loaded bitmap font.
- if(FindBitmapFont(fontDescription.family, fontId))
+ if(mCacheHandler->FindBitmapFont(realFontDescription.family, fontId))
{
return fontId;
}
// Check if the font's description have been validated before.
- FontDescriptionId validatedFontId = 0u;
+ FontDescriptionId fontDescriptionId = 0u;
- if(!FindValidatedFont(fontDescription,
- validatedFontId))
+ if(!mCacheHandler->FindValidatedFont(realFontDescription, fontDescriptionId))
{
// Use font config to validate the font's description.
- ValidateFont(fontDescription,
- validatedFontId);
+ mCacheHandler->ValidateFont(realFontDescription, fontDescriptionId);
}
- FontId fontFaceId = 0u;
- // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
- if(!FindFont(validatedFontId, requestedPointSize, fontFaceId))
+ using FontCacheIndex = CacheHandler::FontCacheIndex;
+ FontCacheIndex fontCacheIndex = 0u;
+ // Check if exists a pair 'fontDescriptionId, requestedPointSize' in the cache.
+ if(!mCacheHandler->FindFont(fontDescriptionId, requestedPointSize, fontCacheIndex))
{
- // Retrieve the font file name path.
- const FontDescription& description = *(mFontDescriptionCache.begin() + validatedFontId - 1u);
-
- // Retrieve the font id. Do not cache the description as it has been already cached.
- fontId = GetFontId(description.path,
- requestedPointSize,
- faceIndex,
- false);
-
- fontFaceId = mFontIdCache[fontId - 1u].id;
- mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(mCharacterSetCache[validatedFontId - 1u]);
-
- // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
- mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
- requestedPointSize,
- fontFaceId));
+ if(fontDescriptionId > 0u && fontDescriptionId <= mCacheHandler->mCharacterSetCache.Count())
+ {
+ // Retrieve the font file name path.
+ const FontDescription& description = *(mCacheHandler->mFontDescriptionCache.begin() + fontDescriptionId - 1u);
+
+ // Retrieve the font id. Do not cache the description as it has been already cached.
+ // Note : CacheFontPath() API call ValidateFont() + setup CharacterSet + cache the font description.
+ // So set cacheDescription=false, that we don't call CacheFontPath().
+ fontId = GetFontIdByPath(description.path, requestedPointSize, faceIndex, false);
+
+ if((fontId > 0u) && (fontId - 1u < mCacheHandler->mFontIdCache.size()))
+ {
+ fontCacheIndex = mCacheHandler->mFontIdCache[fontId - 1u].index;
+ mCacheHandler->mFontFaceCache[fontCacheIndex].mCharacterSet = FcCharSetCopy(mCacheHandler->mCharacterSetCache[fontDescriptionId - 1u]);
+
+ // Cache the pair 'fontDescriptionId, requestedPointSize' to improve the following queries.
+ mCacheHandler->CacheFontDescriptionSize(fontDescriptionId, requestedPointSize, fontCacheIndex);
+ }
+ }
}
else
{
- fontId = mFontFaceCache[fontFaceId].mFontId + 1u;
+ fontId = mCacheHandler->mFontFaceCache[fontCacheIndex].mFontId + 1u;
}
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
return fontId;
}
-FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont)
+FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont) const
{
- for(const auto& item : mBitmapFontCache)
- {
- if(bitmapFont.name == item.font.name)
- {
- return item.id + 1u;
- }
- }
-
- BitmapFontCacheItem bitmapFontCacheItem(bitmapFont, mFontIdCache.Count());
-
- FontIdCacheItem fontIdCacheItem;
- fontIdCacheItem.type = FontDescription::BITMAP_FONT;
- fontIdCacheItem.id = mBitmapFontCache.size();
-
- mBitmapFontCache.push_back(std::move(bitmapFontCacheItem));
- mFontIdCache.PushBack(fontIdCacheItem);
-
- return bitmapFontCacheItem.id + 1u;
-}
-
-void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription,
- FontDescriptionId& validatedFontId)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- FONT_LOG_DESCRIPTION(fontDescription, "");
-
- // Create a font pattern.
- FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription);
-
- FontDescription description;
-
- FcCharSet* characterSet = nullptr;
- bool matched = MatchFontDescriptionToPattern(fontFamilyPattern, description, &characterSet);
- FcPatternDestroy(fontFamilyPattern);
-
- if(matched && (nullptr != characterSet))
+ // The font id to be returned.
+ FontId fontId = 0u;
+ if(!mCacheHandler->FindBitmapFont(bitmapFont.name, fontId))
{
- // Add the path to the cache.
- description.type = FontDescription::FACE_FONT;
- mFontDescriptionCache.push_back(description);
-
- // Set the index to the vector of paths to font file names.
- validatedFontId = mFontDescriptionCache.size();
-
- FONT_LOG_DESCRIPTION(description, "matched");
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " validatedFontId : %d\n", validatedFontId);
-
- // The reference counter of the character set has already been increased in MatchFontDescriptionToPattern.
- mCharacterSetCache.PushBack(characterSet);
-
- // Cache the index and the matched font's description.
- FontDescriptionCacheItem item(description,
- validatedFontId);
+ BitmapFontCacheItem bitmapFontCacheItem(bitmapFont);
- mValidatedFontCache.push_back(std::move(item));
-
- if((fontDescription.family != description.family) ||
- (fontDescription.width != description.width) ||
- (fontDescription.weight != description.weight) ||
- (fontDescription.slant != description.slant))
- {
- // Cache the given font's description if it's different than the matched.
- FontDescriptionCacheItem item(fontDescription,
- validatedFontId);
-
- mValidatedFontCache.push_back(std::move(item));
- }
- }
- else
- {
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font validation failed for font [%s]\n", fontDescription.family.c_str());
+ fontId = mCacheHandler->CacheBitmapFontCacheItem(std::move(bitmapFontCacheItem));
}
+ return fontId;
}
void FontClient::Plugin::GetFontMetrics(FontId fontId,
- FontMetrics& metrics)
+ FontMetrics& metrics) const
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
if(fontCacheItem != nullptr)
}
GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId,
- Character charcode)
+ Character charcode) const
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
if(fontCacheItem != nullptr)
GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId,
Character charcode,
- Character variantSelector)
+ Character variantSelector) const
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
if(fontCacheItem != nullptr)
bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array,
uint32_t size,
GlyphType type,
- bool horizontal)
+ bool horizontal) const
{
if(VECTOR_GLYPH == type)
{
bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array,
uint32_t size,
- bool horizontal)
+ bool horizontal) const
{
- bool success(false);
+ bool success(size > 0u);
for(unsigned int i = 0; i < size; ++i)
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(glyph.fontId);
if(fontCacheItem != nullptr)
{
- success = fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal);
+ success &= fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal);
}
// Check if it's an embedded image.
- else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count()))
+ else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mCacheHandler->mEmbeddedItemCache.size()))
{
- mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph);
- success = true;
+ mCacheHandler->mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph);
+ }
+ else
+ {
+ success = false;
}
}
bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
uint32_t size,
- bool horizontal)
+ bool horizontal) const
{
#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
bool success(true);
FontId fontId = array[i].fontId;
if((fontId > 0u) &&
- (fontId - 1u) < mFontIdCache.Count())
+ (fontId - 1u) < mCacheHandler->mFontIdCache.size())
{
- FontFaceCacheItem& font = mFontFaceCache[mFontIdCache[fontId - 1u].id];
+ FontFaceCacheItem& font = mCacheHandler->mFontFaceCache[mCacheHandler->mFontIdCache[fontId - 1u].index];
if(!font.mVectorFontId)
{
#endif
}
-void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth) const
{
data.isColorBitmap = false;
data.isColorEmoji = false;
{
fontCacheItem->CreateBitmap(glyphIndex, data, outlineWidth, isItalicRequired, isBoldRequired);
}
- else if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count()))
+ else if((0u != glyphIndex) && (glyphIndex <= mCacheHandler->mEmbeddedItemCache.size()))
{
// It's an embedded item.
- mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mPixelBufferCache, data);
+ mCacheHandler->mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mCacheHandler->mPixelBufferCache, data);
}
}
-PixelData FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, int outlineWidth)
+PixelData FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, int outlineWidth) const
{
- TextAbstraction::FontClient::GlyphBufferData data;
+ TextAbstraction::GlyphBufferData data;
CreateBitmap(fontId, glyphIndex, false, false, data, outlineWidth);
+ // If data is compressed or not owned buffer, copy this.
+ if(!data.isBufferOwned || data.compressionType != TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION)
+ {
+ uint8_t* newBuffer = (uint8_t*)malloc(data.width * data.height * Pixel::GetBytesPerPixel(data.format));
+ if(DALI_UNLIKELY(!newBuffer))
+ {
+ DALI_LOG_ERROR("malloc is failed. request malloc size : %u x %u x %u\n", data.width, data.height, Pixel::GetBytesPerPixel(data.format));
+ return Dali::PixelData();
+ }
+
+ TextAbstraction::GlyphBufferData::Decompress(data, newBuffer);
+ if(data.isBufferOwned)
+ {
+ free(data.buffer);
+ }
+
+ data.buffer = newBuffer;
+ data.isBufferOwned = true;
+ data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
+ }
+
return PixelData::New(data.buffer,
data.width * data.height * Pixel::GetBytesPerPixel(data.format),
data.width,
data.height,
data.format,
- PixelData::DELETE_ARRAY);
+ PixelData::FREE);
}
-void FontClient::Plugin::CreateVectorBlob(FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight)
+void FontClient::Plugin::CreateVectorBlob(FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight) const
{
blob = nullptr;
blobLength = 0;
#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
if((fontId > 0u) &&
- (fontId - 1u < mFontIdCache.Count()))
+ (fontId - 1u < mCacheHandler->mFontIdCache.size()))
{
- const FontId fontFaceId = mFontIdCache[fontId - 1u].id;
- FontFaceCacheItem& font = mFontFaceCache[fontFaceId];
+ using FontCacheIndex = CacheHandler::FontCacheIndex;
+ const FontCacheIndex fontCacheIndex = mCacheHandler->mFontIdCache[fontId - 1u].index;
+ FontFaceCacheItem& font = mCacheHandler->mFontFaceCache[fontCacheIndex];
if(!font.mVectorFontId)
{
font.mVectorFontId = mVectorFontCache->GetFontId(font.mPath);
}
- mVectorFontCache->GetVectorBlob(font.mVectorFontId, fontFaceId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight);
+ mVectorFontCache->GetVectorBlob(font.mVectorFontId, fontCacheIndex, glyphIndex, blob, blobLength, nominalWidth, nominalHeight);
}
#endif
}
-const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedPointSize)
+const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedPointSize) const
{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize %d.\n", requestedPointSize);
+ using EllipsisCacheIndex = CacheHandler::EllipsisCacheIndex;
+ using EllipsisItem = CacheHandler::EllipsisItem;
+ EllipsisCacheIndex ellipsisCacheIndex = 0u;
- // First look into the cache if there is an ellipsis glyph for the requested point size.
- for(const auto& item : mEllipsisCache)
+ if(!mCacheHandler->FindEllipsis(requestedPointSize, ellipsisCacheIndex))
{
- if(item.requestedPointSize == requestedPointSize)
- {
- // Use the glyph in the cache.
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " glyph id %d found in the cache.\n", item.glyph.index);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font %d.\n", item.glyph.fontId);
- return item.glyph;
- }
- }
+ // No glyph has been found. Create one.
+ EllipsisItem item;
- // No glyph has been found. Create one.
- mEllipsisCache.PushBack(EllipsisItem());
- EllipsisItem& item = *(mEllipsisCache.End() - 1u);
+ item.requestedPointSize = requestedPointSize;
- item.requestedPointSize = requestedPointSize;
+ // Find a font for the ellipsis glyph.
+ item.glyph.fontId = FindDefaultFont(ELLIPSIS_CHARACTER,
+ requestedPointSize,
+ false);
- // Find a font for the ellipsis glyph.
- item.glyph.fontId = FindDefaultFont(ELLIPSIS_CHARACTER,
- requestedPointSize,
- false);
+ // Set the character index to access the glyph inside the font.
+ item.glyph.index = GetGlyphIndex(item.glyph.fontId, ELLIPSIS_CHARACTER);
- // Set the character index to access the glyph inside the font.
- item.glyph.index = FT_Get_Char_Index(mFontFaceCache[mFontIdCache[item.glyph.fontId - 1u].id].mFreeTypeFace,
- ELLIPSIS_CHARACTER);
+ // Get glyph informations.
+ GetBitmapMetrics(&item.glyph, 1u, true);
- GetBitmapMetrics(&item.glyph, 1u, true);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " glyph id %d found in the cache.\n", item.glyph.index);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font %d.\n", item.glyph.fontId);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " glyph id %d found in the cache.\n", item.glyph.index);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font %d.\n", item.glyph.fontId);
- return item.glyph;
+ // EllipsisCacheIndex is stored in item.index.
+ ellipsisCacheIndex = mCacheHandler->CacheEllipsis(std::move(item));
+ if(!mCacheHandler->mEllipsisCache.empty())
+ {
+ mCacheHandler->mEllipsisCache.back().index = ellipsisCacheIndex;
+ }
+ }
+ return mCacheHandler->mEllipsisCache[ellipsisCacheIndex].glyph;
}
-bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex)
+bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex) const
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
return fontCacheItem && fontCacheItem->IsColorGlyph(glyphIndex);
}
-FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId)
+FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId) const
{
const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId);
if(fontCacheItem != nullptr)
return nullptr;
}
-FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId)
+FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId) const
{
const FontId index = fontId - 1u;
- if((fontId > 0u) &&
- (index < mFontIdCache.Count()))
+ if((fontId > 0u) && (index < mCacheHandler->mFontIdCache.size()))
{
- return mFontIdCache[index].type;
+ return mCacheHandler->mFontIdCache[index].type;
}
return FontDescription::INVALID;
}
return FcConfigAppFontAddDir(nullptr, reinterpret_cast<const FcChar8*>(path.c_str()));
}
-GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat)
+HarfBuzzFontHandle FontClient::Plugin::GetHarfBuzzFont(FontId fontId) const
+{
+ FontCacheItemInterface* fontCacheItem = const_cast<FontCacheItemInterface*>(GetCachedFontItem(fontId));
+ if(fontCacheItem != nullptr)
+ {
+ return fontCacheItem->GetHarfBuzzFont(mDpiHorizontal, mDpiVertical); // May cache
+ }
+ return nullptr;
+}
+
+GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat) const
{
EmbeddedItem embeddedItem;
if(!description.url.empty())
{
// Check if the url is in the cache.
- PixelBufferId index = 0u;
-
- for(const auto& cacheItem : mPixelBufferCache)
- {
- ++index;
- if(cacheItem.url == description.url)
- {
- // The url is in the pixel buffer cache.
- // Set the index +1 to the vector.
- embeddedItem.pixelBufferId = index;
- break;
- }
- }
-
Devel::PixelBuffer pixelBuffer;
- if(0u == embeddedItem.pixelBufferId)
+ if(!mCacheHandler->FindEmbeddedPixelBufferId(description.url, embeddedItem.pixelBufferId))
{
// The pixel buffer is not in the cache. Create one and cache it.
-
- // Load the image from the url.
- pixelBuffer = LoadImageFromFile(description.url);
-
- // Create the cache item.
- PixelBufferCacheItem pixelBufferCacheItem;
- pixelBufferCacheItem.pixelBuffer = pixelBuffer;
- pixelBufferCacheItem.url = description.url;
-
- // Store the cache item in the cache.
- mPixelBufferCache.push_back(std::move(pixelBufferCacheItem));
-
- // Set the pixel buffer id to the embedded item.
- embeddedItem.pixelBufferId = mPixelBufferCache.size();
+ embeddedItem.pixelBufferId = mCacheHandler->CacheEmbeddedPixelBuffer(description.url);
}
- else
+
+ if((embeddedItem.pixelBufferId > 0u) && (embeddedItem.pixelBufferId - 1u) < mCacheHandler->mPixelBufferCache.size())
{
// Retrieve the pixel buffer from the cache to set the pixel format.
- pixelBuffer = mPixelBufferCache[embeddedItem.pixelBufferId - 1u].pixelBuffer;
+ pixelBuffer = mCacheHandler->mPixelBufferCache[embeddedItem.pixelBufferId - 1u].pixelBuffer;
}
if(pixelBuffer)
}
// Find if the same embeddedItem has already been created.
- unsigned int index = 0u;
- for(const auto& item : mEmbeddedItemCache)
+ GlyphIndex index = 0u;
+ if(!mCacheHandler->FindEmbeddedItem(embeddedItem.pixelBufferId, embeddedItem.width, embeddedItem.height, index))
{
- ++index;
- if((item.pixelBufferId == embeddedItem.pixelBufferId) &&
- (item.width == embeddedItem.width) &&
- (item.height == embeddedItem.height))
- {
- return index;
- }
+ index = mCacheHandler->CacheEmbeddedItem(std::move(embeddedItem));
}
-
- // Cache the embedded item.
- mEmbeddedItemCache.PushBack(embeddedItem);
-
- return mEmbeddedItemCache.Count();
+ return index;
}
void FontClient::Plugin::EnableAtlasLimitation(bool enabled)
uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
{
return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
- ;
}
-void FontClient::Plugin::InitSystemFonts()
+FontId FontClient::Plugin::CreateFont(const FontPath& path,
+ PointSize26Dot6 requestedPointSize,
+ FaceIndex faceIndex,
+ bool cacheDescription) const
{
DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " path : [%s]\n", path.c_str());
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize);
- FcFontSet* fontSet = GetFcFontSet(); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_CREATE_FONT");
- if(fontSet)
- {
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : %d\n", fontSet->nfont);
+ FontId fontId = 0u;
+ FT_Face ftFace;
+ FT_Error error;
- // Reserve some space to avoid reallocations.
- mSystemFonts.reserve(fontSet->nfont);
+ uint8_t* fontDataPtr = nullptr;
+ std::streampos dataSize = 0;
+ bool fontDataFound = mCacheHandler->FindFontData(path, fontDataPtr, dataSize);
- for(int i = 0u; i < fontSet->nfont; ++i)
+ if(fontDataFound)
+ {
+ // Create & cache new font face from pre-loaded font
+ error = FT_New_Memory_Face(mFreeTypeLibrary, reinterpret_cast<FT_Byte*>(fontDataPtr), static_cast<FT_Long>(dataSize), 0, &ftFace);
+#if defined(TRACE_ENABLED)
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
{
- FcPattern* fontPattern = fontSet->fonts[i];
-
- FontPath path;
-
- // Skip fonts with no path
- if(GetFcString(fontPattern, FC_FILE, path))
- {
- mSystemFonts.push_back(FontDescription());
- FontDescription& fontDescription = mSystemFonts.back();
-
- fontDescription.path = std::move(path);
-
- int width = 0;
- int weight = 0;
- int slant = 0;
- GetFcString(fontPattern, FC_FAMILY, fontDescription.family);
- GetFcInt(fontPattern, FC_WIDTH, width);
- GetFcInt(fontPattern, FC_WEIGHT, weight);
- GetFcInt(fontPattern, FC_SLANT, slant);
- fontDescription.width = IntToWidthType(width);
- fontDescription.weight = IntToWeightType(weight);
- fontDescription.slant = IntToSlantType(slant);
-
- FONT_LOG_DESCRIPTION(fontDescription, "");
- }
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_CREATE_FONT : FT_New_Memory_Face : %s\n", path.c_str());
}
-
- // Destroys the font set created.
- FcFontSetDestroy(fontSet);
- }
-}
-
-bool FontClient::Plugin::MatchFontDescriptionToPattern(FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
-
- FcResult result = FcResultMatch;
- FcPattern* match = FcFontMatch(nullptr /* use default configure */, pattern, &result); // Creates a new font pattern that needs to be destroyed by calling FcPatternDestroy.
-
- const bool matched = nullptr != match;
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " pattern matched : %s\n", (matched ? "true" : "false"));
-
- if(matched)
- {
- int width = 0;
- int weight = 0;
- int slant = 0;
- GetFcString(match, FC_FILE, fontDescription.path);
- GetFcString(match, FC_FAMILY, fontDescription.family);
- GetFcInt(match, FC_WIDTH, width);
- GetFcInt(match, FC_WEIGHT, weight);
- GetFcInt(match, FC_SLANT, slant);
- fontDescription.width = IntToWidthType(width);
- fontDescription.weight = IntToWeightType(weight);
- fontDescription.slant = IntToSlantType(slant);
-
- // Retrieve the character set and increase the reference counter.
- FcPatternGetCharSet(match, FC_CHARSET, 0u, characterSet);
- *characterSet = FcCharSetCopy(*characterSet);
-
- // destroyed the matched pattern
- FcPatternDestroy(match);
- FONT_LOG_DESCRIPTION(fontDescription, "");
+#endif
}
- return matched;
-}
-
-_FcFontSet* FontClient::Plugin::GetFcFontSet() const
-{
- FcFontSet* fontset = nullptr;
-
- // create a new pattern.
- // a pattern holds a set of names, each name refers to a property of the font
- FcPattern* pattern = FcPatternCreate();
-
- if(nullptr != pattern)
+ else
{
- // create an object set used to define which properties are to be returned in the patterns from FcFontList.
- FcObjectSet* objectSet = FcObjectSetCreate();
-
- if(nullptr != objectSet)
+ // Create & cache new font face
+ error = FT_New_Face(mFreeTypeLibrary, path.c_str(), 0, &ftFace);
+#if defined(TRACE_ENABLED)
+ if(gTraceFilter && gTraceFilter->IsTraceEnabled())
{
- // build an object set from a list of property names
- FcObjectSetAdd(objectSet, FC_FILE);
- FcObjectSetAdd(objectSet, FC_FAMILY);
- FcObjectSetAdd(objectSet, FC_WIDTH);
- FcObjectSetAdd(objectSet, FC_WEIGHT);
- FcObjectSetAdd(objectSet, FC_SLANT);
-
- // get a list of fonts
- // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
- fontset = FcFontList(nullptr /* the default configuration is checked to be up to date, and used */, pattern, objectSet); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy.
-
- // clear up the object set
- FcObjectSetDestroy(objectSet);
+ DALI_LOG_DEBUG_INFO("DALI_TEXT_CREATE_FONT : FT_New_Face : %s\n", path.c_str());
}
-
- // clear up the pattern
- FcPatternDestroy(pattern);
- }
-
- return fontset;
-}
-
-bool FontClient::Plugin::GetFcString(const FcPattern* const pattern,
- const char* const n,
- std::string& string)
-{
- FcChar8* file = nullptr;
- const FcResult retVal = FcPatternGetString(pattern, n, 0u, &file);
-
- if(FcResultMatch == retVal)
- {
- // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
- string.assign(reinterpret_cast<const char*>(file));
-
- return true;
- }
-
- return false;
-}
-
-bool FontClient::Plugin::GetFcInt(const _FcPattern* const pattern, const char* const n, int& intVal)
-{
- const FcResult retVal = FcPatternGetInteger(pattern, n, 0u, &intVal);
-
- if(FcResultMatch == retVal)
- {
- return true;
+#endif
}
- return false;
-}
-
-FontId FontClient::Plugin::CreateFont(const FontPath& path,
- PointSize26Dot6 requestedPointSize,
- FaceIndex faceIndex,
- bool cacheDescription)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " path : [%s]\n", path.c_str());
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize);
-
- FontId id = 0u;
-
- // Create & cache new font face
- FT_Face ftFace;
- int error = FT_New_Face(mFreeTypeLibrary,
- path.c_str(),
- 0,
- &ftFace);
-
if(FT_Err_Ok == error)
{
// Check if a font is scalable.
const bool isScalable = (0 != (ftFace->face_flags & FT_FACE_FLAG_SCALABLE));
const bool hasFixedSizedBitmaps = (0 != (ftFace->face_flags & FT_FACE_FLAG_FIXED_SIZES)) && (0 != ftFace->num_fixed_sizes);
const bool hasColorTables = (0 != (ftFace->face_flags & FT_FACE_FLAG_COLOR));
- FontId fontFaceId = 0u;
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " isScalable : [%s]\n", (isScalable ? "true" : "false"));
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " hasFixedSizedBitmaps : [%s]\n", (hasFixedSizedBitmaps ? "true" : "false"));
int fixedSizeIndex = 0;
for(; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex)
{
- const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size;
+ const PointSize26Dot6 fixedSize = static_cast<PointSize26Dot6>(ftFace->available_sizes[fixedSizeIndex].size);
DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " size index : %d, size : %d\n", fixedSizeIndex, fixedSize);
if(fixedSize >= requestedPointSize)
{
// The requested point size is bigger than the bigest fixed size.
fixedSizeIndex = ftFace->num_fixed_sizes - 1;
- actualPointSize = ftFace->available_sizes[fixedSizeIndex].size;
+ actualPointSize = static_cast<PointSize26Dot6>(ftFace->available_sizes[fixedSizeIndex].size);
}
DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize);
}
else
{
+ FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
+
+ FontMetrics metrics(static_cast<float>(ftMetrics.ascender) * FROM_266,
+ static_cast<float>(ftMetrics.descender) * FROM_266,
+ static_cast<float>(ftMetrics.height) * FROM_266,
+ static_cast<float>(ftFace->underline_position) * FROM_266,
+ static_cast<float>(ftFace->underline_thickness) * FROM_266);
+
const float fixedWidth = static_cast<float>(ftFace->available_sizes[fixedSizeIndex].width);
const float fixedHeight = static_cast<float>(ftFace->available_sizes[fixedSizeIndex].height);
- // Indicate that the font is a fixed sized bitmap
- FontMetrics metrics(fixedHeight, // The ascender in pixels.
- 0.0f,
- fixedHeight, // The height in pixels.
- 0.0f,
- 0.0f);
-
// Create the FreeType font face item to cache.
- FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
-
- // Set the index to the font's id cache.
- fontFaceCacheItem.mFontId = mFontIdCache.Count();
+ FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, mCacheHandler->GetGlyphCacheManager(), path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables);
- // Create the font id item to cache.
- FontIdCacheItem fontIdCacheItem;
- fontIdCacheItem.type = FontDescription::FACE_FONT;
-
- // Set the index to the FreeType font face cache.
- fontIdCacheItem.id = mFontFaceCache.size();
- fontFaceId = fontIdCacheItem.id + 1u;
-
- // Cache the items.
- mFontFaceCache.push_back(fontFaceCacheItem);
- mFontIdCache.PushBack(fontIdCacheItem);
-
- // Set the font id to be returned.
- id = mFontIdCache.Count();
+ fontId = mCacheHandler->CacheFontFaceCacheItem(std::move(fontFaceCacheItem));
}
}
else
{
error = FT_Set_Char_Size(ftFace,
0,
- requestedPointSize,
+ FT_F26Dot6(requestedPointSize),
mDpiHorizontal,
mDpiVertical);
}
static_cast<float>(ftFace->underline_thickness) * FROM_266);
// Create the FreeType font face item to cache.
- FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics);
-
- // Set the index to the font's id cache.
- fontFaceCacheItem.mFontId = mFontIdCache.Count();
-
- // Create the font id item to cache.
- FontIdCacheItem fontIdCacheItem;
- fontIdCacheItem.type = FontDescription::FACE_FONT;
-
- // Set the index to the FreeType font face cache.
- fontIdCacheItem.id = mFontFaceCache.size();
- fontFaceId = fontIdCacheItem.id + 1u;
+ FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, mCacheHandler->GetGlyphCacheManager(), path, requestedPointSize, faceIndex, metrics);
- // Cache the items.
- mFontFaceCache.push_back(fontFaceCacheItem);
- mFontIdCache.PushBack(fontIdCacheItem);
-
- // Set the font id to be returned.
- id = mFontIdCache.Count();
+ fontId = mCacheHandler->CacheFontFaceCacheItem(std::move(fontFaceCacheItem));
}
else
{
}
}
- if(0u != fontFaceId)
+ if(0u != fontId)
{
if(cacheDescription)
{
- CacheFontPath(ftFace, fontFaceId, requestedPointSize, path);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Cache Font Path at font id : %d [%s]\n", fontId, path.c_str());
+ mCacheHandler->CacheFontPath(ftFace, fontId, requestedPointSize, path);
}
}
}
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " FreeType New_Face error: %d for [%s]\n", error, path.c_str());
}
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", id);
- return id;
-}
-
-bool FontClient::Plugin::FindFont(const FontPath& path,
- PointSize26Dot6 requestedPointSize,
- FaceIndex faceIndex,
- FontId& fontId) const
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " path : [%s]\n", path.c_str());
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " number of fonts in the cache : %d\n", mFontFaceCache.size());
-
- fontId = 0u;
- for(const auto& cacheItem : mFontFaceCache)
- {
- if(cacheItem.mRequestedPointSize == requestedPointSize &&
- cacheItem.mFaceIndex == faceIndex &&
- cacheItem.mPath == path)
- {
- fontId = cacheItem.mFontId + 1u;
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font found, id : %d\n", fontId);
- return true;
- }
- }
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font not found\n");
- return false;
-}
-
-bool FontClient::Plugin::FindValidatedFont(const FontDescription& fontDescription,
- FontDescriptionId& validatedFontId)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- FONT_LOG_DESCRIPTION(fontDescription, "");
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " number of validated fonts in the cache : %d\n", mValidatedFontCache.size());
-
- validatedFontId = 0u;
-
- for(const auto& item : mValidatedFontCache)
- {
- if(!fontDescription.family.empty() &&
- (fontDescription.family == item.fontDescription.family) &&
- (fontDescription.width == item.fontDescription.width) &&
- (fontDescription.weight == item.fontDescription.weight) &&
- (fontDescription.slant == item.fontDescription.slant))
- {
- validatedFontId = item.index;
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " validated font found, id : %d\n", validatedFontId);
- return true;
- }
- }
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " validated font not found\n");
- return false;
-}
-
-bool FontClient::Plugin::FindFallbackFontList(const FontDescription& fontDescription,
- FontList*& fontList,
- CharacterSetList*& characterSetList)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- FONT_LOG_DESCRIPTION(fontDescription, "");
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " number of fallback font lists in the cache : %d\n", mFallbackCache.size());
-
- fontList = nullptr;
-
- for(const auto& item : mFallbackCache)
- {
- if(!fontDescription.family.empty() &&
- (fontDescription.family == item.fontDescription.family) &&
- (fontDescription.width == item.fontDescription.width) &&
- (fontDescription.weight == item.fontDescription.weight) &&
- (fontDescription.slant == item.fontDescription.slant))
- {
- fontList = item.fallbackFonts;
- characterSetList = item.characterSets;
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " fallback font list found.\n");
- return true;
- }
- }
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " fallback font list not found.\n");
- return false;
-}
-
-bool FontClient::Plugin::FindFont(FontDescriptionId validatedFontId,
- PointSize26Dot6 requestedPointSize,
- FontId& fontId)
-{
- DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " validatedFontId : %d\n", validatedFontId);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize);
-
- fontId = 0u;
-
- for(const auto& item : mFontDescriptionSizeCache)
- {
- if((validatedFontId == item.validatedFontId) &&
- (requestedPointSize == item.requestedPointSize))
- {
- fontId = item.fontId;
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font found, id : %d\n", fontId);
- return true;
- }
- }
-
- DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font not found.\n");
- return false;
-}
-
-bool FontClient::Plugin::FindBitmapFont(const FontFamily& bitmapFont, FontId& fontId) const
-{
- fontId = 0u;
-
- for(const auto& item : mBitmapFontCache)
- {
- if(bitmapFont == item.font.name)
- {
- fontId = item.id + 1u;
- return true;
- }
- }
-
- return false;
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId);
+ return fontId;
}
-bool FontClient::Plugin::IsScalable(const FontPath& path)
+bool FontClient::Plugin::IsScalable(const FontPath& path) const
{
bool isScalable = false;
- FT_Face ftFace;
- int error = FT_New_Face(mFreeTypeLibrary,
+ FT_Face ftFace = nullptr;
+ int error = FT_New_Face(mFreeTypeLibrary,
path.c_str(),
0,
&ftFace);
isScalable = ftFace->face_flags & FT_FACE_FLAG_SCALABLE;
}
+ if(ftFace)
+ {
+ FT_Done_Face(ftFace);
+ }
+
return isScalable;
}
-bool FontClient::Plugin::IsScalable(const FontDescription& fontDescription)
+bool FontClient::Plugin::IsScalable(const FontDescription& fontDescription) const
{
// Create a font pattern.
FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
return isScalable;
}
-void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector<PointSize26Dot6>& sizes)
+void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector<PointSize26Dot6>& sizes) const
{
// Empty the caller container
sizes.Clear();
- FT_Face ftFace;
- int error = FT_New_Face(mFreeTypeLibrary,
+ FT_Face ftFace = nullptr;
+ int error = FT_New_Face(mFreeTypeLibrary,
path.c_str(),
0,
&ftFace);
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font path : [%s]\n", path.c_str());
}
- // Fetch the number of fixed sizes available
- if(ftFace->num_fixed_sizes && ftFace->available_sizes)
+ if(ftFace)
{
- for(int i = 0; i < ftFace->num_fixed_sizes; ++i)
+ // Fetch the number of fixed sizes available
+ if(ftFace->num_fixed_sizes && ftFace->available_sizes)
{
- sizes.PushBack(ftFace->available_sizes[i].size);
+ for(int i = 0; i < ftFace->num_fixed_sizes; ++i)
+ {
+ sizes.PushBack(ftFace->available_sizes[i].size);
+ }
}
+
+ FT_Done_Face(ftFace);
}
}
void FontClient::Plugin::GetFixedSizes(const FontDescription& fontDescription,
- Vector<PointSize26Dot6>& sizes)
+ Vector<PointSize26Dot6>& sizes) const
{
// Create a font pattern.
FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy.
return false;
}
-void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path)
-{
- FontDescription description;
- description.path = path;
- description.family = std::move(FontFamily(ftFace->family_name));
- description.weight = FontWeight::NONE;
- description.width = FontWidth::NONE;
- description.slant = FontSlant::NONE;
-
- // Note FreeType doesn't give too much info to build a proper font style.
- if(ftFace->style_flags & FT_STYLE_FLAG_ITALIC)
- {
- description.slant = FontSlant::ITALIC;
- }
- if(ftFace->style_flags & FT_STYLE_FLAG_BOLD)
- {
- description.weight = FontWeight::BOLD;
- }
-
- FontDescriptionId validatedFontId = 0u;
- if(!FindValidatedFont(description,
- validatedFontId))
- {
- FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
- FcResult result = FcResultMatch;
- FcPattern* match = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
-
- FcCharSet* characterSet = nullptr;
- FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
-
- const FontId fontFaceId = id - 1u;
- mFontFaceCache[fontFaceId].mCharacterSet = FcCharSetCopy(characterSet); // Increases the reference counter.
-
- // Destroys the created patterns.
- FcPatternDestroy(match);
- FcPatternDestroy(pattern);
-
- // Add the path to the cache.
- description.type = FontDescription::FACE_FONT;
- mFontDescriptionCache.push_back(description);
-
- // Set the index to the vector of paths to font file names.
- validatedFontId = mFontDescriptionCache.size();
-
- // Increase the reference counter and add the character set to the cache.
- mCharacterSetCache.PushBack(FcCharSetCopy(characterSet));
-
- // Cache the index and the font's description.
- mValidatedFontCache.push_back(std::move(FontDescriptionCacheItem(std::move(description),
- validatedFontId)));
-
- // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
- mFontDescriptionSizeCache.push_back(FontDescriptionSizeCacheItem(validatedFontId,
- requestedPointSize,
- fontFaceId));
- }
-}
-
-void FontClient::Plugin::ClearFallbackCache(std::vector<FallbackCacheItem>& fallbackCache)
-{
- for(auto& item : fallbackCache)
- {
- if(nullptr != item.fallbackFonts)
- {
- delete item.fallbackFonts;
- }
-
- if(nullptr != item.characterSets)
- {
- // Free the resources allocated by the FcCharSet objects in the 'characterSets' vector.
- DestroyCharacterSets(*item.characterSets);
- delete item.characterSets;
- }
- }
-}
-
-void FontClient::Plugin::ClearCharacterSetFromFontFaceCache()
-{
- for(auto& item : mFontFaceCache)
- {
- FcCharSetDestroy(item.mCharacterSet);
- item.mCharacterSet = nullptr;
- }
-}
-
} // namespace Dali::TextAbstraction::Internal