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 Change-Id: Idfc1dbac67b6912e4985570a0b7c6ccdf47fa4a5
This commit is contained in:
parent
3a615029d0
commit
8c023fd645
3 changed files with 212 additions and 55 deletions
|
@ -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 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 );
|
||||
|
||||
|
@ -178,7 +218,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;
|
||||
}
|
||||
|
@ -190,7 +237,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) )
|
||||
|
|
|
@ -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
|
||||
|
@ -109,7 +115,6 @@ public: // TODO: hide members behind accessor methods
|
|||
// ----------------
|
||||
// - PhysicalFontFace -
|
||||
// ----------------
|
||||
// DONE: rename ImplFontData to PhysicalFontFace
|
||||
// TODO: no more direct access to members
|
||||
// TODO: add reference counting
|
||||
// TODO: get rid of height/width for scalable fonts
|
||||
|
@ -152,24 +157,27 @@ friend class ImplDevFontListData;
|
|||
PhysicalFontFace* mpNext;
|
||||
};
|
||||
|
||||
// ----------------------
|
||||
// - FontSelectPattern -
|
||||
// ----------------------
|
||||
|
||||
class FontSelectPattern : public ImplFontAttributes
|
||||
class FontSelectPatternAttributes : public ImplFontAttributes
|
||||
{
|
||||
public:
|
||||
FontSelectPattern( const Font&, const String& rSearchName,
|
||||
const Size&, float fExactHeight );
|
||||
FontSelectPattern( const PhysicalFontFace&, const Size&,
|
||||
float fExactHeight, int nOrientation, bool bVertical );
|
||||
FontSelectPatternAttributes( const Font&, const String& rSearchName,
|
||||
const Size&, float fExactHeight );
|
||||
FontSelectPatternAttributes( const PhysicalFontFace&, 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 +185,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 PhysicalFontFace&, const Size&,
|
||||
float fExactHeight, int nOrientation, bool bVertical );
|
||||
|
||||
public: // TODO: change to private
|
||||
const PhysicalFontFace* mpFontData; // a matching PhysicalFontFace object
|
||||
ImplFontEntry* mpFontEntry; // pointer to the resulting FontCache entry
|
||||
void copyAttributes(const FontSelectPatternAttributes &rAttributes);
|
||||
};
|
||||
|
||||
// -------------------
|
||||
|
|
|
@ -2139,21 +2139,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;
|
||||
|
||||
|
@ -2175,51 +2171,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 )
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: this ctor is still used on Windows. Do not remove.
|
||||
FontSelectPattern::FontSelectPattern( const PhysicalFontFace& rFontData,
|
||||
FontSelectPatternAttributes::FontSelectPatternAttributes( const PhysicalFontFace& 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 PhysicalFontFace& 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
|
||||
|
@ -3332,6 +3392,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 )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue