summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2012-06-19 22:23:33 +0100
committerMichael Meeks <michael.meeks@suse.com>2012-06-25 10:44:27 +0100
commitd122b0f592aaa8af00695109ce2a71f6d8807a96 (patch)
tree864c0dcb44d3fb747f3da0786746cf28cc822229
parent3e6d34e4afa67d01a40804e93b6d3f94b09dcc5e (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.cxx59
-rw-r--r--vcl/inc/outfont.hxx38
-rwxr-xr-xvcl/source/gdi/outdev3.cxx165
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 )
{