X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Ftext%2Ftext-abstraction%2Fplugin%2Ffont-client-plugin-impl.cpp;h=e319b46418a3b8bb038a7cf46e5b61b4d143f952;hb=5a983dd62d2c305086b7689a7553e8e7dd0ee984;hp=e438a53ed2af619942a58f8ad71e2923ec2b0323;hpb=c95ad6d50d9549451e01c351d8338d83a937d98a;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp index e438a53..e319b46 100644 --- a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp +++ b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -20,14 +20,14 @@ // INTERNAL INCLUDES #include - -#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -76,39 +76,25 @@ Dali::Integration::Log::Filter* gFontClientLogFilter = Dali::Integration::Log::F 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 * @@ -227,57 +213,17 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi, 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) @@ -292,51 +238,19 @@ FontClient::Plugin::Plugin(unsigned int horizontalDpi, 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(); - - mDefaultFontDescriptionCached = false; + mCacheHandler->ClearCache(); } void FontClient::Plugin::SetDpi(unsigned int horizontalDpi, @@ -346,218 +260,59 @@ void FontClient::Plugin::SetDpi(unsigned int horizontalDpi, mDpiVertical = verticalDpi; } -void FontClient::Plugin::ResetSystemDefaults() -{ - mDefaultFontDescriptionCached = false; -} - -void FontClient::Plugin::SetFontList(const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList) +void FontClient::Plugin::ResetSystemDefaults() 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(nullptr != fontSet) - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of fonts found : [%d]\n", fontSet->nfont); - // Reserve some space to avoid reallocations. - fontList.reserve(fontSet->nfont); - - for(int i = 0u; i < fontSet->nfont; ++i) - { - FcPattern* fontPattern = fontSet->fonts[i]; - - FontPath path; - - // Skip fonts with no path - if(GetFcString(fontPattern, FC_FILE, path)) - { - // Retrieve the character set. Need to call FcCharSetDestroy to free the resources. - FcCharSet* characterSet = nullptr; - FcPatternGetCharSet(fontPattern, FC_CHARSET, 0u, &characterSet); - - // Increase the reference counter of the character set. - characterSetList.PushBack(FcCharSetCopy(characterSet)); - - fontList.push_back(FontDescription()); - FontDescription& newFontDescription = fontList.back(); - - newFontDescription.path = std::move(path); - - int width = 0; - int weight = 0; - int slant = 0; - GetFcString(fontPattern, FC_FAMILY, newFontDescription.family); - GetFcInt(fontPattern, FC_WIDTH, width); - GetFcInt(fontPattern, FC_WEIGHT, weight); - GetFcInt(fontPattern, FC_SLANT, slant); - newFontDescription.width = IntToWidthType(width); - newFontDescription.weight = IntToWeightType(weight); - newFontDescription.slant = IntToSlantType(slant); - - FONT_LOG_DESCRIPTION(newFontDescription, ""); - } - } - - // Destroys the font set created by FcFontSort. - FcFontSetDestroy(fontSet); - } - else - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " No fonts found.\n"); - } - - // Destroys the pattern created by FcPatternCreate in CreateFontFamilyPattern. - FcPatternDestroy(fontFamilyPattern); + mCacheHandler->ResetSystemDefaults(); } -void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts) +void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& fontDescription) const { DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - if(mDefaultFonts.empty()) - { - FontDescription fontDescription; - fontDescription.family = DEFAULT_FONT_FAMILY_NAME; // todo This could be set to the Platform font - fontDescription.width = DefaultFontWidth(); - fontDescription.weight = DefaultFontWeight(); - fontDescription.slant = DefaultFontSlant(); - SetFontList(fontDescription, mDefaultFonts, mDefaultFontCharacterSets); - } - - defaultFonts = mDefaultFonts; + mCacheHandler->InitDefaultFontDescription(); + fontDescription = mCacheHandler->mDefaultFontDescription; - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of default fonts : [%d]\n", mDefaultFonts.size()); + FONT_LOG_DESCRIPTION(fontDescription, ""); } -void FontClient::Plugin::GetDefaultPlatformFontDescription(FontDescription& fontDescription) +void FontClient::Plugin::GetDefaultFonts(FontList& defaultFonts) const { DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - if(!mDefaultFontDescriptionCached) - { - // Clear any font config stored info in the caches. - - // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects. - DestroyCharacterSets(mDefaultFontCharacterSets); - DestroyCharacterSets(mCharacterSetCache); - mDefaultFontCharacterSets.Clear(); - mCharacterSetCache.Clear(); - - for(auto& item : mFallbackCache) - { - // Decrease the reference counter and eventually free the resources allocated by FcCharSet objects. - DestroyCharacterSets(*item.characterSets); - - delete item.characterSets; - item.characterSets = nullptr; - } - - // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont() - ClearCharacterSetFromFontFaceCache(); - - // FcInitBringUptoDate did not seem to reload config file as was still getting old default font. - FcInitReinitialize(); - - FcPattern* matchPattern = FcPatternCreate(); // Creates a pattern that needs to be destroyed by calling FcPatternDestroy. - - if(nullptr != matchPattern) - { - FcConfigSubstitute(nullptr, matchPattern, FcMatchPattern); - FcDefaultSubstitute(matchPattern); - - FcCharSet* characterSet = nullptr; - MatchFontDescriptionToPattern(matchPattern, mDefaultFontDescription, &characterSet); - // Decrease the reference counter of the character set as it's not stored. - FcCharSetDestroy(characterSet); - - // Destroys the pattern created. - FcPatternDestroy(matchPattern); - } - - // Create again the character sets as they are not valid after FcInitReinitialize() - - for(const auto& description : mDefaultFonts) - { - mDefaultFontCharacterSets.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description))); - } - - for(const auto& description : mFontDescriptionCache) - { - mCharacterSetCache.PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description))); - } - - for(auto& item : mFallbackCache) - { - if(nullptr != item.fallbackFonts) - { - if(nullptr == item.characterSets) - { - item.characterSets = new CharacterSetList; - } - - for(const auto& description : *(item.fallbackFonts)) - { - item.characterSets->PushBack(FcCharSetCopy(CreateCharacterSetFromDescription(description))); - } - } - } - - mDefaultFontDescriptionCached = true; - } - - fontDescription.path = mDefaultFontDescription.path; - fontDescription.family = mDefaultFontDescription.family; - fontDescription.width = mDefaultFontDescription.width; - fontDescription.weight = mDefaultFontDescription.weight; - fontDescription.slant = mDefaultFontDescription.slant; + mCacheHandler->InitDefaultFonts(); + defaultFonts = mCacheHandler->mDefaultFonts; - FONT_LOG_DESCRIPTION(fontDescription, ""); + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of default fonts : [%d]\n", mCacheHandler->mDefaultFonts.size()); } -void FontClient::Plugin::GetSystemFonts(FontList& systemFonts) +void FontClient::Plugin::GetSystemFonts(FontList& systemFonts) const { DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - if(mSystemFonts.empty()) - { - InitSystemFonts(); - } + mCacheHandler->InitSystemFonts(); + systemFonts = mCacheHandler->mSystemFonts; - systemFonts = mSystemFonts; - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : [%d]\n", mSystemFonts.size()); + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : [%d]\n", mCacheHandler->mSystemFonts.size()); } -void FontClient::Plugin::GetDescription(FontId id, +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; @@ -568,7 +323,7 @@ void FontClient::Plugin::GetDescription(FontId id, 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: @@ -580,16 +335,16 @@ void FontClient::Plugin::GetDescription(FontId id, } } - 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(); @@ -599,7 +354,7 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id) 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); @@ -616,21 +371,20 @@ bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character cha 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: { @@ -645,7 +399,7 @@ FontId FontClient::Plugin::FindFontForCharacter(const FontList& fontList 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); @@ -681,10 +435,9 @@ FontId FontClient::Plugin::FindFontForCharacter(const FontList& fontList 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; } @@ -706,7 +459,7 @@ FontId FontClient::Plugin::FindFontForCharacter(const FontList& fontList FontId FontClient::Plugin::FindDefaultFont(Character charcode, PointSize26Dot6 requestedPointSize, - bool preferColor) + bool preferColor) const { DALI_LOG_TRACE_METHOD(gFontClientLogFilter); FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor); @@ -714,21 +467,12 @@ FontId FontClient::Plugin::FindDefaultFont(Character charcode, 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; @@ -737,18 +481,20 @@ FontId FontClient::Plugin::FindDefaultFont(Character charcode, 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); @@ -759,34 +505,20 @@ FontId FontClient::Plugin::FindFallbackFont(Character charcode, 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) @@ -798,10 +530,10 @@ FontId FontClient::Plugin::FindFallbackFont(Character charcode, 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()); @@ -812,7 +544,7 @@ FontId FontClient::Plugin::GetFontId(const FontPath& path, if(nullptr != mFreeTypeLibrary) { FontId foundId = 0u; - if(FindFont(path, requestedPointSize, faceIndex, foundId)) + if(mCacheHandler->FindFontByPath(path, requestedPointSize, faceIndex, foundId)) { id = foundId; } @@ -828,10 +560,22 @@ FontId FontClient::Plugin::GetFontId(const FontPath& path, 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: @@ -856,145 +600,94 @@ FontId FontClient::Plugin::GetFontId(const FontDescription& fontDescription, 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); + const FontDescription& description = *(mCacheHandler->mFontDescriptionCache.begin() + fontDescriptionId - 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)); + // 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) + // The font id to be returned. + FontId fontId = 0u; + if(!mCacheHandler->FindBitmapFont(bitmapFont.name, fontId)) { - if(bitmapFont.name == item.font.name) - { - return item.id + 1u; - } - } + BitmapFontCacheItem bitmapFontCacheItem(bitmapFont); - 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; + fontId = mCacheHandler->CacheBitmapFontCacheItem(std::move(bitmapFontCacheItem)); + } + return fontId; } -void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription, - FontDescriptionId& validatedFontId) +void FontClient::Plugin::GetFontMetrics(FontId fontId, + FontMetrics& metrics) const { - DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - FONT_LOG_DESCRIPTION(fontDescription, ""); - - // Create a font pattern. - FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); - - FontDescription description; - - FcCharSet* characterSet = nullptr; - bool matched = MatchFontDescriptionToPattern(fontFamilyPattern, description, &characterSet); - FcPatternDestroy(fontFamilyPattern); - - if(matched && (nullptr != characterSet)) - { - // Add the path to the cache. - description.type = FontDescription::FACE_FONT; - mFontDescriptionCache.push_back(description); - - // Set the index to the vector of paths to font file names. - validatedFontId = mFontDescriptionCache.size(); - - FONT_LOG_DESCRIPTION(description, "matched"); - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " validatedFontId : %d\n", validatedFontId); - - // The reference counter of the character set has already been increased in MatchFontDescriptionToPattern. - mCharacterSetCache.PushBack(characterSet); - - // Cache the index and the matched font's description. - FontDescriptionCacheItem item(description, - validatedFontId); - - mValidatedFontCache.push_back(std::move(item)); - - if((fontDescription.family != description.family) || - (fontDescription.width != description.width) || - (fontDescription.weight != description.weight) || - (fontDescription.slant != description.slant)) - { - // Cache the given font's description if it's different than the matched. - FontDescriptionCacheItem item(fontDescription, - validatedFontId); - - mValidatedFontCache.push_back(std::move(item)); - } - } - else + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font validation failed for font [%s]\n", fontDescription.family.c_str()); + fontCacheItem->GetFontMetrics(metrics, mDpiVertical); } } -void FontClient::Plugin::GetFontMetrics(FontId fontId, - FontMetrics& metrics) +GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId, + Character charcode) const { const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); if(fontCacheItem != nullptr) { - fontCacheItem->GetFontMetrics(metrics, mDpiVertical); + return fontCacheItem->GetGlyphIndex(charcode); } + + return 0u; } GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId, - Character charcode) + Character charcode, + Character variantSelector) const { const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); if(fontCacheItem != nullptr) { - return fontCacheItem->GetGlyphIndex(charcode); + return fontCacheItem->GetGlyphIndex(charcode, variantSelector); } return 0u; @@ -1003,7 +696,7 @@ GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId, bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type, - bool horizontal) + bool horizontal) const { if(VECTOR_GLYPH == type) { @@ -1015,9 +708,9 @@ bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array, 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) { @@ -1026,13 +719,16 @@ bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array, 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())) + { + mCacheHandler->mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph); + } + else { - mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph); - success = true; + success = false; } } @@ -1041,7 +737,7 @@ bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array, bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array, uint32_t size, - bool horizontal) + bool horizontal) const { #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING bool success(true); @@ -1051,9 +747,9 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array, 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) { @@ -1082,7 +778,7 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array, #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::FontClient::GlyphBufferData& data, int outlineWidth) const { data.isColorBitmap = false; data.isColorEmoji = false; @@ -1091,95 +787,105 @@ void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool { 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; CreateBitmap(fontId, glyphIndex, false, false, data, outlineWidth); + // If data is compressed or not owned buffer, copy this. + if(!data.isBufferOwned || data.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION) + { + uint8_t* newBuffer = (uint8_t*)malloc(data.width * data.height * Pixel::GetBytesPerPixel(data.format)); + TextAbstraction::FontClient::GlyphBufferData::Decompress(data, newBuffer); + if(data.isBufferOwned) + { + free(data.buffer); + } + + data.buffer = newBuffer; + data.isBufferOwned = true; + data.compressionType = TextAbstraction::FontClient::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.index = ellipsisCacheIndex; - 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 = mCacheHandler->CacheEllipsis(std::move(item)); + } + 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) @@ -1189,13 +895,12 @@ FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId) 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; } @@ -1206,7 +911,17 @@ bool FontClient::Plugin::AddCustomFontDirectory(const FontPath& path) return FcConfigAppFontAddDir(nullptr, reinterpret_cast(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(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; @@ -1219,43 +934,17 @@ GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontCli 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) @@ -1277,22 +966,12 @@ GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontCli } // 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) @@ -1341,165 +1020,24 @@ uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const ; } -void FontClient::Plugin::InitSystemFonts() -{ - DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - - FcFontSet* fontSet = GetFcFontSet(); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy. - - if(fontSet) - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " number of system fonts : %d\n", fontSet->nfont); - - // Reserve some space to avoid reallocations. - mSystemFonts.reserve(fontSet->nfont); - - for(int i = 0u; i < fontSet->nfont; ++i) - { - FcPattern* fontPattern = fontSet->fonts[i]; - - FontPath path; - - // Skip fonts with no path - if(GetFcString(fontPattern, FC_FILE, path)) - { - mSystemFonts.push_back(FontDescription()); - FontDescription& fontDescription = mSystemFonts.back(); - - fontDescription.path = std::move(path); - - int width = 0; - int weight = 0; - int slant = 0; - GetFcString(fontPattern, FC_FAMILY, fontDescription.family); - GetFcInt(fontPattern, FC_WIDTH, width); - GetFcInt(fontPattern, FC_WEIGHT, weight); - GetFcInt(fontPattern, FC_SLANT, slant); - fontDescription.width = IntToWidthType(width); - fontDescription.weight = IntToWeightType(weight); - fontDescription.slant = IntToSlantType(slant); - - FONT_LOG_DESCRIPTION(fontDescription, ""); - } - } - - // Destroys the font set created. - FcFontSetDestroy(fontSet); - } -} - -bool FontClient::Plugin::MatchFontDescriptionToPattern(FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet) -{ - DALI_LOG_TRACE_METHOD(gFontClientLogFilter); - - FcResult result = FcResultMatch; - FcPattern* match = FcFontMatch(nullptr /* use default configure */, pattern, &result); // Creates a new font pattern that needs to be destroyed by calling FcPatternDestroy. - - const bool matched = nullptr != match; - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " pattern matched : %s\n", (matched ? "true" : "false")); - - if(matched) - { - int width = 0; - int weight = 0; - int slant = 0; - GetFcString(match, FC_FILE, fontDescription.path); - GetFcString(match, FC_FAMILY, fontDescription.family); - GetFcInt(match, FC_WIDTH, width); - GetFcInt(match, FC_WEIGHT, weight); - GetFcInt(match, FC_SLANT, slant); - fontDescription.width = IntToWidthType(width); - fontDescription.weight = IntToWeightType(weight); - fontDescription.slant = IntToSlantType(slant); - - // Retrieve the character set and increase the reference counter. - FcPatternGetCharSet(match, FC_CHARSET, 0u, characterSet); - *characterSet = FcCharSetCopy(*characterSet); - - // destroyed the matched pattern - FcPatternDestroy(match); - FONT_LOG_DESCRIPTION(fontDescription, ""); - } - return matched; -} - -_FcFontSet* FontClient::Plugin::GetFcFontSet() const -{ - FcFontSet* fontset = nullptr; - - // create a new pattern. - // a pattern holds a set of names, each name refers to a property of the font - FcPattern* pattern = FcPatternCreate(); - - if(nullptr != pattern) - { - // create an object set used to define which properties are to be returned in the patterns from FcFontList. - FcObjectSet* objectSet = FcObjectSetCreate(); - - if(nullptr != objectSet) - { - // build an object set from a list of property names - FcObjectSetAdd(objectSet, FC_FILE); - FcObjectSetAdd(objectSet, FC_FAMILY); - FcObjectSetAdd(objectSet, FC_WIDTH); - FcObjectSetAdd(objectSet, FC_WEIGHT); - FcObjectSetAdd(objectSet, FC_SLANT); - - // get a list of fonts - // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns - fontset = FcFontList(nullptr /* the default configuration is checked to be up to date, and used */, pattern, objectSet); // Creates a FcFontSet that needs to be destroyed by calling FcFontSetDestroy. - - // clear up the object set - FcObjectSetDestroy(objectSet); - } - - // clear up the pattern - FcPatternDestroy(pattern); - } - - return fontset; -} - -bool FontClient::Plugin::GetFcString(const FcPattern* const pattern, - const char* const n, - std::string& string) -{ - FcChar8* file = nullptr; - const FcResult retVal = FcPatternGetString(pattern, n, 0u, &file); - - if(FcResultMatch == retVal) - { - // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*. - string.assign(reinterpret_cast(file)); - - return true; - } - - return false; -} - -bool FontClient::Plugin::GetFcInt(const _FcPattern* const pattern, const char* const n, int& intVal) -{ - const FcResult retVal = FcPatternGetInteger(pattern, n, 0u, &intVal); - - if(FcResultMatch == retVal) - { - return true; - } - - return false; -} - FontId FontClient::Plugin::CreateFont(const FontPath& path, PointSize26Dot6 requestedPointSize, FaceIndex faceIndex, - bool cacheDescription) + 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); - FontId id = 0u; + DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_CREATE_FONT"); + FontId fontId = 0u; + + #if defined(TRACE_ENABLED) + if(gTraceFilter && gTraceFilter->IsTraceEnabled()) + { + DALI_LOG_DEBUG_INFO("DALI_TEXT_CREATE_FONT : FT_New_Face : %s\n", path.c_str()); + } + #endif // Create & cache new font face FT_Face ftFace; @@ -1514,7 +1052,6 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, 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")); @@ -1527,7 +1064,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, int fixedSizeIndex = 0; for(; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex) { - const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size; + const PointSize26Dot6 fixedSize = static_cast(ftFace->available_sizes[fixedSizeIndex].size); DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " size index : %d, size : %d\n", fixedSizeIndex, fixedSize); if(fixedSize >= requestedPointSize) @@ -1541,7 +1078,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, { // 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(ftFace->available_sizes[fixedSizeIndex].size); } DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, " size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize); @@ -1554,36 +1091,21 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, } else { + FT_Size_Metrics& ftMetrics = ftFace->size->metrics; + + FontMetrics metrics(static_cast(ftMetrics.ascender) * FROM_266, + static_cast(ftMetrics.descender) * FROM_266, + static_cast(ftMetrics.height) * FROM_266, + static_cast(ftFace->underline_position) * FROM_266, + static_cast(ftFace->underline_thickness) * FROM_266); + const float fixedWidth = static_cast(ftFace->available_sizes[fixedSizeIndex].width); const float fixedHeight = static_cast(ftFace->available_sizes[fixedSizeIndex].height); - // Indicate that the font is a fixed sized bitmap - FontMetrics metrics(fixedHeight, // The ascender in pixels. - 0.0f, - fixedHeight, // The height in pixels. - 0.0f, - 0.0f); - // Create the FreeType font face item to cache. - FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables); - - // Set the index to the font's id cache. - fontFaceCacheItem.mFontId = mFontIdCache.Count(); - - // Create the font id item to cache. - FontIdCacheItem fontIdCacheItem; - fontIdCacheItem.type = FontDescription::FACE_FONT; + FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, mCacheHandler->GetGlyphCacheManager(), path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables); - // 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 @@ -1623,25 +1145,9 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, static_cast(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(); + FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, mCacheHandler->GetGlyphCacheManager(), path, requestedPointSize, faceIndex, metrics); - // 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 { @@ -1649,11 +1155,12 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, } } - 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); } } } @@ -1662,144 +1169,16 @@ FontId FontClient::Plugin::CreateFont(const FontPath& 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); @@ -1812,10 +1191,15 @@ bool FontClient::Plugin::IsScalable(const FontPath& path) 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. @@ -1845,13 +1229,13 @@ bool FontClient::Plugin::IsScalable(const FontDescription& fontDescription) return isScalable; } -void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector& sizes) +void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vector& 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); @@ -1860,18 +1244,23 @@ void FontClient::Plugin::GetFixedSizes(const FontPath& path, Vectornum_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& sizes) + Vector& sizes) const { // Create a font pattern. FcPattern* fontFamilyPattern = CreateFontFamilyPattern(fontDescription); // Creates a font pattern that needs to be destroyed by calling FcPatternDestroy. @@ -1908,90 +1297,4 @@ bool FontClient::Plugin::HasItalicStyle(FontId fontId) const 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& 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