[Libreoffice-commits] .: Branch 'libreoffice-3-6' - vcl/generic vcl/inc vcl/source

Michael Meeks michael at kemper.freedesktop.org
Mon Jun 25 02:34:19 PDT 2012


 vcl/generic/fontmanager/fontsubst.cxx |   59 ++++++++++--
 vcl/inc/outfont.hxx                   |   38 +++++--
 vcl/source/gdi/outdev3.cxx            |  165 ++++++++++++++++++++++++++--------
 3 files changed, 210 insertions(+), 52 deletions(-)

New commits:
commit 304bb8386cef389c82e437f387576c4cf436de48
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue Jun 19 22:23:33 2012 +0100

    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/inc/outfont.hxx
    	vcl/source/gdi/outdev3.cxx
    
    Change-Id: Idfc1dbac67b6912e4985570a0b7c6ccdf47fa4a5

diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx
index 4f3ec48..3f51fe5 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 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) )
diff --git a/vcl/inc/outfont.hxx b/vcl/inc/outfont.hxx
index 19c2c3a..0702778 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 06d04cc..261f14a 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -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 ImplFontData& rFontData,
+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
@@ -3345,6 +3405,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 )
 {


More information about the Libreoffice-commits mailing list