summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2021-04-14 09:57:33 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2021-04-16 11:32:11 +0200
commitceb556971b163a98e7a46ea573717fe8813047f4 (patch)
tree4ec11ba0a6681b7b1f76875a700f0d6353ce7350
parent93b50c83b370a6621438ae532f897100b2bf0666 (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.hxx5
-rw-r--r--vcl/unx/generic/fontmanager/fontconfig.cxx122
-rw-r--r--vcl/unx/generic/gdi/freetypetextrender.cxx1
-rw-r--r--vcl/unx/generic/glyphs/freetype_glyphcache.cxx11
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);
}
}