diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-04-14 09:57:33 +0100 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2021-04-16 11:32:11 +0200 |
commit | ceb556971b163a98e7a46ea573717fe8813047f4 (patch) | |
tree | 4ec11ba0a6681b7b1f76875a700f0d6353ce7350 | |
parent | 93b50c83b370a6621438ae532f897100b2bf0666 (diff) |
tdf#140639 cache FcPattern for font options
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114083
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
also includes...
getFontOptions is always called with pitch of PITCH_DONTKNOW
getFontOptions is called from only one location and there
the pitch value is left at its default PITCH_DONTKNOW
which is suspicious but that's the way it currently is
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114076
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
use original FontAttributes instead of an intermediate FastPrintFontInfo
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114077
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
hintstyle is unused
left behind after...
commit 561a02ec72cf963d7cd59cfb9a183c1032f0861b
Date: Thu Jun 15 15:28:46 2017 +0200
loplugin:unusedfields in vcl part3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114068
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Change-Id: Ibb1b1e06630e505924e05ea4b5b454e58738d743
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114140
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
(cherry picked from commit 365df37004630b68afafdc676e26f2599c2194a9)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114011
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r-- | vcl/inc/unx/fontmanager.hxx | 5 | ||||
-rw-r--r-- | vcl/unx/generic/fontmanager/fontconfig.cxx | 122 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/freetypetextrender.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 11 |
4 files changed, 117 insertions, 22 deletions
diff --git a/vcl/inc/unx/fontmanager.hxx b/vcl/inc/unx/fontmanager.hxx index 7d625555d833..2b0ace42b6c2 100644 --- a/vcl/inc/unx/fontmanager.hxx +++ b/vcl/inc/unx/fontmanager.hxx @@ -39,6 +39,7 @@ * friends are PostScript afm style, that is they are 1/1000 font height */ +class FontAttributes; class FontSubsetInfo; class FontConfigFontOptions; class FontSelectPattern; @@ -309,7 +310,9 @@ public: in different fonts in e.g. english and japanese */ void matchFont( FastPrintFontInfo& rInfo, const css::lang::Locale& rLocale ); - static std::unique_ptr<FontConfigFontOptions> getFontOptions( const FastPrintFontInfo&, int nSize); + + static std::unique_ptr<FontConfigFontOptions> getFontOptions(const FontAttributes& rFontAttributes, int nSize); + static void clearFontOptionsCache(); void Substitute(FontSelectPattern &rPattern, OUString& rMissingCodes); diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx b/vcl/unx/generic/fontmanager/fontconfig.cxx index a87c2c21094c..3354ccf0f857 100644 --- a/vcl/unx/generic/fontmanager/fontconfig.cxx +++ b/vcl/unx/generic/fontmanager/fontconfig.cxx @@ -18,6 +18,9 @@ */ #include <memory> +#include <string_view> + +#include <o3tl/lru_map.hxx> #include <unx/fontmanager.hxx> #include <unx/helper.hxx> #include <comphelper/sequence.hxx> @@ -44,6 +47,7 @@ using namespace psp; #include <osl/process.h> +#include <boost/functional/hash.hpp> #include <utility> #include <algorithm> @@ -51,7 +55,92 @@ using namespace osl; namespace { - typedef std::pair<FcChar8*, FcChar8*> lang_and_element; + +struct FontOptionsKey +{ + OUString m_sFamilyName; + int m_nFontSize; + FontItalic m_eItalic; + FontWeight m_eWeight; + FontWidth m_eWidth; + + bool operator==(const FontOptionsKey& rOther) const + { + return m_sFamilyName == rOther.m_sFamilyName && + m_nFontSize == rOther.m_nFontSize && + m_eItalic == rOther.m_eItalic && + m_eWeight == rOther.m_eWeight && + m_eWidth == rOther.m_eWidth; + } +}; + +} + +namespace std +{ + +template <> struct hash<FontOptionsKey> +{ + std::size_t operator()(const FontOptionsKey& k) const noexcept + { + std::size_t seed = k.m_sFamilyName.hashCode(); + boost::hash_combine(seed, k.m_nFontSize); + boost::hash_combine(seed, k.m_eItalic); + boost::hash_combine(seed, k.m_eWeight); + boost::hash_combine(seed, k.m_eWidth); + return seed; + } +}; + +} // end std namespace + +namespace +{ + +struct FcPatternDeleter +{ + void operator()(FcPattern* pPattern) const + { + FcPatternDestroy(pPattern); + } +}; + +typedef std::unique_ptr<FcPattern, FcPatternDeleter> FcPatternUniquePtr; + +class CachedFontConfigFontOptions +{ +private: + FontOptionsKey m_aKey; + std::unique_ptr<FontConfigFontOptions> m_xLastFontOptions; + + o3tl::lru_map<FontOptionsKey, FcPatternUniquePtr> lru_options_cache; + +public: + CachedFontConfigFontOptions() + : lru_options_cache(10) // arbitrary cache size of 10 + { + } + + std::unique_ptr<FontConfigFontOptions> lookup(const FontOptionsKey& rKey) + { + auto it = lru_options_cache.find(rKey); + if (it != lru_options_cache.end()) + return std::make_unique<FontConfigFontOptions>(FcPatternDuplicate(it->second.get())); + return nullptr; + } + + void cache(const FontOptionsKey& rKey, const FcPattern* pPattern) + { + lru_options_cache.insert(std::make_pair(rKey, FcPatternUniquePtr(FcPatternDuplicate(pPattern)))); + } + + void clear() + { + m_xLastFontOptions.reset(); + } +}; + +typedef std::pair<FcChar8*, FcChar8*> lang_and_element; class FontCfgWrapper { @@ -76,6 +165,7 @@ public: //to-do, make private and add some cleaner accessor methods std::unordered_map< OString, OString > m_aFontNameToLocalized; std::unordered_map< OString, OString > m_aLocalizedToCanonical; + CachedFontConfigFontOptions m_aCachedFontOptions; private: void cacheLocalizedFontNames(const FcChar8 *origfontname, const FcChar8 *bestfontname, const std::vector< lang_and_element > &lang_and_elements); @@ -367,6 +457,7 @@ void FontCfgWrapper::clear() m_pFontSet = nullptr; } m_pLanguageTag.reset(); + m_aCachedFontOptions.clear(); } /* @@ -1095,15 +1186,20 @@ void FontConfigFontOptions::SyncPattern(const OString& rFileName, sal_uInt32 nIn FcPatternAddBool(mpPattern, FC_EMBOLDEN, bEmbolden ? FcTrue : FcFalse); } -std::unique_ptr<FontConfigFontOptions> PrintFontManager::getFontOptions(const FastPrintFontInfo& rInfo, int nSize) +std::unique_ptr<FontConfigFontOptions> PrintFontManager::getFontOptions(const FontAttributes& rInfo, int nSize) { + FontOptionsKey aKey{ rInfo.GetFamilyName(), nSize, rInfo.GetItalic(), rInfo.GetWeight(), rInfo.GetWidthType() }; + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); - std::unique_ptr<FontConfigFontOptions> pOptions; + std::unique_ptr<FontConfigFontOptions> pOptions = rWrapper.m_aCachedFontOptions.lookup(aKey); + if (pOptions) + return pOptions; + FcConfig* pConfig = FcConfigGetCurrent(); FcPattern* pPattern = FcPatternCreate(); - OString sFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 ); + OString sFamily = OUStringToOString(aKey.m_sFamilyName, RTL_TEXTENCODING_UTF8); std::unordered_map< OString, OString >::const_iterator aI = rWrapper.m_aLocalizedToCanonical.find(sFamily); if (aI != rWrapper.m_aLocalizedToCanonical.end()) @@ -1111,23 +1207,19 @@ std::unique_ptr<FontConfigFontOptions> PrintFontManager::getFontOptions(const Fa if( !sFamily.isEmpty() ) FcPatternAddString(pPattern, FC_FAMILY, reinterpret_cast<FcChar8 const *>(sFamily.getStr())); - addtopattern(pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch); + // TODO: ePitch argument of always PITCH_DONTKNOW is suspicious + addtopattern(pPattern, aKey.m_eItalic, aKey.m_eWeight, aKey.m_eWidth, PITCH_DONTKNOW); FcPatternAddDouble(pPattern, FC_PIXEL_SIZE, nSize); - int hintstyle = FC_HINT_FULL; - FcConfigSubstitute(pConfig, pPattern, FcMatchPattern); FontConfigFontOptions::cairo_font_options_substitute(pPattern); FcDefaultSubstitute(pPattern); FcResult eResult = FcResultNoMatch; FcFontSet* pFontSet = rWrapper.getFontSet(); - FcPattern* pResult = FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult ); - if( pResult ) + if (FcPattern* pResult = FcFontSetMatch(pConfig, &pFontSet, 1, pPattern, &eResult)) { - (void) FcPatternGetInteger(pResult, - FC_HINT_STYLE, 0, &hintstyle); - + rWrapper.m_aCachedFontOptions.cache(aKey, pResult); pOptions.reset(new FontConfigFontOptions(pResult)); } @@ -1137,6 +1229,12 @@ std::unique_ptr<FontConfigFontOptions> PrintFontManager::getFontOptions(const Fa return pOptions; } +void PrintFontManager::clearFontOptionsCache() +{ + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + rWrapper.m_aCachedFontOptions.clear(); +} + void PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const css::lang::Locale& rLocale ) { FontCfgWrapper& rWrapper = FontCfgWrapper::get(); diff --git a/vcl/unx/generic/gdi/freetypetextrender.cxx b/vcl/unx/generic/gdi/freetypetextrender.cxx index 3d94da30440a..d0d4d960f50f 100644 --- a/vcl/unx/generic/gdi/freetypetextrender.cxx +++ b/vcl/unx/generic/gdi/freetypetextrender.cxx @@ -101,6 +101,7 @@ bool FreeTypeTextRenderImpl::AddTempDevFont( PhysicalFontCollection* pFontCollec void FreeTypeTextRenderImpl::ClearDevFontCache() { FreetypeManager::get().ClearFontCache(); + psp::PrintFontManager::clearFontOptionsCache(); } void FreeTypeTextRenderImpl::GetDevFontList( PhysicalFontCollection* pFontCollection ) diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index df59ce1c8e5c..9577ad252f49 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -465,16 +465,9 @@ FreetypeFont::FreetypeFont(FreetypeFontInstance& rFontInstance, std::shared_ptr< namespace { - std::unique_ptr<FontConfigFontOptions> GetFCFontOptions( const FontAttributes& rFontAttributes, int nSize) + std::unique_ptr<FontConfigFontOptions> GetFCFontOptions(const FontAttributes& rFontAttributes, int nSize) { - psp::FastPrintFontInfo aInfo; - - aInfo.m_aFamilyName = rFontAttributes.GetFamilyName(); - aInfo.m_eItalic = rFontAttributes.GetItalic(); - aInfo.m_eWeight = rFontAttributes.GetWeight(); - aInfo.m_eWidth = rFontAttributes.GetWidthType(); - - return psp::PrintFontManager::getFontOptions(aInfo, nSize); + return psp::PrintFontManager::getFontOptions(rFontAttributes, nSize); } } |