summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-03-02 15:05:18 +0000
committerAdolfo Jayme Barrientos <fitojb@ubuntu.com>2022-05-04 16:33:41 +0200
commitea7f625a83d9d9772c2bea2d52e0ed5f8622b6b6 (patch)
tree99fd8662bb73c0064bf1da4a0f47764a48dac16c
parentcb6f462b193c1e3f740dae4fd269b7e91b638d05 (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> (cherry picked from commit 04f9a8957c04b8c5abaa58140328d2c83381f4ff) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133724 Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
-rw-r--r--vcl/inc/fontinstance.hxx16
-rw-r--r--vcl/source/font/PhysicalFontCollection.cxx64
-rw-r--r--vcl/source/font/fontinstance.cxx19
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 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 );
}