vcl/inc/fontinstance.hxx                   |   16 +++++--
 vcl/source/font/PhysicalFontCollection.cxx |   64 +++++++++++++++++------------
 vcl/source/font/fontinstance.cxx           |   19 ++++++--
 3 files changed, 64 insertions(+), 35 deletions(-)

New commits:
commit ea7f625a83d9d9772c2bea2d52e0ed5f8622b6b6
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Wed Mar 2 15:05:18 2022 +0000
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Wed May 4 16:33:41 2022 +0200

    tdf#147283 allow 'fake italic/bold' glyph fallback results to be cached
    
    see also tdf#32665
    
    Change-Id: I69746b815fec3c73f87de4dc3fe84dbc91e61f0f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130877
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 04f9a8957c04b8c5abaa58140328d2c83381f4ff)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133724
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx
index 7fe31dbea828..d23c6a58548d 100644
--- a/vcl/inc/fontinstance.hxx
+++ b/vcl/inc/fontinstance.hxx
@@ -61,8 +61,10 @@ public: // TODO: make data members private
     Degree10        mnOrientation;          // text angle in 3600 system
     bool            mbInit;                 // true if maFontMetric member is 
valid
 
-    void            AddFallbackForUnicode( sal_UCS4, FontWeight eWeight, const 
OUString& rFontName );
-    bool            GetFallbackForUnicode( sal_UCS4, FontWeight eWeight, 
OUString* pFontName ) const;
+    void            AddFallbackForUnicode(sal_UCS4 cChar, FontWeight eWeight, 
const OUString& rFontName,
+                                          bool bEmbolden, const ItalicMatrix& 
rMatrix);
+    bool            GetFallbackForUnicode(sal_UCS4 cInChar, FontWeight 
eInWeight,
+                                          OUString* pOutFontName, bool* 
pOutEmbolden, ItalicMatrix* pOutItalicMatrix) const;
     void            IgnoreFallbackForUnicode( sal_UCS4, FontWeight eWeight, 
std::u16string_view rFontName );
 
     inline hb_font_t* GetHbFont();
@@ -93,10 +95,16 @@ protected:
     virtual hb_font_t* ImplInitHbFont() { assert(false); return 
hb_font_get_empty(); }
 
 private:
-    // cache of Unicode characters and replacement font names
+    struct MapEntry
+    {
+        OUString sFontName;
+        bool bEmbolden;
+        ItalicMatrix aItalicMatrix;
+    };
+    // cache of Unicode characters and replacement font names and attributes
     // TODO: a fallback map can be shared with many other ImplFontEntries
     // TODO: at least the ones which just differ in orientation, stretching or 
height
-    typedef ::std::unordered_map< ::std::pair<sal_UCS4,FontWeight>, OUString > 
UnicodeFallbackList;
+    typedef ::std::unordered_map< ::std::pair<sal_UCS4,FontWeight>, MapEntry > 
UnicodeFallbackList;
     std::unique_ptr<UnicodeFallbackList> mpUnicodeFallbackList;
     mutable ImplFontCache * mpFontCache;
     const vcl::font::FontSelectPattern m_aFontSelData;
diff --git a/vcl/source/font/PhysicalFontCollection.cxx 
b/vcl/source/font/PhysicalFontCollection.cxx
index 0cb503a7df54..5ced193aee8a 100644
--- a/vcl/source/font/PhysicalFontCollection.cxx
+++ b/vcl/source/font/PhysicalFontCollection.cxx
@@ -196,7 +196,10 @@ PhysicalFontFamily* 
PhysicalFontCollection::GetGlyphFallbackFont(FontSelectPatte
         while( nStrIndex < rMissingCodes.getLength() )
         {
             cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
-            bCached = pFontInstance->GetFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), &rFontSelData.maSearchName );
+            bCached = pFontInstance->GetFallbackForUnicode(cChar, 
rFontSelData.GetWeight(),
+                                                           
&rFontSelData.maSearchName,
+                                                           
&rFontSelData.mbEmbolden,
+                                                           
&rFontSelData.maItalicMatrix);
 
             // ignore entries which don't have a fallback
             if( !bCached || !rFontSelData.maSearchName.isEmpty() )
@@ -210,13 +213,20 @@ PhysicalFontFamily* 
PhysicalFontCollection::GetGlyphFallbackFont(FontSelectPatte
             int nRemainingLength = 0;
             std::unique_ptr<sal_UCS4[]> const pRemainingCodes(new 
sal_UCS4[rMissingCodes.getLength()]);
             OUString aFontName;
+            bool bEmbolden;
+            ItalicMatrix aMatrix;
 
             while( nStrIndex < rMissingCodes.getLength() )
             {
                 cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
-                bCached = pFontInstance->GetFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), &aFontName );
-                if( !bCached || (rFontSelData.maSearchName != aFontName) )
+                bCached = pFontInstance->GetFallbackForUnicode(cChar, 
rFontSelData.GetWeight(),
+                                                               &aFontName, 
&bEmbolden, &aMatrix);
+                if (!bCached || rFontSelData.maSearchName != aFontName ||
+                                rFontSelData.mbEmbolden != bEmbolden ||
+                                rFontSelData.maItalicMatrix != aMatrix)
+                {
                     pRemainingCodes[ nRemainingLength++ ] = cChar;
+                }
             }
             rMissingCodes = OUString( pRemainingCodes.get(), nRemainingLength 
);
         }
@@ -231,31 +241,33 @@ PhysicalFontFamily* 
PhysicalFontCollection::GetGlyphFallbackFont(FontSelectPatte
             else
                 rFontSelData.maSearchName.clear();
 
-            // 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)
+            // Cache the result even if there was no match
+            // See tdf#32665 and tdf#147283 for an example where FreeSerif 
that has glyphs that exist
+            // in the bold font, but not in the bold+italic version where 
fontconfig suggest the bold
+            // font + applying a matrix to fake the missing italic.
+            for(;;)
             {
-                for(;;)
-                {
-                     if( !pFontInstance->GetFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), &rFontSelData.maSearchName ) )
-                         pFontInstance->AddFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), rFontSelData.maSearchName );
-                     if( nStrIndex >= aOldMissingCodes.getLength() )
-                         break;
-                     cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
-                }
-                if( !rFontSelData.maSearchName.isEmpty() )
+                 if (!pFontInstance->GetFallbackForUnicode(cChar, 
rFontSelData.GetWeight(),
+                                                           
&rFontSelData.maSearchName,
+                                                           
&rFontSelData.mbEmbolden,
+                                                           
&rFontSelData.maItalicMatrix))
+                 {
+                     pFontInstance->AddFallbackForUnicode(cChar, 
rFontSelData.GetWeight(),
+                                                          
rFontSelData.maSearchName,
+                                                          
rFontSelData.mbEmbolden,
+                                                          
rFontSelData.maItalicMatrix);
+                 }
+                 if( nStrIndex >= aOldMissingCodes.getLength() )
+                     break;
+                 cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
+            }
+            if( !rFontSelData.maSearchName.isEmpty() )
+            {
+                // remove cache entries that were still not resolved
+                for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
                 {
-                    // remove cache entries that were still not resolved
-                    for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); 
)
-                    {
-                        cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
-                        pFontInstance->IgnoreFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), rFontSelData.maSearchName );
-                    }
+                    cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
+                    pFontInstance->IgnoreFallbackForUnicode( cChar, 
rFontSelData.GetWeight(), rFontSelData.maSearchName );
                 }
             }
         }
diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx
index 49b0593ce592..54464b101d72 100644
--- a/vcl/source/font/fontinstance.cxx
+++ b/vcl/source/font/fontinstance.cxx
@@ -118,14 +118,19 @@ void LogicalFontInstance::GetScale(double* nXScale, 
double* nYScale)
         *nXScale = nWidth / nUPEM;
 }
 
-void LogicalFontInstance::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight 
eWeight, const OUString& rFontName )
+void LogicalFontInstance::AddFallbackForUnicode(sal_UCS4 cChar, FontWeight 
eWeight, const OUString& rFontName,
+                                                bool bEmbolden, const 
ItalicMatrix& rMatrix)
 {
     if( !mpUnicodeFallbackList )
         mpUnicodeFallbackList.reset(new UnicodeFallbackList);
-    (*mpUnicodeFallbackList)[ std::pair< sal_UCS4, FontWeight >(cChar,eWeight) 
] = rFontName;
+    MapEntry& rEntry = (*mpUnicodeFallbackList)[ std::pair< sal_UCS4, 
FontWeight >(cChar,eWeight) ];
+    rEntry.sFontName = rFontName;
+    rEntry.bEmbolden = bEmbolden;
+    rEntry.aItalicMatrix = rMatrix;
 }
 
-bool LogicalFontInstance::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight 
eWeight, OUString* pFontName ) const
+bool LogicalFontInstance::GetFallbackForUnicode(sal_UCS4 cChar, FontWeight 
eWeight,
+                                                OUString* pFontName, bool* 
pEmbolden, ItalicMatrix* pMatrix) const
 {
     if( !mpUnicodeFallbackList )
         return false;
@@ -134,7 +139,10 @@ bool LogicalFontInstance::GetFallbackForUnicode( sal_UCS4 
cChar, FontWeight eWei
     if( it == mpUnicodeFallbackList->end() )
         return false;
 
-    *pFontName = (*it).second;
+    const MapEntry& rEntry = (*it).second;
+    *pFontName = rEntry.sFontName;
+    *pEmbolden = rEntry.bEmbolden;
+    *pMatrix = rEntry.aItalicMatrix;
     return true;
 }
 
@@ -143,7 +151,8 @@ void LogicalFontInstance::IgnoreFallbackForUnicode( 
sal_UCS4 cChar, FontWeight e
     UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( std::pair< 
sal_UCS4,FontWeight >(cChar,eWeight) );
     if( it == mpUnicodeFallbackList->end() )
         return;
-    if( (*it).second == rFontName )
+    const MapEntry& rEntry = (*it).second;
+    if (rEntry.sFontName == rFontName)
         mpUnicodeFallbackList->erase( it );
 }
 

Reply via email to