qfontengine.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qfontengine.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8-
9-
10-
11static inline bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b)-
12{-
13 if (a.type() <= QTransform::TxTranslate && b.type() <= QTransform::TxTranslate) {-
14 return true;-
15 } else {-
16-
17-
18 ((!(a.type() < QTransform::TxProject)) ? qt_assert("a.type() < QTransform::TxProject",__FILE__,6874) : qt_noop());-
19 ((!(b.type() < QTransform::TxProject)) ? qt_assert("b.type() < QTransform::TxProject",__FILE__,6975) : qt_noop());-
20-
21 return a.m11() == b.m11()-
22 && a.m12() == b.m12()-
23 && a.m21() == b.m21()-
24 && a.m22() == b.m22();-
25 }-
26}-
27-
28template<typename T>-
29static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)-
30{-
31 if (source + sizeof(T) > end)-
32 return false;-
33-
34 *output = qFromBigEndian<T>(source);-
35 return true;-
36}-
37-
38-
39-
40-
41namespace { namespace Q_QGS_useHarfbuzzNG { typedef bool Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type (qgetenv("QT_HARFBUZZ") != "old"))) : value (qgetenv("QT_HARFBUZZ") != "old") { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<bool, Q_QGS_useHarfbuzzNG::innerFunction, Q_QGS_useHarfbuzzNG::guard> useHarfbuzzNG;-
42-
43bool qt_useHarfbuzzNG()-
44{-
45 return *useHarfbuzzNG();-
46}-
47-
48-
49static_assert(bool(sizeof(HB_Glyph) == sizeof(glyph_t)), "sizeof(HB_Glyph) == sizeof(glyph_t)");-
50static_assert(bool(sizeof(HB_Fixed) == sizeof(QFixed)), "sizeof(HB_Fixed) == sizeof(QFixed)");-
51-
52static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)-
53{-
54 QFontEngine *fe = (QFontEngine *)font->userData;-
55-
56 const QChar *str = reinterpret_cast<const QChar *>(string);-
57-
58 QGlyphLayout qglyphs;-
59 qglyphs.numGlyphs = *numGlyphs;-
60 qglyphs.glyphs = glyphs;-
61 int nGlyphs = *numGlyphs;-
62 bool result = fe->stringToCMap(str, length, &qglyphs, &nGlyphs, QFontEngine::GlyphIndicesOnly);-
63 *numGlyphs = nGlyphs;-
64-
65 if (rightToLeft && result && !fe->symbol) {-
66 QStringIterator it(str, str + length);-
67 while (it.hasNext()) {-
68 const uint ucs4 = it.next();-
69 const uint mirrored = QChar::mirroredChar(ucs4);-
70 if (__builtin_expect(!!(mirrored != ucs4), false))-
71 *glyphs = fe->glyphIndex(mirrored);-
72 ++glyphs;-
73 }-
74 }-
75-
76 return result;-
77}-
78-
79static void hb_getAdvances(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags)-
80{-
81 QFontEngine *fe = (QFontEngine *)font->userData;-
82-
83 QGlyphLayout qglyphs;-
84 qglyphs.numGlyphs = numGlyphs;-
85 qglyphs.glyphs = const_cast<glyph_t *>(glyphs);-
86 qglyphs.advances = reinterpret_cast<QFixed *>(advances);-
87-
88 fe->recalcAdvances(&qglyphs, (flags & HB_ShaperFlag_UseDesignMetrics) ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags(0));-
89}-
90-
91static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 length)-
92{-
93 QFontEngine *fe = (QFontEngine *)font->userData;-
94 return fe->canRender(reinterpret_cast<const QChar *>(string), length);-
95}-
96-
97static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)-
98{-
99 QFontEngine *fe = (QFontEngine *)font->userData;-
100 glyph_metrics_t m = fe->boundingBox(glyph);-
101 metrics->x = m.x.value();-
102 metrics->y = m.y.value();-
103 metrics->width = m.width.value();-
104 metrics->height = m.height.value();-
105 metrics->xOffset = m.xoff.value();-
106 metrics->yOffset = m.yoff.value();-
107}-
108-
109static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)-
110{-
111 if (metric == HB_FontAscent) {-
112 QFontEngine *fe = (QFontEngine *)font->userData;-
113 return fe->ascent().value();-
114 }-
115 return 0;-
116}-
117-
118int QFontEngine::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints)-
119{-
120 (void)glyph;-
121 (void)flags;-
122 (void)point;-
123 (void)xpos;-
124 (void)ypos;-
125 (void)nPoints;-
126 return Err_Not_Covered;-
127}-
128-
129static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)-
130{-
131 QFontEngine *fe = (QFontEngine *)font->userData;-
132 return (HB_Error)fe->getPointInOutline(glyph, flags, point, (QFixed *)xpos, (QFixed *)ypos, (quint32 *)nPoints);-
133}-
134-
135static const HB_FontClass hb_fontClass = {-
136 hb_stringToGlyphs, hb_getAdvances, hb_canRender, hb_getPointInOutline,-
137 hb_getGlyphMetrics, hb_getFontMetric-
138};-
139-
140static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)-
141{-
142 QFontEngine::FaceData *data = (QFontEngine::FaceData *)font;-
143 ((!(data)) ? qt_assert("data",__FILE__,193199) : qt_noop());-
144-
145 qt_get_font_table_func_t get_font_table = data->get_font_table;-
146 ((!(get_font_table)) ? qt_assert("get_font_table",__FILE__,196202) : qt_noop());-
147-
148 if (!get_font_table(data->user_data, tableTag, buffer, length))-
149 return HB_Err_Invalid_Argument;-
150 return HB_Err_Ok;-
151}-
152-
153static void hb_freeFace(void *face)-
154{-
155 qHBFreeFace((HB_Face)face);-
156}-
157-
158-
159static bool qt_get_font_table_default(void *user_data, uint tag, uchar *buffer, uint *length)-
160{-
161 QFontEngine *fe = (QFontEngine *)user_data;-
162 return fe->getSfntTableData(tag, buffer, length);-
163}-
164-
165-
166-
167-
168static QList<QFontEngine *> *enginesCollector = 0;-
169-
170__attribute__((visibility("default"))) void QFontEngine_startCollectingEngines()-
171{-
172 delete enginesCollector;-
173 enginesCollector = new QList<QFontEngine *>();-
174}-
175-
176__attribute__((visibility("default"))) QList<QFontEngine *> QFontEngine_stopCollectingEngines()-
177{-
178 ((!(enginesCollector)) ? qt_assert("enginesCollector",__FILE__,228234) : qt_noop());-
179 QList<QFontEngine *> ret = *enginesCollector;-
180 delete enginesCollector;-
181 enginesCollector = 0;-
182 return ret;-
183}-
184-
185-
186-
187-
188-
189-
190-
191QFontEngine::QFontEngine(Type type)-
192 : m_type(type), ref(0),-
193 font_(0), font_destroy_func(0),(),-
194 face_(0), face_destroy_func(0),(),-
195 m_minLeftBearing(std::numeric_limits<qreal>::max()),-
196 m_minRightBearing(std::numeric_limits<qreal>::max())-
197{-
198 faceData.user_data = this;-
199 faceData.get_font_table = qt_get_font_table_default;-
200-
201 cache_cost = 0;-
202 fsType = 0;-
203 symbol = false;-
204 isSmoothlyScalable = false;-
205-
206 glyphFormat = Format_None;-
207 m_subPixelPositionCount = 0;-
208-
209-
210 if (enginesCollector
enginesCollectorDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
211 enginesCollector->append(this);
never executed: enginesCollector->append(this);
0
212-
213}
never executed: end of block
0
214-
215QFontEngine::~QFontEngine()-
{
m_glyphCaches.clear();
if (font_ && font_destroy_func) {
font_destroy_func(font_);
font_ = 0;
}
if (face_ && face_destroy_func){
217-
218 face_destroy_func(face_);0
face_ = 0;
}if (enginesCollector
enginesCollectorDescription
TRUEnever evaluated
FALSEnever evaluated
)
219 enginesCollector->removeOne(this);
never executed: enginesCollector->removeOne(this);
0
220-
221}
never executed: end of block
0
222-
223QFixed QFontEngine::lineThickness() const-
224{-
225-
226 int score = fontDef.weight * fontDef.pixelSize;-
227 int lw = score / 700;-
228-
229-
230 if (lw < 2 && score >= 1050) lw = 2;-
231 if (lw == 0) lw = 1;-
232-
233 return lw;-
234}-
235-
236QFixed QFontEngine::underlinePosition() const-
237{-
238 return ((lineThickness() * 2) + 3) / 6;-
239}-
240-
241void *QFontEngine::harfbuzzFont() const-
242{-
243 ((!(type() != QFontEngine::Multi)) ? qt_assert("type() != QFontEngine::Multi",__FILE__,304299) : qt_noop());-
244-
245 if (qt_useHarfbuzzNG()
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
246 return
never executed: return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
never executed: return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
0
247-
248 if (!font_
!font_Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
249 HB_Face hbFace = (HB_Face)harfbuzzFace();-
250 if (hbFace->font_for_init
hbFace->font_for_initDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
251 void *data = hbFace->font_for_init;-
252 q_check_ptr(qHBLoadFace(hbFace));-
253 free(data);-
254 }
never executed: end of block
0
255-
256 HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec));-
257 do {if(!(hbFont)
!(hbFont)Description
TRUEnever evaluated
FALSEnever evaluated
)qt_check_pointer(__FILE__,318313);
never executed: qt_check_pointer(__FILE__,313);
} while (0);
0
258 hbFont->klass = &hb_fontClass;-
259 hbFont->userData = const_cast<QFontEngine *>(this);-
260-
261 qint64 emSquare = emSquareSize().truncate();-
262 ((!(emSquare == emSquareSize().toInt())) ? qt_assert("emSquare == emSquareSize().toInt()",__FILE__,323318) : qt_noop());-
263 if (emSquare == 0
emSquare == 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
264 emSquare = 1000;
never executed: emSquare = 1000;
0
265 hbFont->y_ppem = fontDef.pixelSize;-
266 hbFont->x_ppem = fontDef.pixelSize * fontDef.stretch / 100;-
267-
268 hbFont->x_scale = (((qint64)hbFont->x_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare;-
269 hbFont->y_scale = (((qint64)hbFont->y_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare;-
270-
271 font_ = Holder(void *)hbFont;-
font_destroy_func =, free;);
272 }
never executed: end of block
0
273 return
never executed: return font_.get();
font_;.get();
never executed: return font_.get();
0
274}-
275-
276void *QFontEngine::harfbuzzFace() const-
277{-
278 ((!(type() != QFontEngine::Multi)) ? qt_assert("type() != QFontEngine::Multi",__FILE__,340334) : qt_noop());-
279-
280 if (qt_useHarfbuzzNG()
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
281 return
never executed: return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
never executed: return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
0
282-
283 if (!face_
!face_Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
284 QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData));-
285 do {if(!(data)
!(data)Description
TRUEnever evaluated
FALSEnever evaluated
)qt_check_pointer(__FILE__,347341);
never executed: qt_check_pointer(__FILE__,341);
} while (0);
0
286 data->user_data = faceData.user_data;-
287 data->get_font_table = faceData.get_font_table;-
288-
289 HB_Face hbFace = qHBNewFace(data, hb_getSFntTable);-
290 do {if(!(hbFace)
!(hbFace)Description
TRUEnever evaluated
FALSEnever evaluated
)qt_check_pointer(__FILE__,352346);
never executed: qt_check_pointer(__FILE__,346);
} while (0);
0
291 hbFace->isSymbolFont = symbol;-
292-
293 face_ = Holder(void *)hbFace;-
face_destroy_func =, hb_freeFace;);
294 }
never executed: end of block
0
295 return
never executed: return face_.get();
face_;.get();
never executed: return face_.get();
0
296}-
297-
298bool QFontEngine::supportsScript(QChar::Script script) const-
299{-
300 if (type() <= QFontEngine::Multi)-
301 return true;-
302-
303-
304-
305-
306 if (!((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)-
307 || script == QChar::Script_Khmer || script == QChar::Script_Nko)) {-
308 return true;-
309 }-
310-
311-
312 if (qt_useHarfbuzzNG()) {-
313-
314-
315-
316-
317-
318-
319-
320 bool ret = false;-
321 if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {-
322 hb_tag_t script_tag_1, script_tag_2;-
323 hb_ot_tags_from_script(hb_qt_script_to_script(script), &script_tag_1, &script_tag_2);-
324-
325 unsigned int script_index;-
326 ret = hb_ot_layout_table_find_script(face, ((hb_tag_t)((((uint8_t)('G'))<<24)|(((uint8_t)('S'))<<16)|(((uint8_t)('U'))<<8)|((uint8_t)('B')))), script_tag_1, &script_index);-
327 if (!ret) {-
328 ret = hb_ot_layout_table_find_script(face, ((hb_tag_t)((((uint8_t)('G'))<<24)|(((uint8_t)('S'))<<16)|(((uint8_t)('U'))<<8)|((uint8_t)('B')))), script_tag_2, &script_index);-
329 if (!ret && script_tag_2 != ((hb_tag_t)((((uint8_t)('D'))<<24)|(((uint8_t)('F'))<<16)|(((uint8_t)('L'))<<8)|((uint8_t)('T')))))-
330 ret = hb_ot_layout_table_find_script(face, ((hb_tag_t)((((uint8_t)('G'))<<24)|(((uint8_t)('S'))<<16)|(((uint8_t)('U'))<<8)|((uint8_t)('B')))), ((hb_tag_t)((((uint8_t)('D'))<<24)|(((uint8_t)('F'))<<16)|(((uint8_t)('L'))<<8)|((uint8_t)('T')))), &script_index);-
331 }-
332 }-
333 return ret;-
334 }-
335-
336 HB_Face hbFace = (HB_Face)harfbuzzFace();-
337 if (hbFace->font_for_init) {-
338 void *data = hbFace->font_for_init;-
339 q_check_ptr(qHBLoadFace(hbFace));-
340 free(data);-
341 }-
342 return hbFace->supported_scripts[script_to_hbscript(script)];-
343}-
344-
345bool QFontEngine::canRender(const QChar *str, int len) const-
346{-
347 QStringIterator it(str, str + len);-
348 while (it.hasNext()) {-
349 if (glyphIndex(it.next()) == 0)-
350 return false;-
351 }-
352-
353 return true;-
354}-
355-
356glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix)-
357{-
358 glyph_metrics_t metrics = boundingBox(glyph);-
359-
360 if (matrix.type() > QTransform::TxTranslate) {-
361 return metrics.transformed(matrix);-
362 }-
363 return metrics;-
364}-
365-
366QFixed QFontEngine::xHeight() const-
367{-
368 const glyph_t glyph = glyphIndex('x');-
369 glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
370 return bb.height;-
371}-
372-
373QFixed QFontEngine::averageCharWidth() const-
374{-
375 const glyph_t glyph = glyphIndex('x');-
376 glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
377 return bb.xoff;-
378}-
379-
380bool QFontEngine::supportsTransformation(const QTransform &transform) const-
381{-
382 return transform.type() < QTransform::TxProject;-
383}-
384-
385void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,-
386 QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions)-
387{-
388 QFixed xpos;-
389 QFixed ypos;-
390-
391 const bool transform = matrix.m11() != 1.-
392 || matrix.m12() != 0.-
393 || matrix.m21() != 0.-
394 || matrix.m22() != 1.;-
395 if (!transform) {-
396 xpos = QFixed::fromReal(matrix.dx());-
397 ypos = QFixed::fromReal(matrix.dy());-
398 }-
399-
400 int current = 0;-
401 if (flags & QTextItem::RightToLeft) {-
402 int i = glyphs.numGlyphs;-
403 int totalKashidas = 0;-
404 while(i--) {-
405 if (glyphs.attributes[i].dontPrint)-
406 continue;-
407 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
408 totalKashidas += glyphs.justifications[i].nKashidas;-
409 }-
410 positions.resize(glyphs.numGlyphs+totalKashidas);-
411 glyphs_out.resize(glyphs.numGlyphs+totalKashidas);-
412-
413 i = 0;-
414 while(i < glyphs.numGlyphs) {-
415 if (glyphs.attributes[i].dontPrint) {-
416 ++i;-
417 continue;-
418 }-
419 xpos -= glyphs.advances[i];-
420-
421 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
422 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
423 if (transform) {-
424 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
425 gpos = gpos * matrix;-
426 gpos_x = QFixed::fromReal(gpos.x());-
427 gpos_y = QFixed::fromReal(gpos.y());-
428 }-
429 positions[current].x = gpos_x;-
430 positions[current].y = gpos_y;-
431 glyphs_out[current] = glyphs.glyphs[i];-
432 ++current;-
433 if (glyphs.justifications[i].nKashidas) {-
434 QChar ch(0x640);-
435-
436 glyph_t kashidaGlyph = glyphIndex(ch.unicode());-
437 QFixed kashidaWidth;-
438-
439 QGlyphLayout g;-
440 g.numGlyphs = 1;-
441 g.glyphs = &kashidaGlyph;-
442 g.advances = &kashidaWidth;-
443 recalcAdvances(&g, 0);-
444-
445 for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {-
446 xpos -= kashidaWidth;-
447-
448 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
449 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
450 if (transform) {-
451 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
452 gpos = gpos * matrix;-
453 gpos_x = QFixed::fromReal(gpos.x());-
454 gpos_y = QFixed::fromReal(gpos.y());-
455 }-
456 positions[current].x = gpos_x;-
457 positions[current].y = gpos_y;-
458 glyphs_out[current] = kashidaGlyph;-
459 ++current;-
460 }-
461 } else {-
462 xpos -= QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
463 }-
464 ++i;-
465 }-
466 } else {-
467 positions.resize(glyphs.numGlyphs);-
468 glyphs_out.resize(glyphs.numGlyphs);-
469 int i = 0;-
470 if (!transform) {-
471 while (i < glyphs.numGlyphs) {-
472 if (!glyphs.attributes[i].dontPrint) {-
473 positions[current].x = xpos + glyphs.offsets[i].x;-
474 positions[current].y = ypos + glyphs.offsets[i].y;-
475 glyphs_out[current] = glyphs.glyphs[i];-
476 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
477 ++current;-
478 }-
479 ++i;-
480 }-
481 } else {-
482 while (i < glyphs.numGlyphs) {-
483 if (!glyphs.attributes[i].dontPrint) {-
484 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
485 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
486 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
487 gpos = gpos * matrix;-
488 positions[current].x = QFixed::fromReal(gpos.x());-
489 positions[current].y = QFixed::fromReal(gpos.y());-
490 glyphs_out[current] = glyphs.glyphs[i];-
491 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
492 ++current;-
493 }-
494 ++i;-
495 }-
496 }-
497 }-
498 positions.resize(current);-
499 glyphs_out.resize(current);-
500 ((!(positions.size() == glyphs_out.size())) ? qt_assert("positions.size() == glyphs_out.size()",__FILE__,563556) : qt_noop());-
501}-
502-
503void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)-
504{-
505 glyph_metrics_t gi = boundingBox(glyph);-
506 if (leftBearing != 0)-
507 *leftBearing = gi.leftBearing().toReal();-
508 if (rightBearing != 0)-
509 *rightBearing = gi.rightBearing().toReal();-
510}-
511-
512qreal QFontEngine::minLeftBearing() const-
513{-
514 if (m_minLeftBearing == std::numeric_limits<qreal>::max())-
515 minRightBearing();-
516-
517 return m_minLeftBearing;-
518}-
519-
520-
521-
522-
523-
524-
525qreal QFontEngine::minRightBearing() const-
526{-
527 if (m_minRightBearing == std::numeric_limits<qreal>::max()) {-
528-
529-
530 QByteArray hheaTable = getSfntTable(( (((quint32)('h')) << 24) | (((quint32)('h')) << 16) | (((quint32)('e')) << 8) | ((quint32)('a')) ));-
531 if (hheaTable.size() >= int(14 + sizeof(qint16))) {-
532 const uchar *tableData = reinterpret_cast<const uchar *>(hheaTable.constData());-
533 ((!(((qFromBigEndian<quint32>(tableData)) / 65536.0) == 1.0)) ? qt_assert("q16Dot16ToFloat(qFromBigEndian<quint32>(tableData)) == 1.0",__FILE__,596589) : qt_noop());-
534-
535 qint16 minLeftSideBearing = qFromBigEndian<qint16>(tableData + 12);-
536 qint16 minRightSideBearing = qFromBigEndian<qint16>(tableData + 14);-
537-
538-
539-
540-
541 int unitsPerEm = emSquareSize().toInt();-
542 qreal funitToPixelFactor = fontDef.pixelSize / unitsPerEm;-
543-
544-
545-
546-
547-
548 static const int largestValidBearing = 4 * unitsPerEm;-
549-
550 if (qAbs(minLeftSideBearing) < largestValidBearing)-
551 m_minLeftBearing = minLeftSideBearing * funitToPixelFactor;-
552 if (qAbs(minRightSideBearing) < largestValidBearing)-
553 m_minRightBearing = minRightSideBearing * funitToPixelFactor;-
554 }-
555-
556-
557 if (m_minLeftBearing == std::numeric_limits<qreal>::max() || m_minRightBearing == std::numeric_limits<qreal>::max()) {-
558-
559-
560-
561-
562 static const ushort characterSubset[] = {-
563 '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|',-
564 127, 205, 645, 884, 922, 1070, 12386-
565 };-
566-
567-
568 m_minLeftBearing = m_minRightBearing = std::numeric_limits<qreal>::max();-
569-
570 for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) {-
571 const glyph_t glyph = glyphIndex(characterSubset[i]);-
572 if (!glyph)-
573 continue;-
574-
575 glyph_metrics_t glyphMetrics = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
576-
577-
578 if (!glyphMetrics.width || !glyphMetrics.height)-
579 continue;-
580-
581 m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal());-
582 m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal());-
583 }-
584 }-
585-
586 if (m_minLeftBearing == std::numeric_limits<qreal>::max() || m_minRightBearing == std::numeric_limits<qreal>::max())-
587 QMessageLogger(__FILE__, 650643, __PRETTY_FUNCTION__).warning() << "Failed to compute left/right minimum bearings for" << fontDef.family;-
588 }-
589-
590 return m_minRightBearing;-
591}-
592-
593glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)-
594{-
595 glyph_metrics_t overall;-
596-
597 QFixed ymax = 0;-
598 QFixed xmax = 0;-
599 for (int i = 0; i < glyphs.numGlyphs; i++) {-
600 glyph_metrics_t bb = boundingBox(glyphs.glyphs[i]);-
601 QFixed x = overall.xoff + glyphs.offsets[i].x + bb.x;-
602 QFixed y = overall.yoff + glyphs.offsets[i].y + bb.y;-
603 overall.x = qMin(overall.x, x);-
604 overall.y = qMin(overall.y, y);-
605 xmax = qMax(xmax, x + bb.width);-
606 ymax = qMax(ymax, y + bb.height);-
607 overall.xoff += bb.xoff;-
608 overall.yoff += bb.yoff;-
609 }-
610 overall.height = qMax(overall.height, ymax - overall.y);-
611 overall.width = xmax - overall.x;-
612-
613 return overall;-
614}-
615-
616-
617void QFontEngine::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path,-
618 QTextItem::RenderFlags flags)-
619{-
620 if (!glyphs.numGlyphs)-
621 return;-
622-
623 QVarLengthArray<QFixedPoint> positions;-
624 QVarLengthArray<glyph_t> positioned_glyphs;-
625 QTransform matrix = QTransform::fromTranslate(x, y);-
626 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);-
627 addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);-
628}-
629-
630-
631-
632-
633enum { EdgeRight = 0x1,-
634 EdgeDown = 0x2,-
635 EdgeLeft = 0x4,-
636 EdgeUp = 0x8-
637};-
638-
639static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, int w, int h, QPainterPath *path)-
640{-
641 (void)h;;-
642-
643 path->moveTo(x + x0, y + y0);-
644 while (grid[(y)*(w+1) + (x)]) {-
645 if (grid[(y)*(w+1) + (x)] & EdgeRight) {-
646 while (grid[(y)*(w+1) + (x)] & EdgeRight) {-
647 grid[(y)*(w+1) + (x)] &= ~EdgeRight;-
648 ++x;-
649 }-
650 ((!(x <= w)) ? qt_assert("x <= w",__FILE__,713706) : qt_noop());-
651 path->lineTo(x + x0, y + y0);-
652 continue;-
653 }-
654 if (grid[(y)*(w+1) + (x)] & EdgeDown) {-
655 while (grid[(y)*(w+1) + (x)] & EdgeDown) {-
656 grid[(y)*(w+1) + (x)] &= ~EdgeDown;-
657 ++y;-
658 }-
659 ((!(y <= h)) ? qt_assert("y <= h",__FILE__,722715) : qt_noop());-
660 path->lineTo(x + x0, y + y0);-
661 continue;-
662 }-
663 if (grid[(y)*(w+1) + (x)] & EdgeLeft) {-
664 while (grid[(y)*(w+1) + (x)] & EdgeLeft) {-
665 grid[(y)*(w+1) + (x)] &= ~EdgeLeft;-
666 --x;-
667 }-
668 ((!(x >= 0)) ? qt_assert("x >= 0",__FILE__,731724) : qt_noop());-
669 path->lineTo(x + x0, y + y0);-
670 continue;-
671 }-
672 if (grid[(y)*(w+1) + (x)] & EdgeUp) {-
673 while (grid[(y)*(w+1) + (x)] & EdgeUp) {-
674 grid[(y)*(w+1) + (x)] &= ~EdgeUp;-
675 --y;-
676 }-
677 ((!(y >= 0)) ? qt_assert("y >= 0",__FILE__,740733) : qt_noop());-
678 path->lineTo(x + x0, y + y0);-
679 continue;-
680 }-
681 }-
682 path->closeSubpath();-
683}-
684-
685__attribute__((visibility("default"))) void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)-
686{-
687 uint *grid = new uint[(w+1)*(h+1)];-
688-
689 for (int y = 0; y <= h; ++y) {-
690 for (int x = 0; x <= w; ++x) {-
691 bool topLeft = (x == 0)|(y == 0) ? false : (*(image_data + (y - 1)*bpl + ((x - 1) >> 3)) & (0x80 >> ((x - 1) & 7)));-
692 bool topRight = (x == w)|(y == 0) ? false : (*(image_data + (y - 1)*bpl + ((x) >> 3)) & (0x80 >> ((x) & 7)));-
693 bool bottomLeft = (x == 0)|(y == h) ? false : (*(image_data + (y)*bpl + ((x - 1) >> 3)) & (0x80 >> ((x - 1) & 7)));-
694 bool bottomRight = (x == w)|(y == h) ? false : (*(image_data + (y)*bpl + ((x) >> 3)) & (0x80 >> ((x) & 7)));-
695-
696 grid[(y)*(w+1) + (x)] = 0;-
697 if ((!topRight) & bottomRight)-
698 grid[(y)*(w+1) + (x)] |= EdgeRight;-
699 if ((!bottomRight) & bottomLeft)-
700 grid[(y)*(w+1) + (x)] |= EdgeDown;-
701 if ((!bottomLeft) & topLeft)-
702 grid[(y)*(w+1) + (x)] |= EdgeLeft;-
703 if ((!topLeft) & topRight)-
704 grid[(y)*(w+1) + (x)] |= EdgeUp;-
705 }-
706 }-
707-
708-
709 for (int y = 0; y < h; ++y) {-
710 for (int x = 0; x < w; ++x) {-
711 if (!grid[(y)*(w+1) + (x)])-
712 continue;-
713-
714 collectSingleContour(x0, y0, grid, x, y, w, h, path);-
715 }-
716 }-
717 delete [] grid;-
718}-
719-
720-
721-
722-
723-
724void QFontEngine::addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &glyphs,-
725 QPainterPath *path, QTextItem::RenderFlags flags)-
726{-
727-
728 (void)flags;;-
729 QFixed advanceX = QFixed::fromReal(x);-
730 QFixed advanceY = QFixed::fromReal(y);-
731 for (int i=0; i < glyphs.numGlyphs; ++i) {-
732 glyph_metrics_t metrics = boundingBox(glyphs.glyphs[i]);-
733 if (metrics.width.value() == 0 || metrics.height.value() == 0) {-
734 advanceX += glyphs.advances[i];-
735 continue;-
736 }-
737 const QImage alphaMask = alphaMapForGlyph(glyphs.glyphs[i]);-
738-
739 const int w = alphaMask.width();-
740 const int h = alphaMask.height();-
741 const int srcBpl = alphaMask.bytesPerLine();-
742 QImage bitmap;-
743 if (alphaMask.depth() == 1) {-
744 bitmap = alphaMask;-
745 } else {-
746 bitmap = QImage(w, h, QImage::Format_Mono);-
747 const uchar *imageData = alphaMask.bits();-
748 const int destBpl = bitmap.bytesPerLine();-
749 uchar *bitmapData = bitmap.bits();-
750-
751 for (int yi = 0; yi < h; ++yi) {-
752 const uchar *src = imageData + yi*srcBpl;-
753 uchar *dst = bitmapData + yi*destBpl;-
754 for (int xi = 0; xi < w; ++xi) {-
755 const int byte = xi / 8;-
756 const int bit = xi % 8;-
757 if (bit == 0)-
758 dst[byte] = 0;-
759 if (src[xi])-
760 dst[byte] |= 128 >> bit;-
761 }-
762 }-
763 }-
764 const uchar *bitmap_data = bitmap.constBits();-
765 QFixedPoint offset = glyphs.offsets[i];-
766 advanceX += offset.x;-
767 advanceY += offset.y;-
768 qt_addBitmapToPath((advanceX + metrics.x).toReal(), (advanceY + metrics.y).toReal(), bitmap_data, bitmap.bytesPerLine(), w, h, path);-
769 advanceX += glyphs.advances[i];-
770 }-
771}-
772-
773void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,-
774 QPainterPath *path, QTextItem::RenderFlags flags)-
775{-
776 qreal x = positions[0].x.toReal();-
777 qreal y = positions[0].y.toReal();-
778 QVarLengthGlyphLayoutArray g(nGlyphs);-
779-
780 for (int i = 0; i < nGlyphs - 1; ++i) {-
781 g.glyphs[i] = glyphs[i];-
782 g.advances[i] = positions[i + 1].x - positions[i].x;-
783 }-
784 g.glyphs[nGlyphs - 1] = glyphs[nGlyphs - 1];-
785 g.advances[nGlyphs - 1] = QFixed::fromReal(maxCharWidth());-
786-
787 addBitmapFontToPath(x, y, g, path, flags);-
788}-
789-
790QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed )-
791{-
792-
793 return alphaMapForGlyph(glyph);-
794}-
795-
796QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)-
797{-
798 QImage i = alphaMapForGlyph(glyph);-
799 if (t.type() > QTransform::TxTranslate)-
800 i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);-
801 ((!(i.depth() <= 8)) ? qt_assert("i.depth() <= 8",__FILE__,864857) : qt_noop());-
802-
803 return i;-
804}-
805-
806QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
807{-
808 if (! supportsSubPixelPositions())-
809 return alphaMapForGlyph(glyph, t);-
810-
811 QImage i = alphaMapForGlyph(glyph, subPixelPosition);-
812 if (t.type() > QTransform::TxTranslate)-
813 i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);-
814 ((!(i.depth() <= 8)) ? qt_assert("i.depth() <= 8",__FILE__,877870) : qt_noop());-
815-
816 return i;-
817}-
818-
819QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed , const QTransform &t)-
820{-
821 const QImage alphaMask = alphaMapForGlyph(glyph, t);-
822 QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);-
823-
824 for (int y=0; y<alphaMask.height(); ++y) {-
825 uint *dst = (uint *) rgbMask.scanLine(y);-
826 const uchar *src = alphaMask.constScanLine(y);-
827 for (int x=0; x<alphaMask.width(); ++x) {-
828 int val = src[x];-
829 dst[x] = qRgb(val, val, val);-
830 }-
831 }-
832-
833 return rgbMask;-
834}-
835-
836QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&)-
837{-
838 (void)subPixelPosition;;-
839-
840 return QImage();-
841}-
842-
843QFixed QFontEngine::subPixelPositionForX(QFixed x) const-
844{-
845 if (m_subPixelPositionCount <= 1 || !supportsSubPixelPositions())-
846 return QFixed();-
847-
848 QFixed subPixelPosition;-
849 if (x != 0) {-
850 subPixelPosition = x - x.floor();-
851 QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();-
852-
853-
854-
855 subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);-
856 }-
857 return subPixelPosition;-
858}-
859-
860QImage *QFontEngine::lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,-
861 QFontEngine::GlyphFormat neededFormat,-
862 const QTransform &t, QPoint *offset)-
863{-
864 ((!(currentlyLockedAlphaMap.isNull())) ? qt_assert("currentlyLockedAlphaMap.isNull()",__FILE__,927920) : qt_noop());-
865 if (neededFormat == Format_None)-
866 neededFormat = Format_A32;-
867-
868 if (neededFormat != Format_A32)-
869 currentlyLockedAlphaMap = alphaMapForGlyph(glyph, subPixelPosition, t);-
870 else-
871 currentlyLockedAlphaMap = alphaRGBMapForGlyph(glyph, subPixelPosition, t);-
872-
873 if (offset != 0)-
874 *offset = QPoint(0, 0);-
875-
876 return &currentlyLockedAlphaMap;-
877}-
878-
879void QFontEngine::unlockAlphaMapForGlyph()-
880{-
881 ((!(!currentlyLockedAlphaMap.isNull())) ? qt_assert("!currentlyLockedAlphaMap.isNull()",__FILE__,944937) : qt_noop());-
882 currentlyLockedAlphaMap = QImage();-
883}-
884-
885QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)-
886{-
887 glyph_metrics_t gm = boundingBox(glyph);-
888 int glyph_x = qFloor(gm.x.toReal());-
889 int glyph_y = qFloor(gm.y.toReal());-
890 int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x;-
891 int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y;-
892-
893 if (glyph_width <= 0 || glyph_height <= 0)-
894 return QImage();-
895 QFixedPoint pt;-
896 pt.x = -glyph_x;-
897 pt.y = -glyph_y;-
898 QPainterPath path;-
899 path.setFillRule(Qt::WindingFill);-
900 QImage im(glyph_width, glyph_height, QImage::Format_ARGB32_Premultiplied);-
901 im.fill(Qt::transparent);-
902 QPainter p(&im);-
903 p.setRenderHint(QPainter::Antialiasing);-
904 addGlyphsToPath(&glyph, &pt, 1, &path, 0);-
905 p.setPen(Qt::NoPen);-
906 p.setBrush(Qt::black);-
907 p.drawPath(path);-
908 p.end();-
909-
910 QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);-
911-
912 for (int y=0; y<im.height(); ++y) {-
913 uchar *dst = (uchar *) alphaMap.scanLine(y);-
914 const uint *src = reinterpret_cast<const uint *>(im.constScanLine(y));-
915 for (int x=0; x<im.width(); ++x)-
916 dst[x] = qAlpha(src[x]);-
917 }-
918-
919 return alphaMap;-
920}-
921-
922void QFontEngine::removeGlyphFromCache(glyph_t)-
923{-
924}-
925-
926QFontEngine::Properties QFontEngine::properties() const-
927{-
928 Properties p;-
929 QByteArray psname = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8());-
930 psname += '-';-
931 psname += QByteArray::number(fontDef.style);-
932 psname += '-';-
933 psname += QByteArray::number(fontDef.weight);-
934-
935 p.postscriptName = psname;-
936 p.ascent = ascent();-
937 p.descent = descent();-
938 p.leading = leading();-
939 p.emSquare = p.ascent;-
940 p.boundingBox = QRectF(0, -p.ascent.toReal(), maxCharWidth(), (p.ascent + p.descent).toReal());-
941 p.italicAngle = 0;-
942 p.capHeight = p.ascent;-
943 p.lineWidth = lineThickness();-
944 return p;-
945}-
946-
947void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)-
948{-
949 *metrics = boundingBox(glyph);-
950 QFixedPoint p;-
951 p.x = 0;-
952 p.y = 0;-
953 addGlyphsToPath(&glyph, &p, 1, path, QFlag(0));-
954}-
955bool QFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const-
956{-
957 (void)tag;-
958 (void)buffer;-
959 (void)length;-
960 return false;-
961}-
962-
963QByteArray QFontEngine::getSfntTable(uint tag) const-
964{-
965 QByteArray table;-
966 uint len = 0;-
967 if (!getSfntTableData(tag, 0, &len))-
968 return table;-
969 table.resize(len);-
970 if (!getSfntTableData(tag, reinterpret_cast<uchar *>(table.data()), &len))-
971 return QByteArray();-
972 return table;-
973}-
974-
975void QFontEngine::clearGlyphCache(const void *context)-
976{-
977 m_glyphCaches.remove(context);-
978}-
979-
980void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cache)-
981{-
982 ((!(cache)) ? qt_assert("cache",__FILE__,10571050) : qt_noop());-
983-
984 GlyphCaches &caches = m_glyphCaches[context];-
985 for (GlyphCaches::const_iterator it = caches.constBegin(), end = caches.constEnd(); it != end; ++it) {-
986 if (cache == it->cache.data())-
987 return;-
988 }-
989-
990-
991-
992 if (caches.size() == 4)-
993 caches.removeLast();-
994-
995 GlyphCacheEntry entry;-
996 entry.cache = cache;-
997 caches.push_front(entry);-
998-
999}-
1000-
1001QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat format, const QTransform &transform) const-
1002{-
1003 const QHash<const void*, GlyphCaches>::const_iterator caches = m_glyphCaches.constFind(context);-
1004 if (caches == m_glyphCaches.cend())-
1005 return nullptr;-
1006-
1007 for (GlyphCaches::const_iterator it = caches->begin(), end = caches->end(); it != end; ++it) {-
1008 QFontEngineGlyphCache *cache = it->cache.data();-
1009 if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform))-
1010 return cache;-
1011 }-
1012-
1013 return nullptr;-
1014}-
1015-
1016static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)-
1017{-
1018 uint left_right = (left << 16) + right;-
1019-
1020 left = 0, right = numPairs - 1;-
1021 while (left <= right) {-
1022 int middle = left + ( ( right - left ) >> 1 );-
1023-
1024 if(pairs[middle].left_right == left_right)-
1025 return pairs[middle].adjust;-
1026-
1027 if (pairs[middle].left_right < left_right)-
1028 left = middle + 1;-
1029 else-
1030 right = middle - 1;-
1031 }-
1032 return 0;-
1033}-
1034-
1035void QFontEngine::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
1036{-
1037 int numPairs = kerning_pairs.size();-
1038 if(!numPairs)-
1039 return;-
1040-
1041 const KernPair *pairs = kerning_pairs.constData();-
1042-
1043 if (flags & DesignMetrics) {-
1044 for(int i = 0; i < glyphs->numGlyphs - 1; ++i)-
1045 glyphs->advances[i] += kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs);-
1046 } else {-
1047 for(int i = 0; i < glyphs->numGlyphs - 1; ++i)-
1048 glyphs->advances[i] += qRound(kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs));-
1049 }-
1050}-
1051-
1052void QFontEngine::loadKerningPairs(QFixed scalingFactor)-
1053{-
1054 kerning_pairs.clear();-
1055-
1056 QByteArray tab = getSfntTable(( (((quint32)('k')) << 24) | (((quint32)('e')) << 16) | (((quint32)('r')) << 8) | ((quint32)('n')) ));-
1057 if (tab.isEmpty())-
1058 return;-
1059-
1060 const uchar *table = reinterpret_cast<const uchar *>(tab.constData());-
1061 const uchar *end = table + tab.size();-
1062-
1063 quint16 version;-
1064 if (!qSafeFromBigEndian(table, end, &version))-
1065 return;-
1066-
1067 if (version != 0) {-
1068-
1069 return;-
1070 }-
1071-
1072 quint16 numTables;-
1073 if (!qSafeFromBigEndian(table + 2, end, &numTables))-
1074 return;-
1075-
1076 {-
1077 int offset = 4;-
1078 for(int i = 0; i < numTables; ++i) {-
1079 const uchar *header = table + offset;-
1080-
1081 quint16 version;-
1082 if (!qSafeFromBigEndian(header, end, &version))-
1083 goto end;-
1084-
1085 quint16 length;-
1086 if (!qSafeFromBigEndian(header + 2, end, &length))-
1087 goto end;-
1088-
1089 quint16 coverage;-
1090 if (!qSafeFromBigEndian(header + 4, end, &coverage))-
1091 goto end;-
1092-
1093-
1094 if(version == 0 && coverage == 0x0001) {-
1095 if (offset + length > tab.size()) {-
1096-
1097 goto end;-
1098 }-
1099 const uchar *data = table + offset + 6;-
1100-
1101 quint16 nPairs;-
1102 if (!qSafeFromBigEndian(data, end, &nPairs))-
1103 goto end;-
1104-
1105 if(nPairs * 6 + 8 > length - 6) {-
1106-
1107-
1108 goto end;-
1109 }-
1110-
1111 int off = 8;-
1112 for(int i = 0; i < nPairs; ++i) {-
1113 QFontEngine::KernPair p;-
1114-
1115 quint16 tmp;-
1116 if (!qSafeFromBigEndian(data + off, end, &tmp))-
1117 goto end;-
1118-
1119 p.left_right = uint(tmp) << 16;-
1120 if (!qSafeFromBigEndian(data + off + 2, end, &tmp))-
1121 goto end;-
1122-
1123 p.left_right |= tmp;-
1124-
1125 if (!qSafeFromBigEndian(data + off + 4, end, &tmp))-
1126 goto end;-
1127-
1128 p.adjust = QFixed(int(short(tmp))) / scalingFactor;-
1129 kerning_pairs.append(p);-
1130 off += 6;-
1131 }-
1132 }-
1133 offset += length;-
1134 }-
1135 }-
1136end:-
1137 std::sort(kerning_pairs.begin(), kerning_pairs.end());-
1138-
1139-
1140}-
1141-
1142-
1143int QFontEngine::glyphCount() const-
1144{-
1145 QByteArray maxpTable = getSfntTable(( (((quint32)('m')) << 24) | (((quint32)('a')) << 16) | (((quint32)('x')) << 8) | ((quint32)('p')) ));-
1146 if (maxpTable.size() < 6)-
1147 return 0;-
1148-
1149 const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);-
1150 const uchar *end = source + maxpTable.size();-
1151-
1152 quint16 count = 0;-
1153 qSafeFromBigEndian(source, end, &count);-
1154 return count;-
1155}-
1156-
1157Qt::HANDLE QFontEngine::handle() const-
1158{-
1159 return nullptr;-
1160}-
1161-
1162const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)-
1163{-
1164 const uchar *header = table;-
1165 const uchar *endPtr = table + tableSize;-
1166-
1167-
1168 quint16 version;-
1169 if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)-
1170 return 0;-
1171-
1172 quint16 numTables;-
1173 if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))-
1174 return 0;-
1175-
1176 const uchar *maps = table + 4;-
1177-
1178 enum {-
1179 Invalid,-
1180 AppleRoman,-
1181 Symbol,-
1182 Unicode11,-
1183 Unicode,-
1184 MicrosoftUnicode,-
1185 MicrosoftUnicodeExtended-
1186 };-
1187-
1188 int symbolTable = -1;-
1189 int tableToUse = -1;-
1190 int score = Invalid;-
1191 for (int n = 0; n < numTables; ++n) {-
1192 quint16 platformId;-
1193 if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))-
1194 return 0;-
1195-
1196 quint16 platformSpecificId;-
1197 if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))-
1198 return 0;-
1199-
1200 switch (platformId) {-
1201 case 0:-
1202 if (score < Unicode &&-
1203 (platformSpecificId == 0 ||-
1204 platformSpecificId == 2 ||-
1205 platformSpecificId == 3)) {-
1206 tableToUse = n;-
1207 score = Unicode;-
1208 } else if (score < Unicode11 && platformSpecificId == 1) {-
1209 tableToUse = n;-
1210 score = Unicode11;-
1211 }-
1212 break;-
1213 case 1:-
1214 if (score < AppleRoman && platformSpecificId == 0) {-
1215 tableToUse = n;-
1216 score = AppleRoman;-
1217 }-
1218 break;-
1219 case 3:-
1220 switch (platformSpecificId) {-
1221 case 0:-
1222 symbolTable = n;-
1223 if (score < Symbol) {-
1224 tableToUse = n;-
1225 score = Symbol;-
1226 }-
1227 break;-
1228 case 1:-
1229 if (score < MicrosoftUnicode) {-
1230 tableToUse = n;-
1231 score = MicrosoftUnicode;-
1232 }-
1233 break;-
1234 case 0xa:-
1235 if (score < MicrosoftUnicodeExtended) {-
1236 tableToUse = n;-
1237 score = MicrosoftUnicodeExtended;-
1238 }-
1239 break;-
1240 default:-
1241 break;-
1242 }-
1243 default:-
1244 break;-
1245 }-
1246 }-
1247 if(tableToUse < 0)-
1248 return 0;-
1249-
1250resolveTable:-
1251 *isSymbolFont = (symbolTable > -1);-
1252-
1253 quint32 unicode_table;-
1254 if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))-
1255 return 0;-
1256-
1257 if (!unicode_table)-
1258 return 0;-
1259-
1260-
1261 header = table + unicode_table;-
1262-
1263 quint16 format;-
1264 if (!qSafeFromBigEndian(header, endPtr, &format))-
1265 return 0;-
1266-
1267 quint32 length;-
1268 if (format < 8) {-
1269 quint16 tmp;-
1270 if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))-
1271 return 0;-
1272 length = tmp;-
1273 } else {-
1274 if (!qSafeFromBigEndian(header + 4, endPtr, &length))-
1275 return 0;-
1276 }-
1277-
1278 if (table + unicode_table + length > endPtr)-
1279 return 0;-
1280 *cmapSize = length;-
1281-
1282-
1283-
1284-
1285 if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) {-
1286 const uchar *selectedTable = table + unicode_table;-
1287-
1288-
1289 bool unicodeTableHasLatin1 = false;-
1290 for (int uc=0x00; uc<0x100; ++uc) {-
1291 if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {-
1292 unicodeTableHasLatin1 = true;-
1293 break;-
1294 }-
1295 }-
1296-
1297-
1298 bool unicodeTableHasSymbols = false;-
1299 if (!unicodeTableHasLatin1) {-
1300 for (int uc=0xf000; uc<0xf100; ++uc) {-
1301 if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {-
1302 unicodeTableHasSymbols = true;-
1303 break;-
1304 }-
1305 }-
1306 }-
1307-
1308-
1309 if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) {-
1310 tableToUse = symbolTable;-
1311 score = Symbol;-
1312 goto resolveTable;-
1313 }-
1314 }-
1315-
1316 return table + unicode_table;-
1317}-
1318-
1319quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)-
1320{-
1321 const uchar *end = cmap + cmapSize;-
1322 quint16 format;-
1323 if (!qSafeFromBigEndian(cmap, end, &format))-
1324 return 0;-
1325-
1326 if (format == 0) {-
1327 const uchar *ptr = cmap + 6 + unicode;-
1328 if (unicode < 256 && ptr < end)-
1329 return quint32(*ptr);-
1330 } else if (format == 4) {-
1331-
1332-
1333-
1334-
1335-
1336 if(unicode >= 0xffff)-
1337 return 0;-
1338-
1339 quint16 segCountX2;-
1340 if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))-
1341 return 0;-
1342-
1343 const unsigned char *ends = cmap + 14;-
1344-
1345 int i = 0;-
1346 for (; i < segCountX2/2; ++i) {-
1347 quint16 codePoint;-
1348 if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))-
1349 return 0;-
1350 if (codePoint >= unicode)-
1351 break;-
1352 }-
1353-
1354 const unsigned char *idx = ends + segCountX2 + 2 + 2*i;-
1355-
1356 quint16 startIndex;-
1357 if (!qSafeFromBigEndian(idx, end, &startIndex))-
1358 return 0;-
1359 if (startIndex > unicode)-
1360 return 0;-
1361-
1362 idx += segCountX2;-
1363-
1364 quint16 tmp;-
1365 if (!qSafeFromBigEndian(idx, end, &tmp))-
1366 return 0;-
1367 qint16 idDelta = qint16(tmp);-
1368-
1369 idx += segCountX2;-
1370-
1371 quint16 idRangeoffset_t;-
1372 if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))-
1373 return 0;-
1374-
1375 quint16 glyphIndex;-
1376 if (idRangeoffset_t) {-
1377 quint16 id;-
1378 if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))-
1379 return 0;-
1380-
1381 if (id)-
1382 glyphIndex = (idDelta + id) % 0x10000;-
1383 else-
1384 glyphIndex = 0;-
1385 } else {-
1386 glyphIndex = (idDelta + unicode) % 0x10000;-
1387 }-
1388 return glyphIndex;-
1389 } else if (format == 6) {-
1390 quint16 tableSize;-
1391 if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))-
1392 return 0;-
1393-
1394 quint16 firstCode6;-
1395 if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))-
1396 return 0;-
1397 if (unicode < firstCode6)-
1398 return 0;-
1399-
1400 quint16 entryCount6;-
1401 if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))-
1402 return 0;-
1403 if (entryCount6 * 2 + 10 > tableSize)-
1404 return 0;-
1405-
1406 quint16 sentinel6 = firstCode6 + entryCount6;-
1407 if (unicode >= sentinel6)-
1408 return 0;-
1409-
1410 quint16 entryIndex6 = unicode - firstCode6;-
1411-
1412 quint16 index = 0;-
1413 qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);-
1414 return index;-
1415 } else if (format == 12) {-
1416 quint32 nGroups;-
1417 if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))-
1418 return 0;-
1419-
1420 cmap += 16;-
1421-
1422 int left = 0, right = nGroups - 1;-
1423 while (left <= right) {-
1424 int middle = left + ( ( right - left ) >> 1 );-
1425-
1426 quint32 startCharCode;-
1427 if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))-
1428 return 0;-
1429-
1430 if(unicode < startCharCode)-
1431 right = middle - 1;-
1432 else {-
1433 quint32 endCharCode;-
1434 if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))-
1435 return 0;-
1436-
1437 if (unicode <= endCharCode) {-
1438 quint32 index;-
1439 if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))-
1440 return 0;-
1441-
1442 return index + unicode - startCharCode;-
1443 }-
1444 left = middle + 1;-
1445 }-
1446 }-
1447 } else {-
1448 QMessageLogger(__FILE__, 15231516, __PRETTY_FUNCTION__).debug("cmap table of format %d not implemented", format);-
1449 }-
1450-
1451 return 0;-
1452}-
1453-
1454QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &family)-
1455{-
1456 QByteArray f = family;-
1457 f.replace(' ', "");-
1458 f.replace('(', "");-
1459 f.replace(')', "");-
1460 f.replace('<', "");-
1461 f.replace('>', "");-
1462 f.replace('[', "");-
1463 f.replace(']', "");-
1464 f.replace('{', "");-
1465 f.replace('}', "");-
1466 f.replace('/', "");-
1467 f.replace('%', "");-
1468 return f;-
1469}-
1470-
1471-
1472-
1473-
1474bool QFontEngine::hasUnreliableGlyphOutline() const-
1475{-
1476-
1477 return glyphFormat == QFontEngine::Format_ARGB;-
1478}-
1479-
1480QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)-
1481{-
1482 if (glyphs.numGlyphs >= 1) {-
1483 glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1];-
1484 glyph_metrics_t gi = boundingBox(glyph);-
1485 if (gi.isValid())-
1486 return round ? qRound(gi.rightBearing()) : gi.rightBearing();-
1487 }-
1488 return 0;-
1489}-
1490-
1491-
1492QFontEngine::GlyphCacheEntry::GlyphCacheEntry()-
1493{-
1494}-
1495-
1496QFontEngine::GlyphCacheEntry::GlyphCacheEntry(const GlyphCacheEntry &o)-
1497 : cache(o.cache)-
1498{-
1499}-
1500-
1501QFontEngine::GlyphCacheEntry::~GlyphCacheEntry()-
1502{-
1503}-
1504-
1505QFontEngine::GlyphCacheEntry &QFontEngine::GlyphCacheEntry::operator=(const GlyphCacheEntry &o)-
1506{-
1507 cache = o.cache;-
1508 return *this;-
1509}-
1510-
1511-
1512-
1513-
1514-
1515QFontEngineBox::QFontEngineBox(int size)-
1516 : QFontEngine(Box),-
1517 _size(size)-
1518{-
1519 cache_cost = sizeof(QFontEngineBox);-
1520}-
1521-
1522QFontEngineBox::QFontEngineBox(Type type, int size)-
1523 : QFontEngine(type),-
1524 _size(size)-
1525{-
1526 cache_cost = sizeof(QFontEngineBox);-
1527}-
1528-
1529QFontEngineBox::~QFontEngineBox()-
1530{-
1531}-
1532-
1533glyph_t QFontEngineBox::glyphIndex(uint ucs4) const-
1534{-
1535 (void)ucs4;-
1536 return 0;-
1537}-
1538-
1539bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const-
1540{-
1541 ((!(glyphs->numGlyphs >= *nglyphs)) ? qt_assert("glyphs->numGlyphs >= *nglyphs",__FILE__,16161609) : qt_noop());-
1542 if (*nglyphs < len) {-
1543 *nglyphs = len;-
1544 return false;-
1545 }-
1546-
1547 int ucs4Length = 0;-
1548 QStringIterator it(str, str + len);-
1549 while (it.hasNext()) {-
1550 it.advance();-
1551 glyphs->glyphs[ucs4Length++] = 0;-
1552 }-
1553-
1554 *nglyphs = ucs4Length;-
1555 glyphs->numGlyphs = ucs4Length;-
1556-
1557 if (!(flags & GlyphIndicesOnly))-
1558 recalcAdvances(glyphs, flags);-
1559-
1560 return true;-
1561}-
1562-
1563void QFontEngineBox::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const-
1564{-
1565 for (int i = 0; i < glyphs->numGlyphs; i++)-
1566 glyphs->advances[i] = _size;-
1567}-
1568-
1569void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)-
1570{-
1571 if (!glyphs.numGlyphs)-
1572 return;-
1573-
1574 QVarLengthArray<QFixedPoint> positions;-
1575 QVarLengthArray<glyph_t> positioned_glyphs;-
1576 QTransform matrix = QTransform::fromTranslate(x, y - _size);-
1577 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);-
1578-
1579 QSize s(_size - 3, _size - 3);-
1580 for (int k = 0; k < positions.size(); k++)-
1581 path->addRect(QRectF(positions[k].toPointF(), s));-
1582}-
1583-
1584glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs)-
1585{-
1586 glyph_metrics_t overall;-
1587 overall.width = _size*glyphs.numGlyphs;-
1588 overall.height = _size;-
1589 overall.xoff = overall.width;-
1590 return overall;-
1591}-
1592-
1593void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti)-
1594{-
1595 if (!ti.glyphs.numGlyphs)-
1596 return;-
1597-
1598-
1599 QSize s(_size - 3, _size - 3);-
1600-
1601 QVarLengthArray<QFixedPoint> positions;-
1602 QVarLengthArray<glyph_t> glyphs;-
1603 QTransform matrix = QTransform::fromTranslate(x, y - _size);-
1604 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);-
1605 if (glyphs.size() == 0)-
1606 return;-
1607-
1608-
1609 QPainter *painter = p->painter();-
1610 painter->save();-
1611 painter->setBrush(Qt::NoBrush);-
1612 QPen pen = painter->pen();-
1613 pen.setWidthF(lineThickness().toReal());-
1614 painter->setPen(pen);-
1615 for (int k = 0; k < positions.size(); k++)-
1616 painter->drawRect(QRectF(positions[k].toPointF(), s));-
1617 painter->restore();-
1618}-
1619-
1620glyph_metrics_t QFontEngineBox::boundingBox(glyph_t)-
1621{-
1622 return glyph_metrics_t(0, -_size, _size, _size, _size, 0);-
1623}-
1624-
1625QFontEngine *QFontEngineBox::cloneWithSize(qreal pixelSize) const-
1626{-
1627 QFontEngineBox *fe = new QFontEngineBox(pixelSize);-
1628 return fe;-
1629}-
1630-
1631QFixed QFontEngineBox::ascent() const-
1632{-
1633 return _size;-
1634}-
1635-
1636QFixed QFontEngineBox::descent() const-
1637{-
1638 return 0;-
1639}-
1640-
1641QFixed QFontEngineBox::leading() const-
1642{-
1643 QFixed l = _size * QFixed::fromReal(qreal(0.15));-
1644 return l.ceil();-
1645}-
1646-
1647qreal QFontEngineBox::maxCharWidth() const-
1648{-
1649 return _size;-
1650}-
1651-
1652bool QFontEngineBox::canRender(const QChar *, int) const-
1653{-
1654 return true;-
1655}-
1656-
1657QImage QFontEngineBox::alphaMapForGlyph(glyph_t)-
1658{-
1659 QImage image(_size, _size, QImage::Format_Alpha8);-
1660 image.fill(0);-
1661-
1662-
1663 for (int i=2; i <= _size-3; ++i) {-
1664 image.setPixel(i, 2, 255);-
1665 image.setPixel(i, _size-3, 255);-
1666 image.setPixel(2, i, 255);-
1667 image.setPixel(_size-3, i, 255);-
1668 }-
1669 return image;-
1670}-
1671-
1672-
1673-
1674-
1675-
1676static inline uchar highByte(glyph_t glyph)-
1677{ return glyph >> 24; }-
1678-
1679-
1680static inline glyph_t stripped(glyph_t glyph)-
1681{ return glyph & 0x00ffffff; }-
1682-
1683QFontEngineMulti::QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies)-
1684 : QFontEngine(Multi),-
1685 m_fallbackFamilies(fallbackFamilies),-
1686 m_script(script),-
1687 m_fallbackFamiliesQueried(!m_fallbackFamilies.isEmpty())-
1688{-
1689 ((!(engine && engine->type() != QFontEngine::Multi)) ? qt_assert("engine && engine->type() != QFontEngine::Multi",__FILE__,17641757) : qt_noop());-
1690-
1691 if (m_fallbackFamilies.isEmpty()) {-
1692-
1693 m_fallbackFamilies << QString();-
1694 }-
1695-
1696 m_engines.resize(m_fallbackFamilies.size() + 1);-
1697-
1698 engine->ref.ref();-
1699 m_engines[0] = engine;-
1700-
1701 fontDef = engine->fontDef;-
1702 cache_cost = engine->cache_cost;-
1703}-
1704-
1705QFontEngineMulti::~QFontEngineMulti()-
1706{-
1707 for (int i = 0; i < m_engines.size(); ++i) {-
1708 QFontEngine *fontEngine = m_engines.at(i);-
1709 if (fontEngine && !fontEngine->ref.deref())-
1710 delete fontEngine;-
1711 }-
1712}-
1713-
1714QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script);-
1715-
1716void QFontEngineMulti::ensureFallbackFamiliesQueried()-
1717{-
1718 QFont::StyleHint styleHint = QFont::StyleHint(fontDef.styleHint);-
1719 if (styleHint == QFont::AnyStyle && fontDef.fixedPitch)-
1720 styleHint = QFont::TypeWriter;-
1721-
1722 setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.family, QFont::Style(fontDef.style), styleHint, QChar::Script(m_script)));-
1723}-
1724-
1725void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamilies)-
1726{-
1727 ((!(!m_fallbackFamiliesQueried)) ? qt_assert("!m_fallbackFamiliesQueried",__FILE__,18021795) : qt_noop());-
1728-
1729 m_fallbackFamilies = fallbackFamilies;-
1730 if (m_fallbackFamilies.isEmpty()) {-
1731-
1732 ((!(m_engines.size() == 2)) ? qt_assert("m_engines.size() == 2",__FILE__,18071800) : qt_noop());-
1733 QFontEngine *engine = m_engines.at(0);-
1734 engine->ref.ref();-
1735 m_engines[1] = engine;-
1736 m_fallbackFamilies << fontDef.family;-
1737 } else {-
1738 m_engines.resize(m_fallbackFamilies.size() + 1);-
1739 }-
1740-
1741 m_fallbackFamiliesQueried = true;-
1742}-
1743-
1744void QFontEngineMulti::ensureEngineAt(int at)-
1745{-
1746 if (!m_fallbackFamiliesQueried)-
1747 ensureFallbackFamiliesQueried();-
1748 ((!(at < m_engines.size())) ? qt_assert("at < m_engines.size()",__FILE__,18231816) : qt_noop());-
1749 if (!m_engines.at(at)) {-
1750 QFontEngine *engine = loadEngine(at);-
1751 if (!engine)-
1752 engine = new QFontEngineBox(fontDef.pixelSize);-
1753 ((!(engine && engine->type() != QFontEngine::Multi)) ? qt_assert("engine && engine->type() != QFontEngine::Multi",__FILE__,18281821) : qt_noop());-
1754 engine->ref.ref();-
1755 m_engines[at] = engine;-
1756 }-
1757}-
1758-
1759QFontEngine *QFontEngineMulti::loadEngine(int at)-
1760{-
1761 QFontDef request(fontDef);-
1762 request.styleStrategy |= QFont::NoFontMerging;-
1763 request.family = fallbackFamilyAt(at - 1);-
1764-
1765 if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {-
1766 engine->fontDef.weight = request.weight;-
1767 if (request.style > QFont::StyleNormal)-
1768 engine->fontDef.style = request.style;-
1769 return engine;-
1770 }-
1771-
1772 return 0;-
1773}-
1774-
1775glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const-
1776{-
1777 glyph_t glyph = engine(0)->glyphIndex(ucs4);-
1778 if (glyph == 0 && ucs4 != QChar::LineSeparator) {-
1779 if (!m_fallbackFamiliesQueried)-
1780 const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();-
1781 for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {-
1782 QFontEngine *engine = m_engines.at(x);-
1783 if (!engine) {-
1784 if (!shouldLoadFontEngineForCharacter(x, ucs4))-
1785 continue;-
1786 const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);-
1787 engine = m_engines.at(x);-
1788 }-
1789 ((!(engine != 0)) ? qt_assert("engine != 0",__FILE__,18641857) : qt_noop());-
1790 if (engine->type() == Box)-
1791 continue;-
1792-
1793 glyph = engine->glyphIndex(ucs4);-
1794 if (glyph != 0) {-
1795-
1796 glyph |= (x << 24);-
1797 break;-
1798 }-
1799 }-
1800 }-
1801-
1802 return glyph;-
1803}-
1804-
1805bool QFontEngineMulti::stringToCMap(const QChar *str, int len,-
1806 QGlyphLayout *glyphs, int *nglyphs,-
1807 QFontEngine::ShaperFlags flags) const-
1808{-
1809 if (!engine(0)->stringToCMap(str, len, glyphs, nglyphs, flags))-
1810 return false;-
1811-
1812 int glyph_pos = 0;-
1813 QStringIterator it(str, str + len);-
1814 while (it.hasNext()) {-
1815 const uint ucs4 = it.peekNext();-
1816 if (glyphs->glyphs[glyph_pos] == 0 && ucs4 != QChar::LineSeparator) {-
1817 if (!m_fallbackFamiliesQueried)-
1818 const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();-
1819 for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {-
1820 QFontEngine *engine = m_engines.at(x);-
1821 if (!engine) {-
1822 if (!shouldLoadFontEngineForCharacter(x, ucs4))-
1823 continue;-
1824 const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);-
1825 engine = m_engines.at(x);-
1826 if (!engine)-
1827 continue;-
1828 }-
1829 ((!(engine != 0)) ? qt_assert("engine != 0",__FILE__,19041897) : qt_noop());-
1830 if (engine->type() == Box)-
1831 continue;-
1832-
1833 glyph_t glyph = engine->glyphIndex(ucs4);-
1834 if (glyph != 0) {-
1835 glyphs->glyphs[glyph_pos] = glyph;-
1836 if (!(flags & GlyphIndicesOnly)) {-
1837 QGlyphLayout g = glyphs->mid(glyph_pos, 1);-
1838 engine->recalcAdvances(&g, flags);-
1839 }-
1840-
1841 glyphs->glyphs[glyph_pos] |= (x << 24);-
1842 break;-
1843 }-
1844 }-
1845 }-
1846-
1847 it.advance();-
1848 ++glyph_pos;-
1849 }-
1850-
1851 *nglyphs = glyph_pos;-
1852 glyphs->numGlyphs = glyph_pos;-
1853-
1854 return true;-
1855}-
1856-
1857bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const-
1858{-
1859 (void)at;;-
1860 (void)ucs4;;-
1861 return true;-
1862}-
1863-
1864glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)-
1865{-
1866 if (glyphs.numGlyphs <= 0)-
1867 return glyph_metrics_t();-
1868-
1869 glyph_metrics_t overall;-
1870-
1871 int which = highByte(glyphs.glyphs[0]);-
1872 int start = 0;-
1873 int end, i;-
1874 for (end = 0; end < glyphs.numGlyphs; ++end) {-
1875 const int e = highByte(glyphs.glyphs[end]);-
1876 if (e == which)-
1877 continue;-
1878-
1879-
1880 for (i = start; i < end; ++i)-
1881 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);-
1882-
1883-
1884 const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));-
1885-
1886 overall.x = qMin(overall.x, gm.x);-
1887 overall.y = qMin(overall.y, gm.y);-
1888 overall.width = overall.xoff + gm.width;-
1889 overall.height = qMax(overall.height + overall.y, gm.height + gm.y) --
1890 qMin(overall.y, gm.y);-
1891 overall.xoff += gm.xoff;-
1892 overall.yoff += gm.yoff;-
1893-
1894-
1895 const int hi = which << 24;-
1896 for (i = start; i < end; ++i)-
1897 glyphs.glyphs[i] = hi | glyphs.glyphs[i];-
1898-
1899-
1900 start = end;-
1901 which = e;-
1902 }-
1903-
1904-
1905 for (i = start; i < end; ++i)-
1906 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);-
1907-
1908-
1909 const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));-
1910-
1911 overall.x = qMin(overall.x, gm.x);-
1912 overall.y = qMin(overall.y, gm.y);-
1913 overall.width = overall.xoff + gm.width;-
1914 overall.height = qMax(overall.height + overall.y, gm.height + gm.y) --
1915 qMin(overall.y, gm.y);-
1916 overall.xoff += gm.xoff;-
1917 overall.yoff += gm.yoff;-
1918-
1919-
1920 const int hi = which << 24;-
1921 for (i = start; i < end; ++i)-
1922 glyphs.glyphs[i] = hi | glyphs.glyphs[i];-
1923-
1924 return overall;-
1925}-
1926-
1927void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)-
1928{-
1929 int which = highByte(glyph);-
1930 ensureEngineAt(which);-
1931 engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);-
1932}-
1933-
1934void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,-
1935 QPainterPath *path, QTextItem::RenderFlags flags)-
1936{-
1937 if (glyphs.numGlyphs <= 0)-
1938 return;-
1939-
1940 int which = highByte(glyphs.glyphs[0]);-
1941 int start = 0;-
1942 int end, i;-
1943 if (flags & QTextItem::RightToLeft) {-
1944 for (int gl = 0; gl < glyphs.numGlyphs; gl++)-
1945 x += glyphs.advances[gl].toReal();-
1946 }-
1947 for (end = 0; end < glyphs.numGlyphs; ++end) {-
1948 const int e = highByte(glyphs.glyphs[end]);-
1949 if (e == which)-
1950 continue;-
1951-
1952 if (flags & QTextItem::RightToLeft) {-
1953 for (i = start; i < end; ++i)-
1954 x -= glyphs.advances[i].toReal();-
1955 }-
1956-
1957-
1958 for (i = start; i < end; ++i)-
1959 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);-
1960 engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);-
1961-
1962 const int hi = which << 24;-
1963 for (i = start; i < end; ++i)-
1964 glyphs.glyphs[i] = hi | glyphs.glyphs[i];-
1965-
1966 if (!(flags & QTextItem::RightToLeft)) {-
1967 for (i = start; i < end; ++i)-
1968 x += glyphs.advances[i].toReal();-
1969 }-
1970-
1971-
1972 start = end;-
1973 which = e;-
1974 }-
1975-
1976 if (flags & QTextItem::RightToLeft) {-
1977 for (i = start; i < end; ++i)-
1978 x -= glyphs.advances[i].toReal();-
1979 }-
1980-
1981-
1982 for (i = start; i < end; ++i)-
1983 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);-
1984-
1985 engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);-
1986-
1987-
1988 const int hi = which << 24;-
1989 for (i = start; i < end; ++i)-
1990 glyphs.glyphs[i] = hi | glyphs.glyphs[i];-
1991}-
1992-
1993void QFontEngineMulti::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
1994{-
1995 if (glyphs->numGlyphs <= 0)-
1996 return;-
1997-
1998 int which = highByte(glyphs->glyphs[0]);-
1999 int start = 0;-
2000 int end, i;-
2001 for (end = 0; end < glyphs->numGlyphs; ++end) {-
2002 const int e = highByte(glyphs->glyphs[end]);-
2003 if (e == which)-
2004 continue;-
2005-
2006-
2007 for (i = start; i < end; ++i)-
2008 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);-
2009-
2010 QGlyphLayout offs = glyphs->mid(start, end - start);-
2011 engine(which)->recalcAdvances(&offs, flags);-
2012-
2013-
2014 const int hi = which << 24;-
2015 for (i = start; i < end; ++i)-
2016 glyphs->glyphs[i] = hi | glyphs->glyphs[i];-
2017-
2018-
2019 start = end;-
2020 which = e;-
2021 }-
2022-
2023-
2024 for (i = start; i < end; ++i)-
2025 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);-
2026-
2027 QGlyphLayout offs = glyphs->mid(start, end - start);-
2028 engine(which)->recalcAdvances(&offs, flags);-
2029-
2030-
2031 const int hi = which << 24;-
2032 for (i = start; i < end; ++i)-
2033 glyphs->glyphs[i] = hi | glyphs->glyphs[i];-
2034}-
2035-
2036void QFontEngineMulti::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
2037{-
2038 if (glyphs->numGlyphs <= 0)-
2039 return;-
2040-
2041 int which = highByte(glyphs->glyphs[0]);-
2042 int start = 0;-
2043 int end, i;-
2044 for (end = 0; end < glyphs->numGlyphs; ++end) {-
2045 const int e = highByte(glyphs->glyphs[end]);-
2046 if (e == which)-
2047 continue;-
2048-
2049-
2050 for (i = start; i < end; ++i)-
2051 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);-
2052-
2053 QGlyphLayout offs = glyphs->mid(start, end - start);-
2054 engine(which)->doKerning(&offs, flags);-
2055-
2056-
2057 const int hi = which << 24;-
2058 for (i = start; i < end; ++i)-
2059 glyphs->glyphs[i] = hi | glyphs->glyphs[i];-
2060-
2061-
2062 start = end;-
2063 which = e;-
2064 }-
2065-
2066-
2067 for (i = start; i < end; ++i)-
2068 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);-
2069-
2070 QGlyphLayout offs = glyphs->mid(start, end - start);-
2071 engine(which)->doKerning(&offs, flags);-
2072-
2073-
2074 const int hi = which << 24;-
2075 for (i = start; i < end; ++i)-
2076 glyphs->glyphs[i] = hi | glyphs->glyphs[i];-
2077}-
2078-
2079glyph_metrics_t QFontEngineMulti::boundingBox(glyph_t glyph)-
2080{-
2081 const int which = highByte(glyph);-
2082 return engine(which)->boundingBox(stripped(glyph));-
2083}-
2084-
2085QFixed QFontEngineMulti::ascent() const-
2086{ return engine(0)->ascent(); }-
2087-
2088QFixed QFontEngineMulti::descent() const-
2089{ return engine(0)->descent(); }-
2090-
2091QFixed QFontEngineMulti::leading() const-
2092{-
2093 return engine(0)->leading();-
2094}-
2095-
2096QFixed QFontEngineMulti::xHeight() const-
2097{-
2098 return engine(0)->xHeight();-
2099}-
2100-
2101QFixed QFontEngineMulti::averageCharWidth() const-
2102{-
2103 return engine(0)->averageCharWidth();-
2104}-
2105-
2106QFixed QFontEngineMulti::lineThickness() const-
2107{-
2108 return engine(0)->lineThickness();-
2109}-
2110-
2111QFixed QFontEngineMulti::underlinePosition() const-
2112{-
2113 return engine(0)->underlinePosition();-
2114}-
2115-
2116qreal QFontEngineMulti::maxCharWidth() const-
2117{-
2118 return engine(0)->maxCharWidth();-
2119}-
2120-
2121qreal QFontEngineMulti::minLeftBearing() const-
2122{-
2123 return engine(0)->minLeftBearing();-
2124}-
2125-
2126qreal QFontEngineMulti::minRightBearing() const-
2127{-
2128 return engine(0)->minRightBearing();-
2129}-
2130-
2131bool QFontEngineMulti::canRender(const QChar *string, int len) const-
2132{-
2133 if (engine(0)->canRender(string, len))-
2134 return true;-
2135-
2136 int nglyphs = len;-
2137-
2138 QVarLengthArray<glyph_t> glyphs(nglyphs);-
2139-
2140 QGlyphLayout g;-
2141 g.numGlyphs = nglyphs;-
2142 g.glyphs = glyphs.data();-
2143 if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))-
2144 do { ((!(false)) ? qt_assert_x("Q_UNREACHABLE()", "Q_UNREACHABLE was reached",__FILE__,22192212) : qt_noop()); __builtin_unreachable(); } while (0);-
2145-
2146 for (int i = 0; i < nglyphs; i++) {-
2147 if (glyphs[i] == 0)-
2148 return false;-
2149 }-
2150-
2151 return true;-
2152}-
2153-
2154-
2155-
2156-
2157QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph)-
2158{-
2159 const int which = highByte(glyph);-
2160 return engine(which)->alphaMapForGlyph(stripped(glyph));-
2161}-
2162-
2163QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)-
2164{-
2165 const int which = highByte(glyph);-
2166 return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition);-
2167}-
2168-
2169QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, const QTransform &t)-
2170{-
2171 const int which = highByte(glyph);-
2172 return engine(which)->alphaMapForGlyph(stripped(glyph), t);-
2173}-
2174-
2175QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
2176{-
2177 const int which = highByte(glyph);-
2178 return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition, t);-
2179}-
2180-
2181QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
2182{-
2183 const int which = highByte(glyph);-
2184 return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);-
2185}-
2186QFontEngine *QFontEngineMulti::createMultiFontEngine(QFontEngine *fe, int script)-
2187{-
2188 QFontEngine *engine = 0;-
2189 QFontCache::Key key(fe->fontDef, script, true);-
2190 QFontCache *fc = QFontCache::instance();-
2191-
2192-
2193-
2194-
2195-
2196 const bool faceIsLocal = !fe->faceId().filename.isEmpty();-
2197 QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),-
2198 end = fc->engineCache.end();-
2199 while (it != end && it.key() == key) {-
2200 ((!(it.value().data->type() == QFontEngine::Multi)) ? qt_assert("it.value().data->type() == QFontEngine::Multi",__FILE__,22842277) : qt_noop());-
2201 QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);-
2202 if (fe == cachedEngine->engine(0) || (faceIsLocal && fe->faceId().filename == cachedEngine->engine(0)->faceId().filename)) {-
2203 engine = cachedEngine;-
2204 fc->updateHitCountAndTimeStamp(it.value());-
2205 break;-
2206 }-
2207 ++it;-
2208 }-
2209 if (!engine) {-
2210 engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));-
2211 fc->insertEngine(key, engine, !faceIsLocal);-
2212 }-
2213 ((!(engine)) ? qt_assert("engine",__FILE__,22972290) : qt_noop());-
2214 return engine;-
2215}-
2216-
2217QTestFontEngine::QTestFontEngine(int size)-
2218 : QFontEngineBox(TestFontEngine, size)-
2219{}-
2220-
2221-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9