1 |
From 58b48f188bbfd9a3382460d6de63848eb3db416d Mon Sep 17 00:00:00 2001 |
2 |
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com> |
3 |
Date: Thu, 27 Oct 2011 12:24:11 +0100 |
4 |
Subject: [PATCH] Resolves: fdo#32665 handle that FreeSerif lacks some glyphs |
5 |
in bold/italic |
6 |
|
7 |
FreeSerif lacks glyphs in bold/italic variants that it has in the normal one. A |
8 |
lot of our glyph fallback infrastructure, especially the caches don't expect |
9 |
that a normal variant of a font with extra emboldening or extra font skew can |
10 |
be a fallback for a bold/italic variant of itself which exists, but doesn't |
11 |
have the missing glyphs that the normal one does. |
12 |
|
13 |
We really need to improve our glyph/font caching, but we can get 90% of the |
14 |
way there by excluding such cases from the caches. |
15 |
--- |
16 |
vcl/generic/fontmanager/fontconfig.cxx | 18 ++++++++- |
17 |
vcl/generic/fontmanager/fontsubst.cxx | 6 +++- |
18 |
vcl/generic/glyphs/glyphcache.cxx | 7 ++++ |
19 |
vcl/inc/outfont.hxx | 19 ++++++++++ |
20 |
vcl/inc/vcl/fontmanager.hxx | 3 +- |
21 |
vcl/source/gdi/outdev3.cxx | 60 ++++++++++++++++++++++---------- |
22 |
6 files changed, 90 insertions(+), 23 deletions(-) |
23 |
|
24 |
diff --git a/vcl/generic/fontmanager/fontconfig.cxx b/vcl/generic/fontmanager/fontconfig.cxx |
25 |
index be91349..a4f5f7f 100644 |
26 |
--- a/vcl/unx/source/fontmanager/fontconfig.cxx |
27 |
+++ b/vcl/unx/source/fontmanager/fontconfig.cxx |
28 |
@@ -68,6 +68,9 @@ |
29 |
#ifndef FC_EMBOLDEN |
30 |
#define FC_EMBOLDEN "embolden" |
31 |
#endif |
32 |
+ #ifndef FC_MATRIX |
33 |
+ #define FC_MATRIX "matrix" |
34 |
+ #endif |
35 |
#ifndef FC_FONTFORMAT |
36 |
#define FC_FONTFORMAT "fontformat" |
37 |
#endif |
38 |
@@ -145,6 +148,7 @@ |
39 |
FcResult (*m_pFcPatternGetString)(const FcPattern*,const char*,int,FcChar8**); |
40 |
FcResult (*m_pFcPatternGetInteger)(const FcPattern*,const char*,int,int*); |
41 |
FcResult (*m_pFcPatternGetDouble)(const FcPattern*,const char*,int,double*); |
42 |
+ FcResult (*m_pFcPatternGetMatrix)(const FcPattern*,const char*,int,FcMatrix**); |
43 |
FcResult (*m_pFcPatternGetBool)(const FcPattern*,const char*,int,FcBool*); |
44 |
void (*m_pFcDefaultSubstitute)(FcPattern *); |
45 |
FcPattern* (*m_pFcFontSetMatch)(FcConfig*,FcFontSet**, int, FcPattern*,FcResult*); |
46 |
@@ -255,6 +259,9 @@ |
47 |
FcResult FcPatternGetDouble( const FcPattern* pPattern, const char* object, int n, double* s ) |
48 |
{ return m_pFcPatternGetDouble( pPattern, object, n, s ); } |
49 |
|
50 |
+ FcResult FcPatternGetMatrix( const FcPattern* pPattern, const char* object, int n, FcMatrix** s ) |
51 |
+ { return m_pFcPatternGetMatrix( pPattern, object, n, s ); } |
52 |
+ |
53 |
FcResult FcPatternGetBool( const FcPattern* pPattern, const char* object, int n, FcBool* s ) |
54 |
{ return m_pFcPatternGetBool( pPattern, object, n, s ); } |
55 |
FcBool FcConfigAppFontAddFile( FcConfig* pConfig, const FcChar8* pFileName ) |
56 |
@@ -381,6 +388,8 @@ |
57 |
loadSymbol( "FcPatternGetInteger" ); |
58 |
m_pFcPatternGetDouble = (FcResult(*)(const FcPattern*,const char*,int,double*)) |
59 |
loadSymbol( "FcPatternGetDouble" ); |
60 |
+ m_pFcPatternGetMatrix = (FcResult(*)(const FcPattern*,const char*,int,FcMatrix**)) |
61 |
+ loadSymbol( "FcPatternGetMatrix" ); |
62 |
m_pFcPatternGetBool = (FcResult(*)(const FcPattern*,const char*,int,FcBool*)) |
63 |
loadSymbol( "FcPatternGetBool" ); |
64 |
m_pFcConfigAppFontAddFile = (FcBool(*)(FcConfig*, const FcChar8*)) |
65 |
@@ -453,6 +462,7 @@ |
66 |
m_pFcPatternGetString && |
67 |
m_pFcPatternGetInteger && |
68 |
m_pFcPatternGetDouble && |
69 |
+ m_pFcPatternGetMatrix && |
70 |
m_pFcPatternGetBool && |
71 |
m_pFcConfigAppFontAddFile && |
72 |
m_pFcConfigAppFontAddDir && |
73 |
@@ -1260,7 +1270,7 @@ |
74 |
rtl::OUString PrintFontManager::Substitute(const rtl::OUString& rFontName, |
75 |
rtl::OUString& rMissingCodes, const rtl::OString &rLangAttrib, |
76 |
italic::type &rItalic, weight::type &rWeight, |
77 |
- width::type &rWidth, pitch::type &rPitch) const |
78 |
+ width::type &rWidth, pitch::type &rPitch, bool &rEmbolden, ItalicMatrix &rMatrix) const |
79 |
{ |
80 |
rtl::OUString aName; |
81 |
FontCfgWrapper& rWrapper = FontCfgWrapper::get(); |
82 |
@@ -1353,6 +1363,17 @@ |
83 |
rPitch = convertSpacing(val); |
84 |
if ( FcResultMatch == rWrapper.FcPatternGetInteger( pSet->fonts[0], FC_WIDTH, 0, &val)) |
85 |
rWidth = convertWidth(val); |
86 |
+ FcBool bEmbolden; |
87 |
+ if (FcResultMatch == rWrapper.FcPatternGetBool(pSet->fonts[0], FC_EMBOLDEN, 0, &bEmbolden)) |
88 |
+ rEmbolden = bEmbolden; |
89 |
+ FcMatrix *pMatrix = 0; |
90 |
+ if (FcResultMatch == rWrapper.FcPatternGetMatrix(pSet->fonts[0], FC_MATRIX, 0, &pMatrix)) |
91 |
+ { |
92 |
+ rMatrix.xx = pMatrix->xx; |
93 |
+ rMatrix.xy = pMatrix->xy; |
94 |
+ rMatrix.yx = pMatrix->yx; |
95 |
+ rMatrix.yy = pMatrix->yy; |
96 |
+ } |
97 |
} |
98 |
|
99 |
// update rMissingCodes by removing resolved unicodes |
100 |
diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx |
101 |
index 3bf2d07..2d187b1 100644 |
102 |
--- a/vcl/unx/source/gdi/salgdi3.cxx |
103 |
+++ b/vcl/unx/source/gdi/salgdi3.cxx |
104 |
@@ -1526,8 +1526,14 @@ |
105 |
} |
106 |
} |
107 |
|
108 |
+ bool bEmbolden = rFontSelData.mbEmbolden; |
109 |
+ ItalicMatrix aMatrix = rFontSelData.maItalicMatrix; |
110 |
+ |
111 |
const psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); |
112 |
- aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch); |
113 |
+ aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch, bEmbolden, aMatrix ); |
114 |
+ |
115 |
+ aRet.maItalicMatrix = aMatrix; |
116 |
+ aRet.mbEmbolden = bEmbolden; |
117 |
|
118 |
switch (eItalic) |
119 |
{ |
120 |
diff --git a/vcl/generic/glyphs/glyphcache.cxx b/vcl/generic/glyphs/glyphcache.cxx |
121 |
index 5322b65..fa712bb 100644 |
122 |
--- a/vcl/source/glyphs/glyphcache.cxx |
123 |
+++ b/vcl/source/glyphs/glyphcache.cxx |
124 |
@@ -163,6 +163,13 @@ bool GlyphCache::IFSD_Equal::operator()( const ImplFontSelectData& rA, const Imp |
125 |
!= STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName) |
126 |
return false; |
127 |
#endif |
128 |
+ |
129 |
+ if (rA.mbEmbolden != rB.mbEmbolden) |
130 |
+ return false; |
131 |
+ |
132 |
+ if (rA.maItalicMatrix != rB.maItalicMatrix) |
133 |
+ return false; |
134 |
+ |
135 |
return true; |
136 |
} |
137 |
|
138 |
diff --git a/vcl/inc/outfont.hxx b/vcl/inc/outfont.hxx |
139 |
index faf2b00..857d944 100644 |
140 |
--- a/vcl/inc/vcl/outfont.hxx |
141 |
+++ b/vcl/inc/vcl/outfont.hxx |
142 |
@@ -175,6 +191,9 @@ public: // TODO: change to private |
143 |
bool mbVertical; // vertical mode of requested font |
144 |
bool mbNonAntialiased; // true if antialiasing is disabled |
145 |
|
146 |
+ bool mbEmbolden; // Force emboldening |
147 |
+ ItalicMatrix maItalicMatrix; // Force matrix for slant |
148 |
+ |
149 |
const ImplFontData* mpFontData; // a matching ImplFontData object |
150 |
ImplFontEntry* mpFontEntry; // pointer to the resulting FontCache entry |
151 |
}; |
152 |
diff --git a/vcl/inc/vcl/fontmanager.hxx b/vcl/inc/vcl/fontmanager.hxx |
153 |
index 0af5e14..4a110ad 100644 |
154 |
--- a/vcl/inc/vcl/fontmanager.hxx |
155 |
+++ b/vcl/inc/vcl/fontmanager.hxx |
156 |
@@ -36,6 +36,7 @@ |
157 |
|
158 |
#include "vcl/dllapi.h" |
159 |
#include "vcl/helper.hxx" |
160 |
+#include "vcl/vclenum.hxx" |
161 |
|
162 |
#include "com/sun/star/lang/Locale.hpp" |
163 |
|
164 |
@@ -737,7 +738,7 @@ |
165 |
|
166 |
rtl::OUString Substitute( const rtl::OUString& rFontName, rtl::OUString& rMissingCodes, |
167 |
const rtl::OString& rLangAttrib, italic::type& rItalic, weight::type& rWeight, |
168 |
- width::type& rWidth, pitch::type& rPitch) const; |
169 |
+ width::type& rWidth, pitch::type& rPitch, bool &rEmboldening, ItalicMatrix &rMatrix) const; |
170 |
bool hasFontconfig() const { return m_bFontconfigSuccess; } |
171 |
|
172 |
int FreeTypeCharIndex( void *pFace, sal_uInt32 aChar ); |
173 |
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx |
174 |
index b0f59cd..3cc438c 100755 |
175 |
--- a/vcl/source/gdi/outdev3.cxx |
176 |
+++ b/vcl/source/gdi/outdev3.cxx |
177 |
@@ -865,9 +865,11 @@ bool ImplFontData::IsBetterMatch( const ImplFontSelectData& rFSD, FontMatchStatu |
178 |
|
179 |
if( rFSD.meWeight != WEIGHT_DONTKNOW ) |
180 |
{ |
181 |
- // if not bold prefer light fonts to bold fonts |
182 |
- int nReqWeight = (int)rFSD.meWeight; |
183 |
- if ( rFSD.meWeight > WEIGHT_MEDIUM ) |
184 |
+ // if not bold or requiring emboldening prefer light fonts to bold fonts |
185 |
+ FontWeight ePatternWeight = rFSD.mbEmbolden ? WEIGHT_NORMAL : rFSD.meWeight; |
186 |
+ |
187 |
+ int nReqWeight = (int)ePatternWeight; |
188 |
+ if ( ePatternWeight > WEIGHT_MEDIUM ) |
189 |
nReqWeight += 100; |
190 |
|
191 |
int nGivenWeight = (int)meWeight; |
192 |
@@ -897,14 +899,17 @@ bool ImplFontData::IsBetterMatch( const ImplFontSelectData& rFSD, FontMatchStatu |
193 |
nMatch += 150; |
194 |
} |
195 |
|
196 |
- if ( rFSD.meItalic == ITALIC_NONE ) |
197 |
+ // if requiring custom matrix to fake italic, prefer upright font |
198 |
+ FontItalic ePatternItalic = rFSD.maItalicMatrix != ItalicMatrix() ? ITALIC_NONE : rFSD.meItalic; |
199 |
+ |
200 |
+ if ( ePatternItalic == ITALIC_NONE ) |
201 |
{ |
202 |
if( meItalic == ITALIC_NONE ) |
203 |
nMatch += 900; |
204 |
} |
205 |
else |
206 |
{ |
207 |
- if( rFSD.meItalic == meItalic ) |
208 |
+ if( ePatternItalic == meItalic ) |
209 |
nMatch += 900; |
210 |
else if( meItalic != ITALIC_NONE ) |
211 |
nMatch += 600; |
212 |
@@ -1457,22 +1462,31 @@ ImplDevFontListData* ImplDevFontList::GetGlyphFallbackFont( ImplFontSelectData& |
213 |
else |
214 |
rFontSelData.maSearchName = String(); |
215 |
|
216 |
- // cache the result even if there was no match |
217 |
- for(;;) |
218 |
- { |
219 |
- if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) ) |
220 |
- rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); |
221 |
- if( nStrIndex >= aOldMissingCodes.getLength() ) |
222 |
- break; |
223 |
- cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex ); |
224 |
- } |
225 |
- if( rFontSelData.maSearchName.Len() != 0 ) |
226 |
+ //See fdo#32665 for an example. FreeSerif that has glyphs in normal |
227 |
+ //font, but not in the italic or bold version |
228 |
+ bool bSubSetOfFontRequiresPropertyFaking = rFontSelData.mbEmbolden || rFontSelData.maItalicMatrix != ItalicMatrix(); |
229 |
+ |
230 |
+ // cache the result even if there was no match, unless its from part of a font for which the properties need |
231 |
+ // to be faked. We need to rework this cache to take into account that fontconfig can return different fonts |
232 |
+ // for different input sizes, weights, etc. Basically the cache is way to naive |
233 |
+ if (!bSubSetOfFontRequiresPropertyFaking) |
234 |
{ |
235 |
- // remove cache entries that were still not resolved |
236 |
- for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) |
237 |
+ for(;;) |
238 |
{ |
239 |
- cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); |
240 |
- rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); |
241 |
+ if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) ) |
242 |
+ rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); |
243 |
+ if( nStrIndex >= aOldMissingCodes.getLength() ) |
244 |
+ break; |
245 |
+ cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex ); |
246 |
+ } |
247 |
+ if( rFontSelData.maSearchName.Len() != 0 ) |
248 |
+ { |
249 |
+ // remove cache entries that were still not resolved |
250 |
+ for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); ) |
251 |
+ { |
252 |
+ cChar = rMissingCodes.iterateCodePoints( &nStrIndex ); |
253 |
+ rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName ); |
254 |
+ } |
255 |
} |
256 |
} |
257 |
} |
258 |
@@ -2180,6 +2194,7 @@ ImplFontSelectData::ImplFontSelectData( const Font& rFont, |
259 |
meLanguage( rFont.GetLanguage() ), |
260 |
mbVertical( rFont.IsVertical() ), |
261 |
mbNonAntialiased( false ), |
262 |
+ mbEmbolden( false ), |
263 |
mpFontData( NULL ), |
264 |
mpFontEntry( NULL ) |
265 |
{ |
266 |
@@ -2215,6 +2230,7 @@ ImplFontSelectData::ImplFontSelectData( const ImplFontData& rFontData, |
267 |
meLanguage( 0 ), |
268 |
mbVertical( bVertical ), |
269 |
mbNonAntialiased( false ), |
270 |
+ mbEmbolden( false ), |
271 |
mpFontData( &rFontData ), |
272 |
mpFontEntry( NULL ) |
273 |
{ |
274 |
@@ -2297,6 +2313,12 @@ bool ImplFontCache::IFSD_Equal::operator()(const ImplFontSelectData& rA, const I |
275 |
return false; |
276 |
#endif |
277 |
|
278 |
+ if (rA.mbEmbolden != rB.mbEmbolden) |
279 |
+ return false; |
280 |
+ |
281 |
+ if (rA.maItalicMatrix != rB.maItalicMatrix) |
282 |
+ return false; |
283 |
+ |
284 |
return true; |
285 |
} |
286 |
|
287 |
--- a/vcl/inc/vcl/vclenum.hxx 2011-10-27 15:10:10.402317337 +0100 |
288 |
+++ b/vcl/inc/vcl/vclenum.hxx 2011-10-27 15:10:29.561528762 +0100 |
289 |
@@ -326,6 +326,22 @@ |
290 |
|
291 |
#endif |
292 |
|
293 |
+struct ItalicMatrix |
294 |
+{ |
295 |
+ double xx, xy, yx, yy; |
296 |
+ ItalicMatrix() : xx(1), xy(0), yx(0), yy(1) {} |
297 |
+}; |
298 |
+ |
299 |
+inline bool operator ==(const ItalicMatrix& a, const ItalicMatrix& b) |
300 |
+{ |
301 |
+ return a.xx == b.xx && a.xy == b.xy && a.yx == b.yx && a.yy == b.yy; |
302 |
+} |
303 |
+ |
304 |
+inline bool operator !=(const ItalicMatrix& a, const ItalicMatrix& b) |
305 |
+{ |
306 |
+ return a.xx != b.xx || a.xy != b.xy || a.yx != b.yx || a.yy != b.yy; |
307 |
+} |
308 |
+ |
309 |
#endif // _VCL_VCLENUM_HXX |
310 |
|
311 |
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |