diff options
author | Caolán McNamara <caolanm@redhat.com> | 2022-03-02 15:05:18 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-03-02 22:15:59 +0100 |
commit | 04f9a8957c04b8c5abaa58140328d2c83381f4ff (patch) | |
tree | 568ca45b4be46972ec4bb84bf85fd2c990095bf8 | |
parent | 8716721f4645078b04770271c71f7687a2b21e07 (diff) |
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 <caolanm@redhat.com>
-rw-r--r-- | vcl/inc/fontinstance.hxx | 16 | ||||
-rw-r--r-- | vcl/source/font/PhysicalFontCollection.cxx | 64 | ||||
-rw-r--r-- | vcl/source/font/fontinstance.cxx | 19 |
3 files changed, 64 insertions, 35 deletions
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 211e4e65bd57..139e4f133e88 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 ); } |