]>
Commit | Line | Data |
---|---|---|
519bda15 AM |
1 | From 0a2f2382541424726168804be2c90b91381608c6 Mon Sep 17 00:00:00 2001 |
2 | From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com> | |
3 | Date: Fri, 10 Jul 2015 13:22:32 +0200 | |
4 | Subject: [PATCH] Better handling of invalid font tables | |
5 | ||
6 | Specifically when reading files with broken cmap tables, we could | |
7 | get some undeterministic results. We handle this more gracefully | |
8 | by verifying that the offsets are sane and bailing out early if not. | |
9 | This replaces the current pattern throughout the font engine for | |
10 | consistency. | |
11 | ||
12 | This is a back-port of 4a1e5dbade4bab55f39bd368480dcca9a11e4b38 | |
13 | from Qt 5. | |
14 | ||
15 | Change-Id: If4172b9ef0808801c8e27ffaad962535afe572ed | |
16 | Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> | |
17 | Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> | |
18 | --- | |
19 | src/gui/text/qfontengine.cpp | 212 +++++++++++++++++++++++++++++---------- | |
20 | src/gui/text/qfontengine_mac.mm | 11 +- | |
21 | src/gui/text/qfontengine_mac_p.h | 1 + | |
22 | src/gui/text/qfontengine_p.h | 2 +- | |
23 | src/gui/text/qfontengine_qpa.cpp | 12 +-- | |
24 | src/gui/text/qfontengine_qpf.cpp | 12 +-- | |
25 | src/gui/text/qfontengine_s60.cpp | 9 +- | |
26 | src/gui/text/qfontengine_s60_p.h | 1 + | |
27 | src/gui/text/qfontengine_win.cpp | 22 ++-- | |
28 | src/gui/text/qfontengine_win_p.h | 1 + | |
29 | 10 files changed, 198 insertions(+), 85 deletions(-) | |
30 | ||
31 | diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp | |
32 | index 67b8798..3f7d831 100644 | |
33 | --- a/src/gui/text/qfontengine.cpp | |
34 | +++ b/src/gui/text/qfontengine.cpp | |
35 | @@ -69,6 +69,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr | |
36 | } | |
37 | } | |
38 | ||
39 | +template<typename T> | |
40 | +static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output) | |
41 | +{ | |
42 | + if (source + sizeof(T) > end) | |
43 | + return false; | |
44 | + | |
45 | + *output = qFromBigEndian<T>(source); | |
46 | + return true; | |
47 | +} | |
48 | + | |
49 | // Harfbuzz helper functions | |
50 | ||
51 | static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft) | |
52 | @@ -808,26 +818,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) | |
53 | return; | |
54 | ||
55 | const uchar *table = reinterpret_cast<const uchar *>(tab.constData()); | |
56 | + const uchar *end = table + tab.size(); | |
57 | + | |
58 | + quint16 version; | |
59 | + if (!qSafeFromBigEndian(table, end, &version)) | |
60 | + return; | |
61 | ||
62 | - unsigned short version = qFromBigEndian<quint16>(table); | |
63 | if (version != 0) { | |
64 | // qDebug("wrong version"); | |
65 | return; | |
66 | } | |
67 | ||
68 | - unsigned short numTables = qFromBigEndian<quint16>(table + 2); | |
69 | + quint16 numTables; | |
70 | + if (!qSafeFromBigEndian(table + 2, end, &numTables)) | |
71 | + return; | |
72 | + | |
73 | { | |
74 | int offset = 4; | |
75 | for(int i = 0; i < numTables; ++i) { | |
76 | - if (offset + 6 > tab.size()) { | |
77 | -// qDebug("offset out of bounds"); | |
78 | - goto end; | |
79 | - } | |
80 | const uchar *header = table + offset; | |
81 | ||
82 | - ushort version = qFromBigEndian<quint16>(header); | |
83 | - ushort length = qFromBigEndian<quint16>(header+2); | |
84 | - ushort coverage = qFromBigEndian<quint16>(header+4); | |
85 | + quint16 version; | |
86 | + if (!qSafeFromBigEndian(header, end, &version)) | |
87 | + goto end; | |
88 | + | |
89 | + quint16 length; | |
90 | + if (!qSafeFromBigEndian(header + 2, end, &length)) | |
91 | + goto end; | |
92 | + | |
93 | + quint16 coverage; | |
94 | + if (!qSafeFromBigEndian(header + 4, end, &coverage)) | |
95 | + goto end; | |
96 | + | |
97 | // qDebug("subtable: version=%d, coverage=%x",version, coverage); | |
98 | if(version == 0 && coverage == 0x0001) { | |
99 | if (offset + length > tab.size()) { | |
100 | @@ -836,7 +858,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) | |
101 | } | |
102 | const uchar *data = table + offset + 6; | |
103 | ||
104 | - ushort nPairs = qFromBigEndian<quint16>(data); | |
105 | + quint16 nPairs; | |
106 | + if (!qSafeFromBigEndian(data, end, &nPairs)) | |
107 | + goto end; | |
108 | + | |
109 | if(nPairs * 6 + 8 > length - 6) { | |
110 | // qDebug("corrupt table!"); | |
111 | // corrupt table | |
112 | @@ -846,8 +871,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) | |
113 | int off = 8; | |
114 | for(int i = 0; i < nPairs; ++i) { | |
115 | QFontEngine::KernPair p; | |
116 | - p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2); | |
117 | - p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor; | |
118 | + | |
119 | + quint16 tmp; | |
120 | + if (!qSafeFromBigEndian(data + off, end, &tmp)) | |
121 | + goto end; | |
122 | + | |
123 | + p.left_right = uint(tmp) << 16; | |
124 | + if (!qSafeFromBigEndian(data + off + 2, end, &tmp)) | |
125 | + goto end; | |
126 | + | |
127 | + p.left_right |= tmp; | |
128 | + | |
129 | + if (!qSafeFromBigEndian(data + off + 4, end, &tmp)) | |
130 | + goto end; | |
131 | + | |
132 | + p.adjust = QFixed(int(short(tmp))) / scalingFactor; | |
133 | kerning_pairs.append(p); | |
134 | off += 6; | |
135 | } | |
136 | @@ -872,26 +910,31 @@ int QFontEngine::glyphCount() const | |
137 | QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p')); | |
138 | if (maxpTable.size() < 6) | |
139 | return 0; | |
140 | - return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4)); | |
141 | + | |
142 | + const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4); | |
143 | + const uchar *end = source + maxpTable.size(); | |
144 | + | |
145 | + quint16 count = 0; | |
146 | + qSafeFromBigEndian(source, end, &count); | |
147 | + return count; | |
148 | } | |
149 | ||
150 | const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize) | |
151 | { | |
152 | const uchar *header = table; | |
153 | - if (tableSize < 4) | |
154 | - return 0; | |
155 | - | |
156 | const uchar *endPtr = table + tableSize; | |
157 | ||
158 | // version check | |
159 | - if (qFromBigEndian<quint16>(header) != 0) | |
160 | + quint16 version; | |
161 | + if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0) | |
162 | return 0; | |
163 | ||
164 | - unsigned short numTables = qFromBigEndian<quint16>(header + 2); | |
165 | - const uchar *maps = table + 4; | |
166 | - if (maps + 8 * numTables > endPtr) | |
167 | + quint16 numTables; | |
168 | + if (!qSafeFromBigEndian(header + 2, endPtr, &numTables)) | |
169 | return 0; | |
170 | ||
171 | + const uchar *maps = table + 4; | |
172 | + | |
173 | enum { | |
174 | Invalid, | |
175 | AppleRoman, | |
176 | @@ -906,8 +949,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy | |
177 | int tableToUse = -1; | |
178 | int score = Invalid; | |
179 | for (int n = 0; n < numTables; ++n) { | |
180 | - const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n); | |
181 | - const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2); | |
182 | + quint16 platformId; | |
183 | + if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId)) | |
184 | + return 0; | |
185 | + | |
186 | + quint16 platformSpecificId; | |
187 | + if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId)) | |
188 | + return 0; | |
189 | + | |
190 | switch (platformId) { | |
191 | case 0: // Unicode | |
192 | if (score < Unicode && | |
193 | @@ -961,20 +1010,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy | |
194 | resolveTable: | |
195 | *isSymbolFont = (symbolTable > -1); | |
196 | ||
197 | - unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4); | |
198 | + quint32 unicode_table; | |
199 | + if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table)) | |
200 | + return 0; | |
201 | ||
202 | - if (!unicode_table || unicode_table + 8 > tableSize) | |
203 | + if (!unicode_table) | |
204 | return 0; | |
205 | ||
206 | // get the header of the unicode table | |
207 | header = table + unicode_table; | |
208 | ||
209 | - unsigned short format = qFromBigEndian<quint16>(header); | |
210 | - unsigned int length; | |
211 | - if(format < 8) | |
212 | - length = qFromBigEndian<quint16>(header + 2); | |
213 | - else | |
214 | - length = qFromBigEndian<quint32>(header + 4); | |
215 | + quint16 format; | |
216 | + if (!qSafeFromBigEndian(header, endPtr, &format)) | |
217 | + return 0; | |
218 | + | |
219 | + quint32 length; | |
220 | + if (format < 8) { | |
221 | + quint16 tmp; | |
222 | + if (!qSafeFromBigEndian(header + 2, endPtr, &tmp)) | |
223 | + return 0; | |
224 | + length = tmp; | |
225 | + } else { | |
226 | + if (!qSafeFromBigEndian(header + 4, endPtr, &length)) | |
227 | + return 0; | |
228 | + } | |
229 | ||
230 | if (table + unicode_table + length > endPtr) | |
231 | return 0; | |
232 | @@ -989,7 +1048,7 @@ resolveTable: | |
233 | // Check that none of the latin1 range are in the unicode table | |
234 | bool unicodeTableHasLatin1 = false; | |
235 | for (int uc=0x00; uc<0x100; ++uc) { | |
236 | - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { | |
237 | + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { | |
238 | unicodeTableHasLatin1 = true; | |
239 | break; | |
240 | } | |
241 | @@ -999,7 +1058,7 @@ resolveTable: | |
242 | bool unicodeTableHasSymbols = false; | |
243 | if (!unicodeTableHasLatin1) { | |
244 | for (int uc=0xf000; uc<0xf100; ++uc) { | |
245 | - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { | |
246 | + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { | |
247 | unicodeTableHasSymbols = true; | |
248 | break; | |
249 | } | |
250 | @@ -1017,12 +1076,17 @@ resolveTable: | |
251 | return table + unicode_table; | |
252 | } | |
253 | ||
254 | -quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) | |
255 | +quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode) | |
256 | { | |
257 | - unsigned short format = qFromBigEndian<quint16>(cmap); | |
258 | + const uchar *end = cmap + cmapSize; | |
259 | + quint16 format; | |
260 | + if (!qSafeFromBigEndian(cmap, end, &format)) | |
261 | + return 0; | |
262 | + | |
263 | if (format == 0) { | |
264 | - if (unicode < 256) | |
265 | - return (int) *(cmap+6+unicode); | |
266 | + const uchar *ptr = cmap + 6 + unicode; | |
267 | + if (unicode < 256 && ptr < end) | |
268 | + return quint32(*ptr); | |
269 | } else if (format == 4) { | |
270 | /* some fonts come with invalid cmap tables, where the last segment | |
271 | specified end = start = rangeoffset = 0xffff, delta = 0x0001 | |
272 | @@ -1031,25 +1095,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) | |
273 | */ | |
274 | if(unicode >= 0xffff) | |
275 | return 0; | |
276 | - quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6); | |
277 | + | |
278 | + quint16 segCountX2; | |
279 | + if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2)) | |
280 | + return 0; | |
281 | + | |
282 | const unsigned char *ends = cmap + 14; | |
283 | + | |
284 | int i = 0; | |
285 | - for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {} | |
286 | + for (; i < segCountX2/2; ++i) { | |
287 | + quint16 codePoint; | |
288 | + if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint)) | |
289 | + return 0; | |
290 | + if (codePoint >= unicode) | |
291 | + break; | |
292 | + } | |
293 | ||
294 | const unsigned char *idx = ends + segCountX2 + 2 + 2*i; | |
295 | - quint16 startIndex = qFromBigEndian<quint16>(idx); | |
296 | ||
297 | + quint16 startIndex; | |
298 | + if (!qSafeFromBigEndian(idx, end, &startIndex)) | |
299 | + return 0; | |
300 | if (startIndex > unicode) | |
301 | return 0; | |
302 | ||
303 | idx += segCountX2; | |
304 | - qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx); | |
305 | + | |
306 | + quint16 tmp; | |
307 | + if (!qSafeFromBigEndian(idx, end, &tmp)) | |
308 | + return 0; | |
309 | + qint16 idDelta = qint16(tmp); | |
310 | + | |
311 | idx += segCountX2; | |
312 | - quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx); | |
313 | + | |
314 | + quint16 idRangeoffset_t; | |
315 | + if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t)) | |
316 | + return 0; | |
317 | ||
318 | quint16 glyphIndex; | |
319 | if (idRangeoffset_t) { | |
320 | - quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx); | |
321 | + quint16 id; | |
322 | + if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id)) | |
323 | + return 0; | |
324 | + | |
325 | if (id) | |
326 | glyphIndex = (idDelta + id) % 0x10000; | |
327 | else | |
328 | @@ -1059,13 +1147,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) | |
329 | } | |
330 | return glyphIndex; | |
331 | } else if (format == 6) { | |
332 | - quint16 tableSize = qFromBigEndian<quint16>(cmap + 2); | |
333 | + quint16 tableSize; | |
334 | + if (!qSafeFromBigEndian(cmap + 2, end, &tableSize)) | |
335 | + return 0; | |
336 | ||
337 | - quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6); | |
338 | + quint16 firstCode6; | |
339 | + if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6)) | |
340 | + return 0; | |
341 | if (unicode < firstCode6) | |
342 | return 0; | |
343 | ||
344 | - quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8); | |
345 | + quint16 entryCount6; | |
346 | + if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6)) | |
347 | + return 0; | |
348 | if (entryCount6 * 2 + 10 > tableSize) | |
349 | return 0; | |
350 | ||
351 | @@ -1074,9 +1168,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) | |
352 | return 0; | |
353 | ||
354 | quint16 entryIndex6 = unicode - firstCode6; | |
355 | - return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2)); | |
356 | + | |
357 | + quint16 index = 0; | |
358 | + qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index); | |
359 | + return index; | |
360 | } else if (format == 12) { | |
361 | - quint32 nGroups = qFromBigEndian<quint32>(cmap + 12); | |
362 | + quint32 nGroups; | |
363 | + if (!qSafeFromBigEndian(cmap + 12, end, &nGroups)) | |
364 | + return 0; | |
365 | ||
366 | cmap += 16; // move to start of groups | |
367 | ||
368 | @@ -1084,13 +1183,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) | |
369 | while (left <= right) { | |
370 | int middle = left + ( ( right - left ) >> 1 ); | |
371 | ||
372 | - quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle); | |
373 | + quint32 startCharCode; | |
374 | + if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode)) | |
375 | + return 0; | |
376 | + | |
377 | if(unicode < startCharCode) | |
378 | right = middle - 1; | |
379 | else { | |
380 | - quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4); | |
381 | - if(unicode <= endCharCode) | |
382 | - return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode; | |
383 | + quint32 endCharCode; | |
384 | + if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode)) | |
385 | + return 0; | |
386 | + | |
387 | + if (unicode <= endCharCode) { | |
388 | + quint32 index; | |
389 | + if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index)) | |
390 | + return 0; | |
391 | + | |
392 | + return index + unicode - startCharCode; | |
393 | + } | |
394 | left = middle + 1; | |
395 | } | |
396 | } | |
397 | diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm | |
398 | index ba01f4c..460aa5f 100644 | |
399 | --- a/src/gui/text/qfontengine_mac.mm | |
400 | +++ b/src/gui/text/qfontengine_mac.mm | |
401 | @@ -625,7 +625,7 @@ bool QFontEngineMacMulti::canRender(const QChar *string, int len) | |
402 | } | |
403 | ||
404 | QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine) | |
405 | - : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false) | |
406 | + : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false), cmapSize(0) | |
407 | { | |
408 | fontDef = def; | |
409 | ATSUCreateAndCopyStyle(baseStyle, &style); | |
410 | @@ -747,22 +747,21 @@ bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph | |
411 | { | |
412 | if (!cmap) { | |
413 | cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); | |
414 | - int size = 0; | |
415 | - cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &size); | |
416 | + cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &cmapSize); | |
417 | if (!cmap) | |
418 | return false; | |
419 | } | |
420 | if (symbolCMap) { | |
421 | for (int i = 0; i < len; ++i) { | |
422 | unsigned int uc = getChar(str, i, len); | |
423 | - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); | |
424 | + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
425 | if(!glyphs->glyphs[i] && uc < 0x100) | |
426 | - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
427 | + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
428 | } | |
429 | } else { | |
430 | for (int i = 0; i < len; ++i) { | |
431 | unsigned int uc = getChar(str, i, len); | |
432 | - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); | |
433 | + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
434 | } | |
435 | } | |
436 | ||
437 | diff --git a/src/gui/text/qfontengine_mac_p.h b/src/gui/text/qfontengine_mac_p.h | |
438 | index 7d70c24..844d421 100644 | |
439 | --- a/src/gui/text/qfontengine_mac_p.h | |
440 | +++ b/src/gui/text/qfontengine_mac_p.h | |
441 | @@ -108,6 +108,7 @@ private: | |
442 | qreal m_maxCharWidth; | |
443 | QFixed m_xHeight; | |
444 | QFixed m_averageCharWidth; | |
445 | + mutable int cmapSize; | |
446 | }; | |
447 | ||
448 | class QFontEngineMacMulti : public QFontEngineMulti | |
449 | diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h | |
450 | index f29ac47..9c3435f 100644 | |
451 | --- a/src/gui/text/qfontengine_p.h | |
452 | +++ b/src/gui/text/qfontengine_p.h | |
453 | @@ -247,7 +247,7 @@ public: | |
454 | QFontEngineGlyphCache *glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const; | |
455 | ||
456 | static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); | |
457 | - static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); | |
458 | + static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode); | |
459 | ||
460 | static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); | |
461 | ||
462 | diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp | |
463 | index 04f7b76..011d233 100644 | |
464 | --- a/src/gui/text/qfontengine_qpa.cpp | |
465 | +++ b/src/gui/text/qfontengine_qpa.cpp | |
466 | @@ -358,9 +358,9 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph | |
467 | unsigned int uc = getChar(str, i, len); | |
468 | if (mirrored) | |
469 | uc = QChar::mirroredChar(uc); | |
470 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
471 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
472 | if(!glyphs->glyphs[glyph_pos] && uc < 0x100) | |
473 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
474 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
475 | ++glyph_pos; | |
476 | } | |
477 | } else { | |
478 | @@ -368,7 +368,7 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph | |
479 | unsigned int uc = getChar(str, i, len); | |
480 | if (mirrored) | |
481 | uc = QChar::mirroredChar(uc); | |
482 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
483 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
484 | #if 0 && defined(DEBUG_FONTENGINE) | |
485 | QChar c(uc); | |
486 | if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) | |
487 | @@ -511,16 +511,16 @@ bool QFontEngineQPA::canRender(const QChar *string, int len) | |
488 | if (symbol) { | |
489 | for (int i = 0; i < len; ++i) { | |
490 | unsigned int uc = getChar(string, i, len); | |
491 | - glyph_t g = getTrueTypeGlyphIndex(cmap, uc); | |
492 | + glyph_t g = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
493 | if(!g && uc < 0x100) | |
494 | - g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
495 | + g = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
496 | if (!g) | |
497 | return false; | |
498 | } | |
499 | } else { | |
500 | for (int i = 0; i < len; ++i) { | |
501 | unsigned int uc = getChar(string, i, len); | |
502 | - if (!getTrueTypeGlyphIndex(cmap, uc)) | |
503 | + if (!getTrueTypeGlyphIndex(cmap, cmapSize, uc)) | |
504 | return false; | |
505 | } | |
506 | } | |
507 | diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp | |
508 | index 8d5e71b..9087cff 100644 | |
509 | --- a/src/gui/text/qfontengine_qpf.cpp | |
510 | +++ b/src/gui/text/qfontengine_qpf.cpp | |
511 | @@ -577,9 +577,9 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph | |
512 | if (symbol) { | |
513 | for (int i = 0; i < len; ++i) { | |
514 | unsigned int uc = getChar(str, i, len); | |
515 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
516 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
517 | if(!glyphs->glyphs[glyph_pos] && uc < 0x100) | |
518 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
519 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
520 | ++glyph_pos; | |
521 | } | |
522 | } else { | |
523 | @@ -587,7 +587,7 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph | |
524 | unsigned int uc = getChar(str, i, len); | |
525 | if (mirrored) | |
526 | uc = QChar::mirroredChar(uc); | |
527 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
528 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
529 | #if 0 && defined(DEBUG_FONTENGINE) | |
530 | QChar c(uc); | |
531 | if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) | |
532 | @@ -786,16 +786,16 @@ bool QFontEngineQPF::canRender(const QChar *string, int len) | |
533 | if (symbol) { | |
534 | for (int i = 0; i < len; ++i) { | |
535 | unsigned int uc = getChar(string, i, len); | |
536 | - glyph_t g = getTrueTypeGlyphIndex(cmap, uc); | |
537 | + glyph_t g = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
538 | if(!g && uc < 0x100) | |
539 | - g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
540 | + g = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
541 | if (!g) | |
542 | return false; | |
543 | } | |
544 | } else { | |
545 | for (int i = 0; i < len; ++i) { | |
546 | unsigned int uc = getChar(string, i, len); | |
547 | - if (!getTrueTypeGlyphIndex(cmap, uc)) | |
548 | + if (!getTrueTypeGlyphIndex(cmap, cmapSize, uc)) | |
549 | return false; | |
550 | } | |
551 | } | |
552 | diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp | |
553 | index 1da501a..b2bb561 100644 | |
554 | --- a/src/gui/text/qfontengine_s60.cpp | |
555 | +++ b/src/gui/text/qfontengine_s60.cpp | |
556 | @@ -77,6 +77,7 @@ QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont | |
557 | : m_cFont(cFont) | |
558 | , m_symbolCMap(false) | |
559 | , m_openFont(openFont) | |
560 | + , m_cmapSize(0) | |
561 | { | |
562 | if (!symbianFontTableApiAvailable()) { | |
563 | TAny *trueTypeExtension = NULL; | |
564 | @@ -161,10 +162,9 @@ const uchar *QSymbianTypeFaceExtras::cmap() const | |
565 | { | |
566 | if (m_cmapTable.isNull()) { | |
567 | const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); | |
568 | - int size = 0; | |
569 | const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *> | |
570 | - (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size); | |
571 | - m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size); | |
572 | + (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &m_cmapSize); | |
573 | + m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), m_cmapSize); | |
574 | } | |
575 | return reinterpret_cast<const uchar *>(m_cmapTable.constData()); | |
576 | } | |
577 | @@ -324,6 +324,7 @@ bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout | |
578 | for (int i = 0; i < len; ++i) { | |
579 | const unsigned int uc = getChar(characters, i, len); | |
580 | *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, | |
581 | + m_cmapSize, | |
582 | (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc); | |
583 | } | |
584 | ||
585 | @@ -463,7 +464,7 @@ bool QFontEngineS60::canRender(const QChar *string, int len) | |
586 | const unsigned char *cmap = m_extras->cmap(); | |
587 | for (int i = 0; i < len; ++i) { | |
588 | const unsigned int uc = getChar(string, i, len); | |
589 | - if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0) | |
590 | + if (QFontEngine::getTrueTypeGlyphIndex(cmap, m_cmapSize, uc) == 0) | |
591 | return false; | |
592 | } | |
593 | return true; | |
594 | diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h | |
595 | index 17e2207..9e38570 100644 | |
596 | --- a/src/gui/text/qfontengine_s60_p.h | |
597 | +++ b/src/gui/text/qfontengine_s60_p.h | |
598 | @@ -93,6 +93,7 @@ private: | |
599 | // the Font Table API | |
600 | COpenFont *m_openFont; | |
601 | mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; | |
602 | + mutable int m_cmapSize; | |
603 | }; | |
604 | ||
605 | class QFontEngineS60 : public QFontEngine | |
606 | diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp | |
607 | index bd9a437..6ad5eb4 100644 | |
608 | --- a/src/gui/text/qfontengine_win.cpp | |
609 | +++ b/src/gui/text/qfontengine_win.cpp | |
610 | @@ -215,9 +215,8 @@ void QFontEngineWin::getCMap() | |
611 | bool symb = false; | |
612 | if (ttf) { | |
613 | cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p'))); | |
614 | - int size = 0; | |
615 | cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), | |
616 | - cmapTable.size(), &symb, &size); | |
617 | + cmapTable.size(), &symb, &cmapSize); | |
618 | } | |
619 | if (!cmap) { | |
620 | ttf = false; | |
621 | @@ -263,14 +262,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout | |
622 | if (symbol) { | |
623 | for (; i < numChars; ++i, ++glyph_pos) { | |
624 | unsigned int uc = getChar(str, i, numChars); | |
625 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
626 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
627 | if (!glyphs->glyphs[glyph_pos] && uc < 0x100) | |
628 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
629 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
630 | } | |
631 | } else if (ttf) { | |
632 | for (; i < numChars; ++i, ++glyph_pos) { | |
633 | unsigned int uc = getChar(str, i, numChars); | |
634 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc)); | |
635 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, QChar::mirroredChar(uc)); | |
636 | } | |
637 | } else { | |
638 | #endif | |
639 | @@ -296,14 +295,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout | |
640 | if (symbol) { | |
641 | for (; i < numChars; ++i, ++glyph_pos) { | |
642 | unsigned int uc = getChar(str, i, numChars); | |
643 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
644 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
645 | if(!glyphs->glyphs[glyph_pos] && uc < 0x100) | |
646 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); | |
647 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); | |
648 | } | |
649 | } else if (ttf) { | |
650 | for (; i < numChars; ++i, ++glyph_pos) { | |
651 | unsigned int uc = getChar(str, i, numChars); | |
652 | - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); | |
653 | + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); | |
654 | } | |
655 | } else { | |
656 | #endif | |
657 | @@ -335,6 +334,7 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont | |
658 | _name = name; | |
659 | ||
660 | cmap = 0; | |
661 | + cmapSize = 0; | |
662 | hfont = _hfont; | |
663 | logfont = lf; | |
664 | HDC hdc = shared_dc(); | |
665 | @@ -811,9 +811,9 @@ bool QFontEngineWin::canRender(const QChar *string, int len) | |
666 | if (symbol) { | |
667 | for (int i = 0; i < len; ++i) { | |
668 | unsigned int uc = getChar(string, i, len); | |
669 | - if (getTrueTypeGlyphIndex(cmap, uc) == 0) { | |
670 | + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0) { | |
671 | if (uc < 0x100) { | |
672 | - if (getTrueTypeGlyphIndex(cmap, uc + 0xf000) == 0) | |
673 | + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000) == 0) | |
674 | return false; | |
675 | } else { | |
676 | return false; | |
677 | @@ -823,7 +823,7 @@ bool QFontEngineWin::canRender(const QChar *string, int len) | |
678 | } else if (ttf) { | |
679 | for (int i = 0; i < len; ++i) { | |
680 | unsigned int uc = getChar(string, i, len); | |
681 | - if (getTrueTypeGlyphIndex(cmap, uc) == 0) | |
682 | + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0) | |
683 | return false; | |
684 | } | |
685 | } else { | |
686 | diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h | |
687 | index 0c8df72..27f0355 100644 | |
688 | --- a/src/gui/text/qfontengine_win_p.h | |
689 | +++ b/src/gui/text/qfontengine_win_p.h | |
690 | @@ -144,6 +144,7 @@ public: | |
691 | mutable uint widthCacheSize; | |
692 | mutable QFixed *designAdvances; | |
693 | mutable int designAdvancesSize; | |
694 | + int cmapSize; | |
695 | ||
696 | private: | |
697 | bool hasCFFTable() const; | |
698 | -- | |
699 | 2.8.1 | |
700 |