diff options
author | Caolán McNamara <caolanm@redhat.com> | 2012-06-19 22:23:33 +0100 |
---|---|---|
committer | Petr Mladek <pmladek@suse.cz> | 2012-06-25 10:44:12 +0200 |
commit | eaf9cbd403f375f9b69e1c7ed8503d3bc23bcc6e (patch) | |
tree | 7555a062893522f45cf4f5bf9e8d5b2f0f1cc4b6 | |
parent | 949c6d959af1971552ae78e69251fab1b8e7dce3 (diff) |
Resolves: fdo#47636 cache fontconfig font substitutions
But this time cache on *all* properties, not just the name, which doesn't cut
it, given the things fontconfig can do, e.g. fdo#41556
(cherry picked from commit 8c023fd645c8b83637ffcde4055886b2e4f94393)
Conflicts:
vcl/generic/fontmanager/fontsubst.cxx
vcl/inc/outfont.hxx
vcl/source/gdi/outdev3.cxx
Change-Id: Idfc1dbac67b6912e4985570a0b7c6ccdf47fa4a5
Signed-off-by: Michael Meeks <michael.meeks@suse.com>
-rw-r--r-- | vcl/generic/fontmanager/fontsubst.cxx | 59 | ||||
-rw-r--r-- | vcl/inc/outfont.hxx | 38 | ||||
-rwxr-xr-x | vcl/source/gdi/outdev3.cxx | 165 |
3 files changed, 210 insertions, 52 deletions
diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx index 3e1cafc7c90b..188e628f809f 100644 --- a/vcl/generic/fontmanager/fontsubst.cxx +++ b/vcl/generic/fontmanager/fontsubst.cxx @@ -42,15 +42,27 @@ #include "salprn.hxx" #include "region.h" +#include <list> + // =========================================================================== // platform specific font substitution hooks // =========================================================================== +struct FontSelectPatternAttributesHash +{ + size_t operator()(const FontSelectPatternAttributes& rAttributes) const + { return rAttributes.hashCode(); } +}; + class FcPreMatchSubstititution : public ImplPreMatchFontSubstitution { public: bool FindFontSubstitute( FontSelectPattern& ) const; + typedef ::std::pair<FontSelectPatternAttributes, FontSelectPatternAttributes> value_type; +private: + typedef ::std::list<value_type> CachedFontMapType; + mutable CachedFontMapType maCachedFontMap; }; class FcGlyphFallbackSubstititution @@ -135,6 +147,19 @@ namespace rOrig.meWidthType == rNew.meWidthType ); } + + class equal + { + private: + const FontSelectPatternAttributes& mrAttributes; + public: + equal(const FontSelectPatternAttributes& rAttributes) + : mrAttributes(rAttributes) + { + } + bool operator()(const FcPreMatchSubstititution::value_type& rOther) const + { return rOther.first == mrAttributes; } + }; } //-------------------------------------------------------------------------- @@ -149,11 +174,26 @@ bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelDa || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) ) return false; - //Note: see fdo#41556 if you feel compelled to cache the results here, - //remember that fontconfig can return e.g. an italic font for a non-italic - //input and/or different fonts depending on fontsize, bold, etc settings so - //don't cache just on the name, cache on all the input and be don't just - //return the original selection data with the fontname updated + //see fdo#41556 and fdo#47636 + //fontconfig can return e.g. an italic font for a non-italic input and/or + //different fonts depending on fontsize, bold, etc settings so don't cache + //just on the name, cache map all the input and all the output not just map + //from original selection to output fontname + FontSelectPatternAttributes& rPatternAttributes = rFontSelData; + CachedFontMapType &rCachedFontMap = const_cast<CachedFontMapType &>(maCachedFontMap); + CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes)); + if (itr != rCachedFontMap.end()) + { + // Cached substitution + rFontSelData.copyAttributes(itr->second); + if (itr != rCachedFontMap.begin()) + { + // MRU, move it to the front + rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr); + } + return true; + } + rtl::OUString aDummy; const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy ); @@ -176,7 +216,14 @@ bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelDa #endif if( bHaveSubstitute ) + { + rCachedFontMap.push_front(value_type(rFontSelData, aOut)); + //fairly arbitrary limit in this case, but I recall measuring max 8 + //fonts as the typical max amount of fonts in medium sized documents + if (rCachedFontMap.size() > 8) + rCachedFontMap.pop_back(); rFontSelData = aOut; + } return bHaveSubstitute; } @@ -188,7 +235,7 @@ bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFont { // We dont' actually want to talk to Fontconfig at all for symbol fonts if( rFontSelData.IsSymbolFont() ) - return false; + return false; // StarSymbol is a unicode font, but it still deserves the symbol flag if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10) || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) ) diff --git a/vcl/inc/outfont.hxx b/vcl/inc/outfont.hxx index 75871dac4293..3145210e7fa9 100644 --- a/vcl/inc/outfont.hxx +++ b/vcl/inc/outfont.hxx @@ -71,6 +71,12 @@ public: // TODO: create matching interface class FontWidth GetWidthType() const { return meWidthType; } bool IsSymbolFont() const { return mbSymbolFlag; } + bool operator==(const ImplFontAttributes& rOther) const; + bool operator!=(const ImplFontAttributes& rOther) const + { + return !(*this == rOther); + } + public: // TODO: hide members behind accessor methods String maName; // Font Family Name String maStyleName; // Font Style Name @@ -152,24 +158,27 @@ friend class ImplDevFontListData; ImplFontData* mpNext; }; -// ---------------------- -// - FontSelectPattern - -// ---------------------- - -class FontSelectPattern : public ImplFontAttributes +class FontSelectPatternAttributes : public ImplFontAttributes { public: - FontSelectPattern( const Font&, const String& rSearchName, + FontSelectPatternAttributes( const Font&, const String& rSearchName, const Size&, float fExactHeight ); - FontSelectPattern( const ImplFontData&, const Size&, + FontSelectPatternAttributes( const ImplFontData&, const Size&, float fExactHeight, int nOrientation, bool bVertical ); -public: // TODO: change to private + size_t hashCode() const; + bool operator==(const FontSelectPatternAttributes& rOther) const; + bool operator!=(const FontSelectPatternAttributes& rOther) const + { + return !(*this == rOther); + } + +public: String maTargetName; // name of the font name token that is chosen String maSearchName; // name of the font that matches best int mnWidth; // width of font in pixel units int mnHeight; // height of font in pixel units - float mfExactHeight; // requested height (in pixels with subpixel details) + float mfExactHeight; // requested height (in pixels with subpixel details) int mnOrientation; // text orientation in 3600 system LanguageType meLanguage; // text language bool mbVertical; // vertical mode of requested font @@ -177,9 +186,20 @@ public: // TODO: change to private bool mbEmbolden; // Force emboldening ItalicMatrix maItalicMatrix; // Force matrix for slant +}; +class FontSelectPattern : public FontSelectPatternAttributes +{ +public: + FontSelectPattern( const Font&, const String& rSearchName, + const Size&, float fExactHeight ); + FontSelectPattern( const ImplFontData&, const Size&, + float fExactHeight, int nOrientation, bool bVertical ); + +public: // TODO: change to private const ImplFontData* mpFontData; // a matching ImplFontData object ImplFontEntry* mpFontEntry; // pointer to the resulting FontCache entry + void copyAttributes(const FontSelectPatternAttributes &rAttributes); }; // ------------------- diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index e35928133ca7..2e2f373d07d5 100755 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -2151,21 +2151,17 @@ ImplGetDevSizeList* ImplDevFontList::GetDevSizeList( const String& rFontName ) c return pGetDevSizeList; } -// ======================================================================= - -FontSelectPattern::FontSelectPattern( const Font& rFont, - const String& rSearchName, const Size& rSize, float fExactHeight) -: maSearchName( rSearchName ), - mnWidth( rSize.Width() ), - mnHeight( rSize.Height() ), - mfExactHeight( fExactHeight), - mnOrientation( rFont.GetOrientation() ), - meLanguage( rFont.GetLanguage() ), - mbVertical( rFont.IsVertical() ), - mbNonAntialiased( false ), - mbEmbolden( false ), - mpFontData( NULL ), - mpFontEntry( NULL ) +FontSelectPatternAttributes::FontSelectPatternAttributes( const Font& rFont, + const String& rSearchName, const Size& rSize, float fExactHeight ) + : maSearchName( rSearchName ) + , mnWidth( rSize.Width() ) + , mnHeight( rSize.Height() ) + , mfExactHeight( fExactHeight) + , mnOrientation( rFont.GetOrientation() ) + , meLanguage( rFont.GetLanguage() ) + , mbVertical( rFont.IsVertical() ) + , mbNonAntialiased( false ) + , mbEmbolden( false ) { maTargetName = maName; @@ -2187,51 +2183,115 @@ FontSelectPattern::FontSelectPattern( const Font& rFont, mnWidth = -mnWidth; } -// ----------------------------------------------------------------------- +FontSelectPattern::FontSelectPattern( const Font& rFont, + const String& rSearchName, const Size& rSize, float fExactHeight) + : FontSelectPatternAttributes(rFont, rSearchName, rSize, fExactHeight) + , mpFontData( NULL ) + , mpFontEntry( NULL ) +{ +} -FontSelectPattern::FontSelectPattern( const ImplFontData& rFontData, +// NOTE: this ctor is still used on Windows. Do not remove. +FontSelectPatternAttributes::FontSelectPatternAttributes( const ImplFontData& rFontData, const Size& rSize, float fExactHeight, int nOrientation, bool bVertical ) -: ImplFontAttributes( rFontData ), - mnWidth( rSize.Width() ), - mnHeight( rSize.Height() ), - mfExactHeight( fExactHeight ), - mnOrientation( nOrientation ), - meLanguage( 0 ), - mbVertical( bVertical ), - mbNonAntialiased( false ), - mbEmbolden( false ), - mpFontData( &rFontData ), - mpFontEntry( NULL ) + : ImplFontAttributes( rFontData ) + , mnWidth( rSize.Width() ) + , mnHeight( rSize.Height() ) + , mfExactHeight( fExactHeight ) + , mnOrientation( nOrientation ) + , meLanguage( 0 ) + , mbVertical( bVertical ) + , mbNonAntialiased( false ) + , mbEmbolden( false ) { maTargetName = maSearchName = maName; // NOTE: no normalization for width/height/orientation } +FontSelectPattern::FontSelectPattern( const ImplFontData& rFontData, + const Size& rSize, float fExactHeight, int nOrientation, bool bVertical ) + : FontSelectPatternAttributes(rFontData, rSize, fExactHeight, nOrientation, bVertical) + , mpFontData( &rFontData ) + , mpFontEntry( NULL ) +{ +} + +void FontSelectPattern::copyAttributes(const FontSelectPatternAttributes &rAttributes) +{ + static_cast<FontSelectPatternAttributes&>(*this) = rAttributes; +} + // ======================================================================= size_t ImplFontCache::IFSD_Hash::operator()( const FontSelectPattern& rFSD ) const { + return rFSD.hashCode(); +} + +size_t FontSelectPatternAttributes::hashCode() const +{ // TODO: does it pay off to improve this hash function? static FontNameHash aFontNameHash; - size_t nHash = aFontNameHash( rFSD.maSearchName ); + size_t nHash = aFontNameHash( maSearchName ); #ifdef ENABLE_GRAPHITE // check for features and generate a unique hash if necessary - if (rFSD.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX) + if (maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX) != STRING_NOTFOUND) { - nHash = aFontNameHash( rFSD.maTargetName ); + nHash = aFontNameHash( maTargetName ); } #endif - nHash += 11 * rFSD.mnHeight; - nHash += 19 * rFSD.meWeight; - nHash += 29 * rFSD.meItalic; - nHash += 37 * rFSD.mnOrientation; - nHash += 41 * rFSD.meLanguage; - if( rFSD.mbVertical ) + nHash += 11 * mnHeight; + nHash += 19 * meWeight; + nHash += 29 * meItalic; + nHash += 37 * mnOrientation; + nHash += 41 * meLanguage; + if( mbVertical ) nHash += 53; return nHash; } +bool FontSelectPatternAttributes::operator==(const FontSelectPatternAttributes& rOther) const +{ + if (static_cast<const ImplFontAttributes&>(*this) != static_cast<const ImplFontAttributes&>(rOther)) + return false; + + if (maTargetName != rOther.maTargetName) + return false; + + if (maSearchName != rOther.maSearchName) + return false; + + if (mnWidth != rOther.mnWidth) + return false; + + if (mnHeight != rOther.mnHeight) + return false; + + if (mfExactHeight != rOther.mfExactHeight) + return false; + + if (mnOrientation != rOther.mnOrientation) + return false; + + if (meLanguage != rOther.meLanguage) + return false; + + if (mbVertical != rOther.mbVertical) + return false; + + if (mbNonAntialiased != rOther.mbNonAntialiased) + return false; + + if (mbEmbolden != rOther.mbEmbolden) + return false; + + if (maItalicMatrix != rOther.maItalicMatrix) + return false; + + return true; +} + // ----------------------------------------------------------------------- bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const FontSelectPattern& rB) const @@ -3290,6 +3350,37 @@ void OutputDevice::ImplInitAboveTextLineSize() // ----------------------------------------------------------------------- +bool ImplFontAttributes::operator==(const ImplFontAttributes& rOther) const +{ + if (maName != rOther.maName) + return false; + + if (maStyleName != rOther.maStyleName) + return false; + + if (meWeight != rOther.meWeight) + return false; + + if (meItalic != rOther.meItalic) + return false; + + if (meFamily != rOther.meFamily) + return false; + + if (mePitch != rOther.mePitch) + return false; + + if (meWidthType != rOther.meWidthType) + return false; + + if (mbSymbolFlag != rOther.mbSymbolFlag) + return false; + + return true; +} + +// ----------------------------------------------------------------------- + ImplFontMetricData::ImplFontMetricData( const FontSelectPattern& rFontSelData ) : ImplFontAttributes( rFontSelData ) { |