[libreoffice] Resolves: rhbz#665800 missing glyph symbol shown when toggling bold/italic for Sinhala text

Caolan McNamara caolanm at fedoraproject.org
Thu Oct 27 12:04:25 UTC 2011


commit 81d48c0b6ce9feb35fee9cf8ea00f287a3d371db
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Oct 27 13:04:20 2011 +0100

    Resolves: rhbz#665800 missing glyph symbol shown when toggling bold/italic for Sinhala text

 ...o-32665-handle-that-FreeSerif-lacks-some-.patch |  286 ++++++++++++++++++++
 ...o-41556-font-sub-cache-of-nameA-nameB-is-.patch |   76 ++++++
 libreoffice.spec                                   |   11 +-
 3 files changed, 372 insertions(+), 1 deletions(-)
---
diff --git a/0001-Resolves-fdo-32665-handle-that-FreeSerif-lacks-some-.patch b/0001-Resolves-fdo-32665-handle-that-FreeSerif-lacks-some-.patch
new file mode 100644
index 0000000..62c19c7
--- /dev/null
+++ b/0001-Resolves-fdo-32665-handle-that-FreeSerif-lacks-some-.patch
@@ -0,0 +1,286 @@
+From 58b48f188bbfd9a3382460d6de63848eb3db416d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm at redhat.com>
+Date: Thu, 27 Oct 2011 12:24:11 +0100
+Subject: [PATCH] Resolves: fdo#32665 handle that FreeSerif lacks some glyphs
+ in bold/italic
+
+FreeSerif lacks glyphs in bold/italic variants that it has in the normal one. A
+lot of our glyph fallback infrastructure, especially the caches don't expect
+that a normal variant of a font with extra emboldening or extra font skew can
+be a fallback for a bold/italic variant of itself which exists, but doesn't
+have the missing glyphs that the normal one does.
+
+We really need to improve our glyph/font caching, but we can get 90% of the
+way there by excluding such cases from the caches.
+---
+ vcl/generic/fontmanager/fontconfig.cxx |   18 ++++++++-
+ vcl/generic/fontmanager/fontsubst.cxx  |    6 +++-
+ vcl/generic/glyphs/glyphcache.cxx      |    7 ++++
+ vcl/inc/outfont.hxx                    |   19 ++++++++++
+ vcl/inc/vcl/fontmanager.hxx            |    3 +-
+ vcl/source/gdi/outdev3.cxx             |   60 ++++++++++++++++++++++----------
+ 6 files changed, 90 insertions(+), 23 deletions(-)
+
+diff --git a/vcl/generic/fontmanager/fontconfig.cxx b/vcl/generic/fontmanager/fontconfig.cxx
+index be91349..a4f5f7f 100644
+--- a/vcl/generic/fontmanager/fontconfig.cxx
++++ b/vcl/generic/fontmanager/fontconfig.cxx
+@@ -68,6 +68,9 @@ using namespace psp;
+ #ifndef FC_EMBOLDEN
+     #define FC_EMBOLDEN "embolden"
+ #endif
++#ifndef FC_MATRIX
++    #define FC_MATRIX "matrix"
++#endif
+ #ifndef FC_FONTFORMAT
+     #define FC_FONTFORMAT "fontformat"
+ #endif
+@@ -747,7 +750,7 @@ static void addtopattern(FcPattern *pPattern,
+ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName,
+     rtl::OUString& rMissingCodes, const rtl::OString &rLangAttrib,
+     FontItalic &rItalic, FontWeight &rWeight,
+-    FontWidth &rWidth, FontPitch &rPitch) const
++    FontWidth &rWidth, FontPitch &rPitch, bool &rEmbolden, ItalicMatrix &rMatrix) const
+ {
+     rtl::OUString aName;
+     FontCfgWrapper& rWrapper = FontCfgWrapper::get();
+@@ -834,6 +837,17 @@ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName,
+                     rPitch = convertSpacing(val);
+                 if (FcResultMatch == FcPatternGetInteger(pSet->fonts[0], FC_WIDTH, 0, &val))
+                     rWidth = convertWidth(val);
++                FcBool bEmbolden;
++                if (FcResultMatch == FcPatternGetBool(pSet->fonts[0], FC_EMBOLDEN, 0, &bEmbolden))
++                    rEmbolden = bEmbolden;
++                FcMatrix *pMatrix = 0;
++                if (FcResultMatch == FcPatternGetMatrix(pSet->fonts[0], FC_MATRIX, 0, &pMatrix))
++                {
++                    rMatrix.xx = pMatrix->xx;
++                    rMatrix.xy = pMatrix->xy;
++                    rMatrix.yx = pMatrix->yx;
++                    rMatrix.yy = pMatrix->yy;
++                }
+             }
+ 
+             // update rMissingCodes by removing resolved unicodes
+@@ -844,7 +858,7 @@ rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName,
+                 FcCharSet* unicodes;
+                 if (!FcPatternGetCharSet(pSet->fonts[0], FC_CHARSET, 0, &unicodes))
+                 {
+-                       for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
++                    for( sal_Int32 nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
+                     {
+                         // also handle unicode surrogates
+                         const sal_uInt32 nCode = rMissingCodes.iterateCodePoints( &nStrIndex );
+diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx
+index 3bf2d07..2d187b1 100644
+--- a/vcl/generic/fontmanager/fontsubst.cxx
++++ b/vcl/generic/fontmanager/fontsubst.cxx
+@@ -127,10 +127,14 @@ static ImplFontSelectData GetFcSubstitute(const ImplFontSelectData &rFontSelData
+     FontWeight eWeight = rFontSelData.GetWeight();
+     FontWidth eWidth = rFontSelData.GetWidthType();
+     FontPitch ePitch = rFontSelData.GetPitch();
++    bool bEmbolden = rFontSelData.mbEmbolden;
++    ItalicMatrix aMatrix = rFontSelData.maItalicMatrix;
+ 
+     const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+-    aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch);
++    aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch, bEmbolden, aMatrix );
+ 
++    aRet.maItalicMatrix = aMatrix;
++    aRet.mbEmbolden  = bEmbolden;
+     aRet.meItalic    = eItalic;
+     aRet.meWeight    = eWeight;
+     aRet.meWidthType = eWidth;
+diff --git a/vcl/generic/glyphs/glyphcache.cxx b/vcl/generic/glyphs/glyphcache.cxx
+index 5322b65..fa712bb 100644
+--- a/vcl/generic/glyphs/glyphcache.cxx
++++ b/vcl/generic/glyphs/glyphcache.cxx
+@@ -163,6 +163,13 @@ bool GlyphCache::IFSD_Equal::operator()( const ImplFontSelectData& rA, const Imp
+         != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
+         return false;
+ #endif
++
++    if (rA.mbEmbolden != rB.mbEmbolden)
++        return false;
++
++    if (rA.maItalicMatrix != rB.maItalicMatrix)
++        return false;
++
+     return true;
+ }
+ 
+diff --git a/vcl/inc/outfont.hxx b/vcl/inc/outfont.hxx
+index faf2b00..857d944 100644
+--- a/vcl/inc/outfont.hxx
++++ b/vcl/inc/outfont.hxx
+@@ -156,6 +156,22 @@ friend class ImplDevFontListData;
+ // - ImplFontSelectData -
+ // ----------------------
+ 
++struct ItalicMatrix
++{
++    double xx, xy, yx, yy;
++    ItalicMatrix() : xx(1), xy(0), yx(0), yy(1) {}
++};
++
++inline bool operator ==(const ItalicMatrix& a, const ItalicMatrix& b)
++{
++    return a.xx == b.xx && a.xy == b.xy && a.yx == b.yx && a.yy == b.yy;
++}
++
++inline bool operator !=(const ItalicMatrix& a, const ItalicMatrix& b)
++{
++    return a.xx != b.xx || a.xy != b.xy || a.yx != b.yx || a.yy != b.yy;
++}
++
+ class ImplFontSelectData : public ImplFontAttributes
+ {
+ public:
+@@ -175,6 +191,9 @@ public: // TODO: change to private
+     bool                mbVertical;         // vertical mode of requested font
+     bool                mbNonAntialiased;   // true if antialiasing is disabled
+ 
++    bool                mbEmbolden;         // Force emboldening
++    ItalicMatrix        maItalicMatrix;     // Force matrix for slant
++
+     const ImplFontData* mpFontData;         // a matching ImplFontData object
+     ImplFontEntry*      mpFontEntry;        // pointer to the resulting FontCache entry
+ };
+diff --git a/vcl/inc/vcl/fontmanager.hxx b/vcl/inc/vcl/fontmanager.hxx
+index 0af5e14..4a110ad 100644
+--- a/vcl/inc/vcl/fontmanager.hxx
++++ b/vcl/inc/vcl/fontmanager.hxx
+@@ -37,6 +37,7 @@
+ #include "vcl/dllapi.h"
+ #include "vcl/helper.hxx"
+ #include "vcl/vclenum.hxx"
++#include "outfont.hxx"
+ #include "com/sun/star/lang/Locale.hpp"
+ 
+ #include <vector>
+@@ -649,7 +650,7 @@ public:
+ 
+     rtl::OUString Substitute( const rtl::OUString& rFontName, rtl::OUString& rMissingCodes,
+         const rtl::OString& rLangAttrib, FontItalic& rItalic, FontWeight& rWeight,
+-        FontWidth& rWidth, FontPitch& rPitch) const;
++        FontWidth& rWidth, FontPitch& rPitch, bool &rEmboldening, ItalicMatrix &rMatrix) const;
+     bool hasFontconfig() const { return m_bFontconfigSuccess; }
+ 
+     int FreeTypeCharIndex( void *pFace, sal_uInt32 aChar );
+diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
+index b0f59cd..3cc438c 100755
+--- a/vcl/source/gdi/outdev3.cxx
++++ b/vcl/source/gdi/outdev3.cxx
+@@ -865,9 +865,11 @@ bool ImplFontData::IsBetterMatch( const ImplFontSelectData& rFSD, FontMatchStatu
+ 
+     if( rFSD.meWeight != WEIGHT_DONTKNOW )
+     {
+-        // if not bold prefer light fonts to bold fonts
+-        int nReqWeight = (int)rFSD.meWeight;
+-        if ( rFSD.meWeight > WEIGHT_MEDIUM )
++        // if not bold or requiring emboldening prefer light fonts to bold fonts
++        FontWeight ePatternWeight = rFSD.mbEmbolden ? WEIGHT_NORMAL : rFSD.meWeight;
++
++        int nReqWeight = (int)ePatternWeight;
++        if ( ePatternWeight > WEIGHT_MEDIUM )
+             nReqWeight += 100;
+ 
+         int nGivenWeight = (int)meWeight;
+@@ -897,14 +899,17 @@ bool ImplFontData::IsBetterMatch( const ImplFontSelectData& rFSD, FontMatchStatu
+             nMatch += 150;
+     }
+ 
+-    if ( rFSD.meItalic == ITALIC_NONE )
++    // if requiring custom matrix to fake italic, prefer upright font
++    FontItalic ePatternItalic = rFSD.maItalicMatrix != ItalicMatrix() ? ITALIC_NONE : rFSD.meItalic;
++
++    if ( ePatternItalic == ITALIC_NONE )
+     {
+         if( meItalic == ITALIC_NONE )
+             nMatch += 900;
+     }
+     else
+     {
+-        if( rFSD.meItalic == meItalic )
++        if( ePatternItalic == meItalic )
+             nMatch += 900;
+         else if( meItalic != ITALIC_NONE )
+             nMatch += 600;
+@@ -1457,22 +1462,31 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData&
+             else
+                 rFontSelData.maSearchName = String();
+ 
+-            // cache the result even if there was no match
+-            for(;;)
+-            {
+-                 if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) )
+-                     rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
+-                 if( nStrIndex >= aOldMissingCodes.getLength() )
+-                     break;
+-                 cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
+-            }
+-            if( rFontSelData.maSearchName.Len() != 0 )
++            //See fdo#32665 for an example. FreeSerif that has glyphs in normal
++            //font, but not in the italic or bold version
++            bool bSubSetOfFontRequiresPropertyFaking = rFontSelData.mbEmbolden || rFontSelData.maItalicMatrix != ItalicMatrix();
++
++            // cache the result even if there was no match, unless its from part of a font for which the properties need
++            // to be faked. We need to rework this cache to take into account that fontconfig can return different fonts
++            // for different input sizes, weights, etc. Basically the cache is way to naive
++            if (!bSubSetOfFontRequiresPropertyFaking)
+             {
+-                // remove cache entries that were still not resolved
+-                for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
++                for(;;)
+                 {
+-                    cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
+-                    rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
++                     if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) )
++                         rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
++                     if( nStrIndex >= aOldMissingCodes.getLength() )
++                         break;
++                     cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
++                }
++                if( rFontSelData.maSearchName.Len() != 0 )
++                {
++                    // remove cache entries that were still not resolved
++                    for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
++                    {
++                        cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
++                        rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
++                    }
+                 }
+             }
+         }
+@@ -2180,6 +2194,7 @@ ImplFontSelectData::ImplFontSelectData( const Font& rFont,
+     meLanguage( rFont.GetLanguage() ),
+     mbVertical( rFont.IsVertical() ),
+     mbNonAntialiased( false ),
++    mbEmbolden( false ),
+     mpFontData( NULL ),
+     mpFontEntry( NULL )
+ {
+@@ -2215,6 +2230,7 @@ ImplFontSelectData::ImplFontSelectData( const ImplFontData& rFontData,
+     meLanguage( 0 ),
+     mbVertical( bVertical ),
+     mbNonAntialiased( false ),
++    mbEmbolden( false ),
+     mpFontData( &rFontData ),
+     mpFontEntry( NULL )
+ {
+@@ -2297,6 +2313,12 @@ bool ImplFontCache::IFSD_Equal::operator()(const ImplFontSelectData& rA, const I
+         return false;
+ #endif
+ 
++    if (rA.mbEmbolden != rB.mbEmbolden)
++        return false;
++
++    if (rA.maItalicMatrix != rB.maItalicMatrix)
++        return false;
++
+     return true;
+ }
+ 
+-- 
+1.7.6.4
+
diff --git a/0001-Resolves-fdo-41556-font-sub-cache-of-nameA-nameB-is-.patch b/0001-Resolves-fdo-41556-font-sub-cache-of-nameA-nameB-is-.patch
new file mode 100644
index 0000000..5668691
--- /dev/null
+++ b/0001-Resolves-fdo-41556-font-sub-cache-of-nameA-nameB-is-.patch
@@ -0,0 +1,76 @@
+From 3f9a28f1f704967446b411b3b7e176deeb78ca83 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm at redhat.com>
+Date: Wed, 19 Oct 2011 16:03:29 +0100
+Subject: [PATCH] Resolves: fdo#41556 font sub cache of nameA => nameB is too
+ simplistic
+
+---
+ vcl/source/gdi/outdev3.cxx      |    2 +-
+ vcl/unx/generic/gdi/salgdi3.cxx |   21 +++++----------------
+ 2 files changed, 6 insertions(+), 17 deletions(-)
+
+diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
+index 4d21f5d..b0f59cd 100755
+--- a/vcl/source/gdi/outdev3.cxx
++++ b/vcl/source/gdi/outdev3.cxx
+@@ -3304,7 +3304,6 @@ ImplFontMetricData::ImplFontMetricData( const ImplFontSelectData& rFontSelData )
+ {
+     // initialize the members provided by the font request
+     mnWidth        = rFontSelData.mnWidth;
+-    mnSlant        = rFontSelData.GetSlant();
+     mnOrientation  = sal::static_int_cast<short>(rFontSelData.mnOrientation);
+ 
+     // intialize the used font name
+@@ -3329,6 +3328,7 @@ ImplFontMetricData::ImplFontMetricData( const ImplFontSelectData& rFontSelData )
+     mnDescent      = 0;
+     mnIntLeading   = 0;
+     mnExtLeading   = 0;
++    mnSlant        = 0;
+     mnMinKashida   = 0;
+ 
+     // reset metrics that are usually derived from the measurements
+diff --git a/vcl/unx/generic/gdi/salgdi3.cxx b/vcl/unx/generic/gdi/salgdi3.cxx
+index 7c94d40..0ced020 100644
+--- a/vcl/unx/generic/gdi/salgdi3.cxx
++++ b/vcl/unx/generic/gdi/salgdi3.cxx
+@@ -847,11 +847,6 @@ class FcPreMatchSubstititution
+ {
+ public:
+     bool FindFontSubstitute( ImplFontSelectData& ) const;
+-
+-private:
+-    typedef ::boost::unordered_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash >
+-        CachedFontMapType;
+-    mutable CachedFontMapType maCachedFontMap;
+ };
+ 
+ class FcGlyphFallbackSubstititution
+@@ -945,20 +940,14 @@ bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelD
+     ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
+         return false;
+ 
+-    CachedFontMapType::const_iterator itr = maCachedFontMap.find(rFontSelData.maTargetName);
+-    if (itr != maCachedFontMap.end())
+-    {
+-        // Cached substitution pair
+-        rFontSelData.maSearchName = itr->second;
+-        return true;
+-    }
+-
++    //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
+     rtl::OUString aDummy;
+     const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, aDummy );
+ 
+-    maCachedFontMap.insert(
+-        CachedFontMapType::value_type(rFontSelData.maTargetName, aOut.maSearchName));
+-
+     if( !aOut.maSearchName.Len() )
+         return false;
+ 
+-- 
+1.7.6.4
+
diff --git a/libreoffice.spec b/libreoffice.spec
index 842dd12..5523ad6 100644
--- a/libreoffice.spec
+++ b/libreoffice.spec
@@ -27,7 +27,7 @@ Summary:        Free Software Productivity Suite
 Name:           libreoffice
 Epoch:          1
 Version:        3.4.4.1
-Release:        2%{?dist}
+Release:        3%{?dist}
 License:        LGPLv3 and LGPLv2+ and BSD and (MPLv1.1 or GPLv2 or LGPLv2 or Netscape) and (CDDL or GPLv2) and Public Domain
 Group:          Applications/Productivity
 URL:            http://www.documentfoundation.org/develop
@@ -123,6 +123,8 @@ Patch27: 0001-Related-fdo-37195-migrationoo3-not-registered.patch
 Patch28: 0001-Resolves-rhbz-738255-avoid-crash-on-NULL-pointer.patch
 Patch29: 0001-avoid-using-com.sun.org-apis.patch
 Patch30: 0001-add-Oracle-Java-1.7.0-recognition.patch
+Patch31: 0001-Resolves-fdo-41556-font-sub-cache-of-nameA-nameB-is-.patch
+Patch32: 0001-Resolves-fdo-32665-handle-that-FreeSerif-lacks-some-.patch
 
 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 %define instdir %{_libdir}
@@ -795,6 +797,8 @@ mv -f redhat.soc extras/source/palettes/standard.soc
 %patch28 -p1 -b .rhbz738255-avoid-crash-on-NULL-pointer.patch
 %patch29 -p1 -b .avoid-using-com.sun.org-apis.patch
 %patch30 -p1 -b .add-Oracle-Java-1.7.0-recognition.patch
+%patch31 -p1 -b .fdo41556-font-sub-cache-of-nameA-nameB-is-.patch
+%patch32 -p1 -b .fdo32665-handle-that-FreeSerif-lacks-some-.patch
 
 # these are horribly incomplete--empty translations and copied english
 # strings with spattering of translated strings
@@ -2096,9 +2100,14 @@ update-desktop-database %{_datadir}/applications &> /dev/null || :
 %{basisinstdir}/program/kde-open-url
 
 %changelog
+* Thu Oct 27 2011 Caolán McNamara <caolanm at redhat.com> - 3.4.4.1-3
+- Resolves: rhbz#665800 missing glyph symbol shown when toggling bold/italic
+  for Sinhala text
+
 * Thu Oct 27 2011 Caolán McNamara <caolanm at redhat.com> - 3.4.4.1-2
 - possible fix for java 1.7.0 detection
 
+
 * Wed Oct 26 2011 David Tardon <dtardon at redhat.com> - 3.4.4.1-1
 - 3.4.4 rc1
 


More information about the scm-commits mailing list