qfontengine.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qfontengine.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include <qdebug.h>-
41#include <private/qfontengine_p.h>-
42#include <private/qfontengineglyphcache_p.h>-
43#include <private/qguiapplication_p.h>-
44-
45#include <qpa/qplatformfontdatabase.h>-
46#include <qpa/qplatformintegration.h>-
47-
48#include "qbitmap.h"-
49#include "qpainter.h"-
50#include "qpainterpath.h"-
51#include "qvarlengtharray.h"-
52#include <qmath.h>-
53#include <qendian.h>-
54#include <private/qstringiterator_p.h>-
55-
56#ifdef QT_ENABLE_HARFBUZZ_NG-
57# include "qharfbuzzng_p.h"-
58# include <harfbuzz/hb-ot.h>-
59#endif-
60#include <private/qharfbuzz_p.h>-
61-
62#include <algorithm>-
63#include <limits.h>-
64-
65QT_BEGIN_NAMESPACE-
66-
67static inline bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b)-
68{-
69 if (a.type() <= QTransform::TxTranslate && b.type() <= QTransform::TxTranslate) {
a.type() <= QT...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
b.type() <= QT...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
0
70 return true;
never executed: return true;
0
71 } else {-
72 // We always use paths for perspective text anyway, so no-
73 // point in checking the full matrix...-
74 Q_ASSERT(a.type() < QTransform::TxProject);-
75 Q_ASSERT(b.type() < QTransform::TxProject);-
76-
77 return a.m11() == b.m11()
never executed: return a.m11() == b.m11() && a.m12() == b.m12() && a.m21() == b.m21() && a.m22() == b.m22();
0
78 && a.m12() == b.m12()
never executed: return a.m11() == b.m11() && a.m12() == b.m12() && a.m21() == b.m21() && a.m22() == b.m22();
0
79 && a.m21() == b.m21()
never executed: return a.m11() == b.m11() && a.m12() == b.m12() && a.m21() == b.m21() && a.m22() == b.m22();
0
80 && a.m22() == b.m22();
never executed: return a.m11() == b.m11() && a.m12() == b.m12() && a.m21() == b.m21() && a.m22() == b.m22();
0
81 }-
82}-
83-
84template<typename T>-
85static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)-
86{-
87 if (source + sizeof(T) > end)
source + sizeof(T) > endDescription
TRUEnever evaluated
FALSEnever evaluated
0
88 return false;
never executed: return false;
0
89-
90 *output = qFromBigEndian<T>(source);-
91 return true;
never executed: return true;
0
92}-
93-
94// Harfbuzz helper functions-
95-
96#ifdef QT_ENABLE_HARFBUZZ_NG-
97Q_GLOBAL_STATIC_WITH_ARGS(bool, useHarfbuzzNG,(qgetenv("QT_HARFBUZZ") != "old"))
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
98-
99bool qt_useHarfbuzzNG()-
100{-
101 return *useHarfbuzzNG();
never executed: return *useHarfbuzzNG();
0
102}-
103#endif-
104-
105Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t));-
106Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed));-
107-
108static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)-
109{-
110 QFontEngine *fe = (QFontEngine *)font->userData;-
111-
112 const QChar *str = reinterpret_cast<const QChar *>(string);-
113-
114 QGlyphLayout qglyphs;-
115 qglyphs.numGlyphs = *numGlyphs;-
116 qglyphs.glyphs = glyphs;-
117 int nGlyphs = *numGlyphs;-
118 bool result = fe->stringToCMap(str, length, &qglyphs, &nGlyphs, QFontEngine::GlyphIndicesOnly);-
119 *numGlyphs = nGlyphs;-
120-
121 if (rightToLeft && result && !fe->symbol) {
rightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
resultDescription
TRUEnever evaluated
FALSEnever evaluated
!fe->symbolDescription
TRUEnever evaluated
FALSEnever evaluated
0
122 QStringIterator it(str, str + length);-
123 while (it.hasNext()) {
it.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
124 const uint ucs4 = it.next();-
125 const uint mirrored = QChar::mirroredChar(ucs4);-
126 if (Q_UNLIKELY(mirrored != ucs4))
__builtin_expe... ucs4), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
127 *glyphs = fe->glyphIndex(mirrored);
never executed: *glyphs = fe->glyphIndex(mirrored);
0
128 ++glyphs;-
129 }
never executed: end of block
0
130 }
never executed: end of block
0
131-
132 return result;
never executed: return result;
0
133}-
134-
135static void hb_getAdvances(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags)-
136{-
137 QFontEngine *fe = (QFontEngine *)font->userData;-
138-
139 QGlyphLayout qglyphs;-
140 qglyphs.numGlyphs = numGlyphs;-
141 qglyphs.glyphs = const_cast<glyph_t *>(glyphs);-
142 qglyphs.advances = reinterpret_cast<QFixed *>(advances);-
143-
144 fe->recalcAdvances(&qglyphs, (flags & HB_ShaperFlag_UseDesignMetrics) ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags(0));-
145}
never executed: end of block
0
146-
147static HB_Bool hb_canRender(HB_Font font, const HB_UChar16 *string, hb_uint32 length)-
148{-
149 QFontEngine *fe = (QFontEngine *)font->userData;-
150 return fe->canRender(reinterpret_cast<const QChar *>(string), length);
never executed: return fe->canRender(reinterpret_cast<const QChar *>(string), length);
0
151}-
152-
153static void hb_getGlyphMetrics(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)-
154{-
155 QFontEngine *fe = (QFontEngine *)font->userData;-
156 glyph_metrics_t m = fe->boundingBox(glyph);-
157 metrics->x = m.x.value();-
158 metrics->y = m.y.value();-
159 metrics->width = m.width.value();-
160 metrics->height = m.height.value();-
161 metrics->xOffset = m.xoff.value();-
162 metrics->yOffset = m.yoff.value();-
163}
never executed: end of block
0
164-
165static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)-
166{-
167 if (metric == HB_FontAscent) {
metric == HB_FontAscentDescription
TRUEnever evaluated
FALSEnever evaluated
0
168 QFontEngine *fe = (QFontEngine *)font->userData;-
169 return fe->ascent().value();
never executed: return fe->ascent().value();
0
170 }-
171 return 0;
never executed: return 0;
0
172}-
173-
174int QFontEngine::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints)-
175{-
176 Q_UNUSED(glyph)-
177 Q_UNUSED(flags)-
178 Q_UNUSED(point)-
179 Q_UNUSED(xpos)-
180 Q_UNUSED(ypos)-
181 Q_UNUSED(nPoints)-
182 return Err_Not_Covered;
never executed: return Err_Not_Covered;
0
183}-
184-
185static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)-
186{-
187 QFontEngine *fe = (QFontEngine *)font->userData;-
188 return (HB_Error)fe->getPointInOutline(glyph, flags, point, (QFixed *)xpos, (QFixed *)ypos, (quint32 *)nPoints);
never executed: return (HB_Error)fe->getPointInOutline(glyph, flags, point, (QFixed *)xpos, (QFixed *)ypos, (quint32 *)nPoints);
0
189}-
190-
191static const HB_FontClass hb_fontClass = {-
192 hb_stringToGlyphs, hb_getAdvances, hb_canRender, hb_getPointInOutline,-
193 hb_getGlyphMetrics, hb_getFontMetric-
194};-
195-
196static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)-
197{-
198 QFontEngine::FaceData *data = (QFontEngine::FaceData *)font;-
199 Q_ASSERT(data);-
200-
201 qt_get_font_table_func_t get_font_table = data->get_font_table;-
202 Q_ASSERT(get_font_table);-
203-
204 if (!get_font_table(data->user_data, tableTag, buffer, length))
!get_font_tabl...uffer, length)Description
TRUEnever evaluated
FALSEnever evaluated
0
205 return HB_Err_Invalid_Argument;
never executed: return HB_Err_Invalid_Argument;
0
206 return HB_Err_Ok;
never executed: return HB_Err_Ok;
0
207}-
208-
209static void hb_freeFace(void *face)-
210{-
211 qHBFreeFace((HB_Face)face);-
212}
never executed: end of block
0
213-
214-
215static bool qt_get_font_table_default(void *user_data, uint tag, uchar *buffer, uint *length)-
216{-
217 QFontEngine *fe = (QFontEngine *)user_data;-
218 return fe->getSfntTableData(tag, buffer, length);
never executed: return fe->getSfntTableData(tag, buffer, length);
0
219}-
220-
221-
222#ifdef QT_BUILD_INTERNAL-
223// for testing purpose only, not thread-safe!-
224static QList<QFontEngine *> *enginesCollector = 0;-
225-
226Q_AUTOTEST_EXPORT void QFontEngine_startCollectingEngines()-
227{-
228 delete enginesCollector;-
229 enginesCollector = new QList<QFontEngine *>();-
230}
never executed: end of block
0
231-
232Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines()-
233{-
234 Q_ASSERT(enginesCollector);-
235 QList<QFontEngine *> ret = *enginesCollector;-
236 delete enginesCollector;-
237 enginesCollector = 0;-
238 return ret;
never executed: return ret;
0
239}-
240#endif // QT_BUILD_INTERNAL-
241-
242-
243// QFontEngine-
244-
245#define kBearingNotInitialized std::numeric_limits<qreal>::max()-
246-
247QFontEngine::QFontEngine(Type type)-
248 : m_type(type), ref(0),-
249 font_(),-
250 face_(),-
251 m_minLeftBearing(kBearingNotInitialized),-
252 m_minRightBearing(kBearingNotInitialized)-
253{-
254 faceData.user_data = this;-
255 faceData.get_font_table = qt_get_font_table_default;-
256-
257 cache_cost = 0;-
258 fsType = 0;-
259 symbol = false;-
260 isSmoothlyScalable = false;-
261-
262 glyphFormat = Format_None;-
263 m_subPixelPositionCount = 0;-
264-
265#ifdef QT_BUILD_INTERNAL-
266 if (enginesCollector)
enginesCollectorDescription
TRUEnever evaluated
FALSEnever evaluated
0
267 enginesCollector->append(this);
never executed: enginesCollector->append(this);
0
268#endif-
269}
never executed: end of block
0
270-
271QFontEngine::~QFontEngine()-
272{-
273#ifdef QT_BUILD_INTERNAL-
274 if (enginesCollector)
enginesCollectorDescription
TRUEnever evaluated
FALSEnever evaluated
0
275 enginesCollector->removeOne(this);
never executed: enginesCollector->removeOne(this);
0
276#endif-
277}
never executed: end of block
0
278-
279QFixed QFontEngine::lineThickness() const-
280{-
281 // ad hoc algorithm-
282 int score = fontDef.weight * fontDef.pixelSize;-
283 int lw = score / 700;-
284-
285 // looks better with thicker line for small pointsizes-
286 if (lw < 2 && score >= 1050) lw = 2;
never executed: lw = 2;
lw < 2Description
TRUEnever evaluated
FALSEnever evaluated
score >= 1050Description
TRUEnever evaluated
FALSEnever evaluated
0
287 if (lw == 0) lw = 1;
never executed: lw = 1;
lw == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
288-
289 return lw;
never executed: return lw;
0
290}-
291-
292QFixed QFontEngine::underlinePosition() const-
293{-
294 return ((lineThickness() * 2) + 3) / 6;
never executed: return ((lineThickness() * 2) + 3) / 6;
0
295}-
296-
297void *QFontEngine::harfbuzzFont() const-
298{-
299 Q_ASSERT(type() != QFontEngine::Multi);-
300#ifdef QT_ENABLE_HARFBUZZ_NG-
301 if (qt_useHarfbuzzNG())
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
0
302 return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
never executed: return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
0
303#endif-
304 if (!font_) {
!font_Description
TRUEnever evaluated
FALSEnever evaluated
0
305 HB_Face hbFace = (HB_Face)harfbuzzFace();-
306 if (hbFace->font_for_init) {
hbFace->font_for_initDescription
TRUEnever evaluated
FALSEnever evaluated
0
307 void *data = hbFace->font_for_init;-
308 q_check_ptr(qHBLoadFace(hbFace));-
309 free(data);-
310 }
never executed: end of block
0
311-
312 HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec));-
313 Q_CHECK_PTR(hbFont);
never executed: qt_check_pointer(__FILE__,313);
!(hbFont)Description
TRUEnever evaluated
FALSEnever evaluated
0
314 hbFont->klass = &hb_fontClass;-
315 hbFont->userData = const_cast<QFontEngine *>(this);-
316-
317 qint64 emSquare = emSquareSize().truncate();-
318 Q_ASSERT(emSquare == emSquareSize().toInt()); // ensure no truncation-
319 if (emSquare == 0)
emSquare == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
320 emSquare = 1000; // a fallback value suitable for Type1 fonts
never executed: emSquare = 1000;
0
321 hbFont->y_ppem = fontDef.pixelSize;-
322 hbFont->x_ppem = fontDef.pixelSize * fontDef.stretch / 100;-
323 // same as QFixed(x)/QFixed(emSquare) but without int32 overflow for x-
324 hbFont->x_scale = (((qint64)hbFont->x_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare;-
325 hbFont->y_scale = (((qint64)hbFont->y_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare;-
326-
327 font_ = Holder(hbFont, free);-
328 }
never executed: end of block
0
329 return font_.get();
never executed: return font_.get();
0
330}-
331-
332void *QFontEngine::harfbuzzFace() const-
333{-
334 Q_ASSERT(type() != QFontEngine::Multi);-
335#ifdef QT_ENABLE_HARFBUZZ_NG-
336 if (qt_useHarfbuzzNG())
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
0
337 return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
never executed: return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
0
338#endif-
339 if (!face_) {
!face_Description
TRUEnever evaluated
FALSEnever evaluated
0
340 QFontEngine::FaceData *data = (QFontEngine::FaceData *)malloc(sizeof(QFontEngine::FaceData));-
341 Q_CHECK_PTR(data);
never executed: qt_check_pointer(__FILE__,341);
!(data)Description
TRUEnever evaluated
FALSEnever evaluated
0
342 data->user_data = faceData.user_data;-
343 data->get_font_table = faceData.get_font_table;-
344-
345 HB_Face hbFace = qHBNewFace(data, hb_getSFntTable);-
346 Q_CHECK_PTR(hbFace);
never executed: qt_check_pointer(__FILE__,346);
!(hbFace)Description
TRUEnever evaluated
FALSEnever evaluated
0
347 hbFace->isSymbolFont = symbol;-
348-
349 face_ = Holder(hbFace, hb_freeFace);-
350 }
never executed: end of block
0
351 return face_.get();
never executed: return face_.get();
0
352}-
353-
354bool QFontEngine::supportsScript(QChar::Script script) const-
355{-
356 if (type() <= QFontEngine::Multi)
type() <= QFontEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
357 return true;
never executed: return true;
0
358-
359 // ### TODO: This only works for scripts that require OpenType. More generally-
360 // for scripts that do not require OpenType we should just look at the list of-
361 // supported writing systems in the font's OS/2 table.-
362 if (!((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
script >= QChar::Script_SyriacDescription
TRUEnever evaluated
FALSEnever evaluated
script <= QCha...Script_SinhalaDescription
TRUEnever evaluated
FALSEnever evaluated
0
363 || script == QChar::Script_Khmer || script == QChar::Script_Nko)) {
script == QChar::Script_KhmerDescription
TRUEnever evaluated
FALSEnever evaluated
script == QChar::Script_NkoDescription
TRUEnever evaluated
FALSEnever evaluated
0
364 return true;
never executed: return true;
0
365 }-
366-
367#ifdef QT_ENABLE_HARFBUZZ_NG-
368 if (qt_useHarfbuzzNG()) {
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
0
369#if defined(Q_OS_DARWIN)-
370 // in AAT fonts, 'gsub' table is effectively replaced by 'mort'/'morx' table-
371 uint len;-
372 if (getSfntTableData(MAKE_TAG('m','o','r','t'), 0, &len) || getSfntTableData(MAKE_TAG('m','o','r','x'), 0, &len))-
373 return true;-
374#endif-
375-
376 bool ret = false;-
377 if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {
hb_face_t *fac...gine *>(this))Description
TRUEnever evaluated
FALSEnever evaluated
0
378 hb_tag_t script_tag_1, script_tag_2;-
379 hb_ot_tags_from_script(hb_qt_script_to_script(script), &script_tag_1, &script_tag_2);-
380-
381 unsigned int script_index;-
382 ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_1, &script_index);-
383 if (!ret) {
!retDescription
TRUEnever evaluated
FALSEnever evaluated
0
384 ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, script_tag_2, &script_index);-
385 if (!ret && script_tag_2 != HB_OT_TAG_DEFAULT_SCRIPT)
!retDescription
TRUEnever evaluated
FALSEnever evaluated
script_tag_2 !...nt8_t)('T'))))Description
TRUEnever evaluated
FALSEnever evaluated
0
386 ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, HB_OT_TAG_DEFAULT_SCRIPT, &script_index);
never executed: 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);
0
387 }
never executed: end of block
0
388 }
never executed: end of block
0
389 return ret;
never executed: return ret;
0
390 }-
391#endif-
392 HB_Face hbFace = (HB_Face)harfbuzzFace();-
393 if (hbFace->font_for_init) {
hbFace->font_for_initDescription
TRUEnever evaluated
FALSEnever evaluated
0
394 void *data = hbFace->font_for_init;-
395 q_check_ptr(qHBLoadFace(hbFace));-
396 free(data);-
397 }
never executed: end of block
0
398 return hbFace->supported_scripts[script_to_hbscript(script)];
never executed: return hbFace->supported_scripts[script_to_hbscript(script)];
0
399}-
400-
401bool QFontEngine::canRender(const QChar *str, int len) const-
402{-
403 QStringIterator it(str, str + len);-
404 while (it.hasNext()) {
it.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
405 if (glyphIndex(it.next()) == 0)
glyphIndex(it.next()) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
406 return false;
never executed: return false;
0
407 }
never executed: end of block
0
408-
409 return true;
never executed: return true;
0
410}-
411-
412glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix)-
413{-
414 glyph_metrics_t metrics = boundingBox(glyph);-
415-
416 if (matrix.type() > QTransform::TxTranslate) {
matrix.type() ...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
0
417 return metrics.transformed(matrix);
never executed: return metrics.transformed(matrix);
0
418 }-
419 return metrics;
never executed: return metrics;
0
420}-
421-
422QFixed QFontEngine::xHeight() const-
423{-
424 const glyph_t glyph = glyphIndex('x');-
425 glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
426 return bb.height;
never executed: return bb.height;
0
427}-
428-
429QFixed QFontEngine::averageCharWidth() const-
430{-
431 const glyph_t glyph = glyphIndex('x');-
432 glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
433 return bb.xoff;
never executed: return bb.xoff;
0
434}-
435-
436bool QFontEngine::supportsTransformation(const QTransform &transform) const-
437{-
438 return transform.type() < QTransform::TxProject;
never executed: return transform.type() < QTransform::TxProject;
0
439}-
440-
441void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,-
442 QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions)-
443{-
444 QFixed xpos;-
445 QFixed ypos;-
446-
447 const bool transform = matrix.m11() != 1.
matrix.m11() != 1.Description
TRUEnever evaluated
FALSEnever evaluated
0
448 || matrix.m12() != 0.
matrix.m12() != 0.Description
TRUEnever evaluated
FALSEnever evaluated
0
449 || matrix.m21() != 0.
matrix.m21() != 0.Description
TRUEnever evaluated
FALSEnever evaluated
0
450 || matrix.m22() != 1.;
matrix.m22() != 1.Description
TRUEnever evaluated
FALSEnever evaluated
0
451 if (!transform) {
!transformDescription
TRUEnever evaluated
FALSEnever evaluated
0
452 xpos = QFixed::fromReal(matrix.dx());-
453 ypos = QFixed::fromReal(matrix.dy());-
454 }
never executed: end of block
0
455-
456 int current = 0;-
457 if (flags & QTextItem::RightToLeft) {
flags & QTextItem::RightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
458 int i = glyphs.numGlyphs;-
459 int totalKashidas = 0;-
460 while(i--) {
i--Description
TRUEnever evaluated
FALSEnever evaluated
0
461 if (glyphs.attributes[i].dontPrint)
glyphs.attributes[i].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
0
462 continue;
never executed: continue;
0
463 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
464 totalKashidas += glyphs.justifications[i].nKashidas;-
465 }
never executed: end of block
0
466 positions.resize(glyphs.numGlyphs+totalKashidas);-
467 glyphs_out.resize(glyphs.numGlyphs+totalKashidas);-
468-
469 i = 0;-
470 while(i < glyphs.numGlyphs) {
i < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
471 if (glyphs.attributes[i].dontPrint) {
glyphs.attributes[i].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
0
472 ++i;-
473 continue;
never executed: continue;
0
474 }-
475 xpos -= glyphs.advances[i];-
476-
477 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
478 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
479 if (transform) {
transformDescription
TRUEnever evaluated
FALSEnever evaluated
0
480 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
481 gpos = gpos * matrix;-
482 gpos_x = QFixed::fromReal(gpos.x());-
483 gpos_y = QFixed::fromReal(gpos.y());-
484 }
never executed: end of block
0
485 positions[current].x = gpos_x;-
486 positions[current].y = gpos_y;-
487 glyphs_out[current] = glyphs.glyphs[i];-
488 ++current;-
489 if (glyphs.justifications[i].nKashidas) {
glyphs.justifi...s[i].nKashidasDescription
TRUEnever evaluated
FALSEnever evaluated
0
490 QChar ch(0x640); // Kashida character-
491-
492 glyph_t kashidaGlyph = glyphIndex(ch.unicode());-
493 QFixed kashidaWidth;-
494-
495 QGlyphLayout g;-
496 g.numGlyphs = 1;-
497 g.glyphs = &kashidaGlyph;-
498 g.advances = &kashidaWidth;-
499 recalcAdvances(&g, 0);-
500-
501 for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
k < glyphs.jus...s[i].nKashidasDescription
TRUEnever evaluated
FALSEnever evaluated
0
502 xpos -= kashidaWidth;-
503-
504 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
505 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
506 if (transform) {
transformDescription
TRUEnever evaluated
FALSEnever evaluated
0
507 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
508 gpos = gpos * matrix;-
509 gpos_x = QFixed::fromReal(gpos.x());-
510 gpos_y = QFixed::fromReal(gpos.y());-
511 }
never executed: end of block
0
512 positions[current].x = gpos_x;-
513 positions[current].y = gpos_y;-
514 glyphs_out[current] = kashidaGlyph;-
515 ++current;-
516 }
never executed: end of block
0
517 } else {
never executed: end of block
0
518 xpos -= QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
519 }
never executed: end of block
0
520 ++i;-
521 }
never executed: end of block
0
522 } else {
never executed: end of block
0
523 positions.resize(glyphs.numGlyphs);-
524 glyphs_out.resize(glyphs.numGlyphs);-
525 int i = 0;-
526 if (!transform) {
!transformDescription
TRUEnever evaluated
FALSEnever evaluated
0
527 while (i < glyphs.numGlyphs) {
i < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
528 if (!glyphs.attributes[i].dontPrint) {
!glyphs.attrib...s[i].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
0
529 positions[current].x = xpos + glyphs.offsets[i].x;-
530 positions[current].y = ypos + glyphs.offsets[i].y;-
531 glyphs_out[current] = glyphs.glyphs[i];-
532 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
533 ++current;-
534 }
never executed: end of block
0
535 ++i;-
536 }
never executed: end of block
0
537 } else {
never executed: end of block
0
538 while (i < glyphs.numGlyphs) {
i < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
539 if (!glyphs.attributes[i].dontPrint) {
!glyphs.attrib...s[i].dontPrintDescription
TRUEnever evaluated
FALSEnever evaluated
0
540 QFixed gpos_x = xpos + glyphs.offsets[i].x;-
541 QFixed gpos_y = ypos + glyphs.offsets[i].y;-
542 QPointF gpos(gpos_x.toReal(), gpos_y.toReal());-
543 gpos = gpos * matrix;-
544 positions[current].x = QFixed::fromReal(gpos.x());-
545 positions[current].y = QFixed::fromReal(gpos.y());-
546 glyphs_out[current] = glyphs.glyphs[i];-
547 xpos += glyphs.advances[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6);-
548 ++current;-
549 }
never executed: end of block
0
550 ++i;-
551 }
never executed: end of block
0
552 }
never executed: end of block
0
553 }-
554 positions.resize(current);-
555 glyphs_out.resize(current);-
556 Q_ASSERT(positions.size() == glyphs_out.size());-
557}
never executed: end of block
0
558-
559void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)-
560{-
561 glyph_metrics_t gi = boundingBox(glyph);-
562 if (leftBearing != 0)
leftBearing != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
563 *leftBearing = gi.leftBearing().toReal();
never executed: *leftBearing = gi.leftBearing().toReal();
0
564 if (rightBearing != 0)
rightBearing != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
565 *rightBearing = gi.rightBearing().toReal();
never executed: *rightBearing = gi.rightBearing().toReal();
0
566}
never executed: end of block
0
567-
568qreal QFontEngine::minLeftBearing() const-
569{-
570 if (m_minLeftBearing == kBearingNotInitialized)
m_minLeftBeari...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
0
571 minRightBearing(); // Initializes both (see below)
never executed: minRightBearing();
0
572-
573 return m_minLeftBearing;
never executed: return m_minLeftBearing;
0
574}-
575-
576#define q16Dot16ToFloat(i) ((i) / 65536.0)-
577-
578#define kMinLeftSideBearingOffset 12-
579#define kMinRightSideBearingOffset 14-
580-
581qreal QFontEngine::minRightBearing() const-
582{-
583 if (m_minRightBearing == kBearingNotInitialized) {
m_minRightBear...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
0
584-
585 // Try the 'hhea' font table first, which covers the entire font-
586 QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));-
587 if (hheaTable.size() >= int(kMinRightSideBearingOffset + sizeof(qint16))) {
hheaTable.size...izeof(qint16))Description
TRUEnever evaluated
FALSEnever evaluated
0
588 const uchar *tableData = reinterpret_cast<const uchar *>(hheaTable.constData());-
589 Q_ASSERT(q16Dot16ToFloat(qFromBigEndian<quint32>(tableData)) == 1.0);-
590-
591 qint16 minLeftSideBearing = qFromBigEndian<qint16>(tableData + kMinLeftSideBearingOffset);-
592 qint16 minRightSideBearing = qFromBigEndian<qint16>(tableData + kMinRightSideBearingOffset);-
593-
594 // The table data is expressed as FUnits, meaning we have to take the number-
595 // of units per em into account. Since pixelSize already has taken DPI into-
596 // account we can use that directly instead of the point size.-
597 int unitsPerEm = emSquareSize().toInt();-
598 qreal funitToPixelFactor = fontDef.pixelSize / unitsPerEm;-
599-
600 // Some fonts on OS X (such as Gurmukhi Sangam MN, Khmer MN, Lao Sangam MN, etc.), have-
601 // invalid values for their NBSPACE left bearing, causing the 'hhea' minimum bearings to-
602 // be way off. We detect this by assuming that the minimum bearsings are within a certain-
603 // range of the em square size.-
604 static const int largestValidBearing = 4 * unitsPerEm;-
605-
606 if (qAbs(minLeftSideBearing) < largestValidBearing)
qAbs(minLeftSi...stValidBearingDescription
TRUEnever evaluated
FALSEnever evaluated
0
607 m_minLeftBearing = minLeftSideBearing * funitToPixelFactor;
never executed: m_minLeftBearing = minLeftSideBearing * funitToPixelFactor;
0
608 if (qAbs(minRightSideBearing) < largestValidBearing)
qAbs(minRightS...stValidBearingDescription
TRUEnever evaluated
FALSEnever evaluated
0
609 m_minRightBearing = minRightSideBearing * funitToPixelFactor;
never executed: m_minRightBearing = minRightSideBearing * funitToPixelFactor;
0
610 }
never executed: end of block
0
611-
612 // Fallback in case of missing 'hhea' table (bitmap fonts e.g.) or broken 'hhea' values-
613 if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) {
m_minLeftBeari...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
m_minRightBear...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
0
614-
615 // To balance performance and correctness we only look at a subset of the-
616 // possible glyphs in the font, based on which characters are more likely-
617 // to have a left or right bearing.-
618 static const ushort characterSubset[] = {-
619 '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|',-
620 127, 205, 645, 884, 922, 1070, 12386-
621 };-
622-
623 // The font may have minimum bearings larger than 0, so we have to start at the max-
624 m_minLeftBearing = m_minRightBearing = std::numeric_limits<qreal>::max();-
625-
626 for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) {
i < (sizeof(ch...izeof(ushort))Description
TRUEnever evaluated
FALSEnever evaluated
0
627 const glyph_t glyph = glyphIndex(characterSubset[i]);-
628 if (!glyph)
!glyphDescription
TRUEnever evaluated
FALSEnever evaluated
0
629 continue;
never executed: continue;
0
630-
631 glyph_metrics_t glyphMetrics = const_cast<QFontEngine *>(this)->boundingBox(glyph);-
632-
633 // Glyphs with no contours shouldn't contribute to bearings-
634 if (!glyphMetrics.width || !glyphMetrics.height)
!glyphMetrics.widthDescription
TRUEnever evaluated
FALSEnever evaluated
!glyphMetrics.heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
635 continue;
never executed: continue;
0
636-
637 m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal());-
638 m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal());-
639 }
never executed: end of block
0
640 }
never executed: end of block
0
641-
642 if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized)
m_minLeftBeari...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
m_minRightBear...<qreal>::max()Description
TRUEnever evaluated
FALSEnever evaluated
0
643 qWarning() << "Failed to compute left/right minimum bearings for" << fontDef.family;
never executed: QMessageLogger(__FILE__, 643, __PRETTY_FUNCTION__).warning() << "Failed to compute left/right minimum bearings for" << fontDef.family;
0
644 }
never executed: end of block
0
645-
646 return m_minRightBearing;
never executed: return m_minRightBearing;
0
647}-
648-
649glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)-
650{-
651 glyph_metrics_t overall;-
652-
653 QFixed ymax = 0;-
654 QFixed xmax = 0;-
655 for (int i = 0; i < glyphs.numGlyphs; i++) {
i < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
656 glyph_metrics_t bb = boundingBox(glyphs.glyphs[i]);-
657 QFixed x = overall.xoff + glyphs.offsets[i].x + bb.x;-
658 QFixed y = overall.yoff + glyphs.offsets[i].y + bb.y;-
659 overall.x = qMin(overall.x, x);-
660 overall.y = qMin(overall.y, y);-
661 xmax = qMax(xmax, x + bb.width);-
662 ymax = qMax(ymax, y + bb.height);-
663 overall.xoff += bb.xoff;-
664 overall.yoff += bb.yoff;-
665 }
never executed: end of block
0
666 overall.height = qMax(overall.height, ymax - overall.y);-
667 overall.width = xmax - overall.x;-
668-
669 return overall;
never executed: return overall;
0
670}-
671-
672-
673void QFontEngine::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path,-
674 QTextItem::RenderFlags flags)-
675{-
676 if (!glyphs.numGlyphs)
!glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
677 return;
never executed: return;
0
678-
679 QVarLengthArray<QFixedPoint> positions;-
680 QVarLengthArray<glyph_t> positioned_glyphs;-
681 QTransform matrix = QTransform::fromTranslate(x, y);-
682 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);-
683 addGlyphsToPath(positioned_glyphs.data(), positions.data(), positioned_glyphs.size(), path, flags);-
684}
never executed: end of block
0
685-
686#define GRID(x, y) grid[(y)*(w+1) + (x)]-
687#define SET(x, y) (*(image_data + (y)*bpl + ((x) >> 3)) & (0x80 >> ((x) & 7)))-
688-
689enum { EdgeRight = 0x1,-
690 EdgeDown = 0x2,-
691 EdgeLeft = 0x4,-
692 EdgeUp = 0x8-
693};-
694-
695static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, int w, int h, QPainterPath *path)-
696{-
697 Q_UNUSED(h);-
698-
699 path->moveTo(x + x0, y + y0);-
700 while (GRID(x, y)) {
grid[(y)*(w+1) + (x)]Description
TRUEnever evaluated
FALSEnever evaluated
0
701 if (GRID(x, y) & EdgeRight) {
grid[(y)*(w+1)...)] & EdgeRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
702 while (GRID(x, y) & EdgeRight) {
grid[(y)*(w+1)...)] & EdgeRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
703 GRID(x, y) &= ~EdgeRight;-
704 ++x;-
705 }
never executed: end of block
0
706 Q_ASSERT(x <= w);-
707 path->lineTo(x + x0, y + y0);-
708 continue;
never executed: continue;
0
709 }-
710 if (GRID(x, y) & EdgeDown) {
grid[(y)*(w+1)...x)] & EdgeDownDescription
TRUEnever evaluated
FALSEnever evaluated
0
711 while (GRID(x, y) & EdgeDown) {
grid[(y)*(w+1)...x)] & EdgeDownDescription
TRUEnever evaluated
FALSEnever evaluated
0
712 GRID(x, y) &= ~EdgeDown;-
713 ++y;-
714 }
never executed: end of block
0
715 Q_ASSERT(y <= h);-
716 path->lineTo(x + x0, y + y0);-
717 continue;
never executed: continue;
0
718 }-
719 if (GRID(x, y) & EdgeLeft) {
grid[(y)*(w+1)...x)] & EdgeLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
720 while (GRID(x, y) & EdgeLeft) {
grid[(y)*(w+1)...x)] & EdgeLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
721 GRID(x, y) &= ~EdgeLeft;-
722 --x;-
723 }
never executed: end of block
0
724 Q_ASSERT(x >= 0);-
725 path->lineTo(x + x0, y + y0);-
726 continue;
never executed: continue;
0
727 }-
728 if (GRID(x, y) & EdgeUp) {
grid[(y)*(w+1) + (x)] & EdgeUpDescription
TRUEnever evaluated
FALSEnever evaluated
0
729 while (GRID(x, y) & EdgeUp) {
grid[(y)*(w+1) + (x)] & EdgeUpDescription
TRUEnever evaluated
FALSEnever evaluated
0
730 GRID(x, y) &= ~EdgeUp;-
731 --y;-
732 }
never executed: end of block
0
733 Q_ASSERT(y >= 0);-
734 path->lineTo(x + x0, y + y0);-
735 continue;
never executed: continue;
0
736 }-
737 }
never executed: end of block
0
738 path->closeSubpath();-
739}
never executed: end of block
0
740-
741Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)-
742{-
743 uint *grid = new uint[(w+1)*(h+1)];-
744 // set up edges-
745 for (int y = 0; y <= h; ++y) {
y <= hDescription
TRUEnever evaluated
FALSEnever evaluated
0
746 for (int x = 0; x <= w; ++x) {
x <= wDescription
TRUEnever evaluated
FALSEnever evaluated
0
747 bool topLeft = (x == 0)|(y == 0) ? false : SET(x - 1, y - 1);
(x == 0)|(y == 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
748 bool topRight = (x == w)|(y == 0) ? false : SET(x, y - 1);
(x == w)|(y == 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
749 bool bottomLeft = (x == 0)|(y == h) ? false : SET(x - 1, y);
(x == 0)|(y == h)Description
TRUEnever evaluated
FALSEnever evaluated
0
750 bool bottomRight = (x == w)|(y == h) ? false : SET(x, y);
(x == w)|(y == h)Description
TRUEnever evaluated
FALSEnever evaluated
0
751-
752 GRID(x, y) = 0;-
753 if ((!topRight) & bottomRight)
(!topRight) & bottomRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
754 GRID(x, y) |= EdgeRight;
never executed: grid[(y)*(w+1) + (x)] |= EdgeRight;
0
755 if ((!bottomRight) & bottomLeft)
(!bottomRight) & bottomLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
756 GRID(x, y) |= EdgeDown;
never executed: grid[(y)*(w+1) + (x)] |= EdgeDown;
0
757 if ((!bottomLeft) & topLeft)
(!bottomLeft) & topLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
758 GRID(x, y) |= EdgeLeft;
never executed: grid[(y)*(w+1) + (x)] |= EdgeLeft;
0
759 if ((!topLeft) & topRight)
(!topLeft) & topRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
760 GRID(x, y) |= EdgeUp;
never executed: grid[(y)*(w+1) + (x)] |= EdgeUp;
0
761 }
never executed: end of block
0
762 }
never executed: end of block
0
763-
764 // collect edges-
765 for (int y = 0; y < h; ++y) {
y < hDescription
TRUEnever evaluated
FALSEnever evaluated
0
766 for (int x = 0; x < w; ++x) {
x < wDescription
TRUEnever evaluated
FALSEnever evaluated
0
767 if (!GRID(x, y))
!grid[(y)*(w+1) + (x)]Description
TRUEnever evaluated
FALSEnever evaluated
0
768 continue;
never executed: continue;
0
769 // found start of a contour, follow it-
770 collectSingleContour(x0, y0, grid, x, y, w, h, path);-
771 }
never executed: end of block
0
772 }
never executed: end of block
0
773 delete [] grid;-
774}
never executed: end of block
0
775-
776#undef GRID-
777#undef SET-
778-
779-
780void QFontEngine::addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &glyphs,-
781 QPainterPath *path, QTextItem::RenderFlags flags)-
782{-
783// TODO what to do with 'flags' ??-
784 Q_UNUSED(flags);-
785 QFixed advanceX = QFixed::fromReal(x);-
786 QFixed advanceY = QFixed::fromReal(y);-
787 for (int i=0; i < glyphs.numGlyphs; ++i) {
i < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
788 glyph_metrics_t metrics = boundingBox(glyphs.glyphs[i]);-
789 if (metrics.width.value() == 0 || metrics.height.value() == 0) {
metrics.width.value() == 0Description
TRUEnever evaluated
FALSEnever evaluated
metrics.height.value() == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
790 advanceX += glyphs.advances[i];-
791 continue;
never executed: continue;
0
792 }-
793 const QImage alphaMask = alphaMapForGlyph(glyphs.glyphs[i]);-
794-
795 const int w = alphaMask.width();-
796 const int h = alphaMask.height();-
797 const int srcBpl = alphaMask.bytesPerLine();-
798 QImage bitmap;-
799 if (alphaMask.depth() == 1) {
alphaMask.depth() == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
800 bitmap = alphaMask;-
801 } else {
never executed: end of block
0
802 bitmap = QImage(w, h, QImage::Format_Mono);-
803 const uchar *imageData = alphaMask.bits();-
804 const int destBpl = bitmap.bytesPerLine();-
805 uchar *bitmapData = bitmap.bits();-
806-
807 for (int yi = 0; yi < h; ++yi) {
yi < hDescription
TRUEnever evaluated
FALSEnever evaluated
0
808 const uchar *src = imageData + yi*srcBpl;-
809 uchar *dst = bitmapData + yi*destBpl;-
810 for (int xi = 0; xi < w; ++xi) {
xi < wDescription
TRUEnever evaluated
FALSEnever evaluated
0
811 const int byte = xi / 8;-
812 const int bit = xi % 8;-
813 if (bit == 0)
bit == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
814 dst[byte] = 0;
never executed: dst[byte] = 0;
0
815 if (src[xi])
src[xi]Description
TRUEnever evaluated
FALSEnever evaluated
0
816 dst[byte] |= 128 >> bit;
never executed: dst[byte] |= 128 >> bit;
0
817 }
never executed: end of block
0
818 }
never executed: end of block
0
819 }
never executed: end of block
0
820 const uchar *bitmap_data = bitmap.constBits();-
821 QFixedPoint offset = glyphs.offsets[i];-
822 advanceX += offset.x;-
823 advanceY += offset.y;-
824 qt_addBitmapToPath((advanceX + metrics.x).toReal(), (advanceY + metrics.y).toReal(), bitmap_data, bitmap.bytesPerLine(), w, h, path);-
825 advanceX += glyphs.advances[i];-
826 }
never executed: end of block
0
827}
never executed: end of block
0
828-
829void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,-
830 QPainterPath *path, QTextItem::RenderFlags flags)-
831{-
832 qreal x = positions[0].x.toReal();-
833 qreal y = positions[0].y.toReal();-
834 QVarLengthGlyphLayoutArray g(nGlyphs);-
835-
836 for (int i = 0; i < nGlyphs - 1; ++i) {
i < nGlyphs - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
837 g.glyphs[i] = glyphs[i];-
838 g.advances[i] = positions[i + 1].x - positions[i].x;-
839 }
never executed: end of block
0
840 g.glyphs[nGlyphs - 1] = glyphs[nGlyphs - 1];-
841 g.advances[nGlyphs - 1] = QFixed::fromReal(maxCharWidth());-
842-
843 addBitmapFontToPath(x, y, g, path, flags);-
844}
never executed: end of block
0
845-
846QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/)-
847{-
848 // For font engines don't support subpixel positioning-
849 return alphaMapForGlyph(glyph);
never executed: return alphaMapForGlyph(glyph);
0
850}-
851-
852QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)-
853{-
854 QImage i = alphaMapForGlyph(glyph);-
855 if (t.type() > QTransform::TxTranslate)
t.type() > QTr...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
0
856 i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);
never executed: i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);
0
857 Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...-
858-
859 return i;
never executed: return i;
0
860}-
861-
862QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
863{-
864 if (! supportsSubPixelPositions())
! supportsSubPixelPositions()Description
TRUEnever evaluated
FALSEnever evaluated
0
865 return alphaMapForGlyph(glyph, t);
never executed: return alphaMapForGlyph(glyph, t);
0
866-
867 QImage i = alphaMapForGlyph(glyph, subPixelPosition);-
868 if (t.type() > QTransform::TxTranslate)
t.type() > QTr...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
0
869 i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);
never executed: i = i.transformed(t).convertToFormat(QImage::Format_Alpha8);
0
870 Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...-
871-
872 return i;
never executed: return i;
0
873}-
874-
875QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &t)-
876{-
877 const QImage alphaMask = alphaMapForGlyph(glyph, t);-
878 QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);-
879-
880 for (int y=0; y<alphaMask.height(); ++y) {
y<alphaMask.height()Description
TRUEnever evaluated
FALSEnever evaluated
0
881 uint *dst = (uint *) rgbMask.scanLine(y);-
882 const uchar *src = alphaMask.constScanLine(y);-
883 for (int x=0; x<alphaMask.width(); ++x) {
x<alphaMask.width()Description
TRUEnever evaluated
FALSEnever evaluated
0
884 int val = src[x];-
885 dst[x] = qRgb(val, val, val);-
886 }
never executed: end of block
0
887 }
never executed: end of block
0
888-
889 return rgbMask;
never executed: return rgbMask;
0
890}-
891-
892QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&)-
893{-
894 Q_UNUSED(subPixelPosition);-
895-
896 return QImage();
never executed: return QImage();
0
897}-
898-
899QFixed QFontEngine::subPixelPositionForX(QFixed x) const-
900{-
901 if (m_subPixelPositionCount <= 1 || !supportsSubPixelPositions())
m_subPixelPositionCount <= 1Description
TRUEnever evaluated
FALSEnever evaluated
!supportsSubPixelPositions()Description
TRUEnever evaluated
FALSEnever evaluated
0
902 return QFixed();
never executed: return QFixed();
0
903-
904 QFixed subPixelPosition;-
905 if (x != 0) {
x != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
906 subPixelPosition = x - x.floor();-
907 QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();-
908-
909 // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over-
910 // the lower boundary for the selected rasterization by adding 1/64.-
911 subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);-
912 }
never executed: end of block
0
913 return subPixelPosition;
never executed: return subPixelPosition;
0
914}-
915-
916QImage *QFontEngine::lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,-
917 QFontEngine::GlyphFormat neededFormat,-
918 const QTransform &t, QPoint *offset)-
919{-
920 Q_ASSERT(currentlyLockedAlphaMap.isNull());-
921 if (neededFormat == Format_None)
neededFormat == Format_NoneDescription
TRUEnever evaluated
FALSEnever evaluated
0
922 neededFormat = Format_A32;
never executed: neededFormat = Format_A32;
0
923-
924 if (neededFormat != Format_A32)
neededFormat != Format_A32Description
TRUEnever evaluated
FALSEnever evaluated
0
925 currentlyLockedAlphaMap = alphaMapForGlyph(glyph, subPixelPosition, t);
never executed: currentlyLockedAlphaMap = alphaMapForGlyph(glyph, subPixelPosition, t);
0
926 else-
927 currentlyLockedAlphaMap = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
never executed: currentlyLockedAlphaMap = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
0
928-
929 if (offset != 0)
offset != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
930 *offset = QPoint(0, 0);
never executed: *offset = QPoint(0, 0);
0
931-
932 return &currentlyLockedAlphaMap;
never executed: return &currentlyLockedAlphaMap;
0
933}-
934-
935void QFontEngine::unlockAlphaMapForGlyph()-
936{-
937 Q_ASSERT(!currentlyLockedAlphaMap.isNull());-
938 currentlyLockedAlphaMap = QImage();-
939}
never executed: end of block
0
940-
941QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)-
942{-
943 glyph_metrics_t gm = boundingBox(glyph);-
944 int glyph_x = qFloor(gm.x.toReal());-
945 int glyph_y = qFloor(gm.y.toReal());-
946 int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x;-
947 int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y;-
948-
949 if (glyph_width <= 0 || glyph_height <= 0)
glyph_width <= 0Description
TRUEnever evaluated
FALSEnever evaluated
glyph_height <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
950 return QImage();
never executed: return QImage();
0
951 QFixedPoint pt;-
952 pt.x = -glyph_x;-
953 pt.y = -glyph_y; // the baseline-
954 QPainterPath path;-
955 path.setFillRule(Qt::WindingFill);-
956 QImage im(glyph_width, glyph_height, QImage::Format_ARGB32_Premultiplied);-
957 im.fill(Qt::transparent);-
958 QPainter p(&im);-
959 p.setRenderHint(QPainter::Antialiasing);-
960 addGlyphsToPath(&glyph, &pt, 1, &path, 0);-
961 p.setPen(Qt::NoPen);-
962 p.setBrush(Qt::black);-
963 p.drawPath(path);-
964 p.end();-
965-
966 QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);-
967-
968 for (int y=0; y<im.height(); ++y) {
y<im.height()Description
TRUEnever evaluated
FALSEnever evaluated
0
969 uchar *dst = (uchar *) alphaMap.scanLine(y);-
970 const uint *src = reinterpret_cast<const uint *>(im.constScanLine(y));-
971 for (int x=0; x<im.width(); ++x)
x<im.width()Description
TRUEnever evaluated
FALSEnever evaluated
0
972 dst[x] = qAlpha(src[x]);
never executed: dst[x] = qAlpha(src[x]);
0
973 }
never executed: end of block
0
974-
975 return alphaMap;
never executed: return alphaMap;
0
976}-
977-
978void QFontEngine::removeGlyphFromCache(glyph_t)-
979{-
980}-
981-
982QFontEngine::Properties QFontEngine::properties() const-
983{-
984 Properties p;-
985 QByteArray psname = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8());-
986 psname += '-';-
987 psname += QByteArray::number(fontDef.style);-
988 psname += '-';-
989 psname += QByteArray::number(fontDef.weight);-
990-
991 p.postscriptName = psname;-
992 p.ascent = ascent();-
993 p.descent = descent();-
994 p.leading = leading();-
995 p.emSquare = p.ascent;-
996 p.boundingBox = QRectF(0, -p.ascent.toReal(), maxCharWidth(), (p.ascent + p.descent).toReal());-
997 p.italicAngle = 0;-
998 p.capHeight = p.ascent;-
999 p.lineWidth = lineThickness();-
1000 return p;
never executed: return p;
0
1001}-
1002-
1003void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)-
1004{-
1005 *metrics = boundingBox(glyph);-
1006 QFixedPoint p;-
1007 p.x = 0;-
1008 p.y = 0;-
1009 addGlyphsToPath(&glyph, &p, 1, path, QFlag(0));-
1010}
never executed: end of block
0
1011-
1012/*!-
1013 Returns \c true if the font table idetified by \a tag exists in the font;-
1014 returns \c false otherwise.-
1015-
1016 If \a buffer is NULL, stores the size of the buffer required for the font table data,-
1017 in bytes, in \a length. If \a buffer is not NULL and the capacity-
1018 of the buffer, passed in \a length, is sufficient to store the font table data,-
1019 also copies the font table data to \a buffer.-
1020-
1021 Note: returning \c false when the font table exists could lead to an undefined behavior.-
1022*/-
1023bool QFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const-
1024{-
1025 Q_UNUSED(tag)-
1026 Q_UNUSED(buffer)-
1027 Q_UNUSED(length)-
1028 return false;
never executed: return false;
0
1029}-
1030-
1031QByteArray QFontEngine::getSfntTable(uint tag) const-
1032{-
1033 QByteArray table;-
1034 uint len = 0;-
1035 if (!getSfntTableData(tag, 0, &len))
!getSfntTableD...(tag, 0, &len)Description
TRUEnever evaluated
FALSEnever evaluated
0
1036 return table;
never executed: return table;
0
1037 table.resize(len);-
1038 if (!getSfntTableData(tag, reinterpret_cast<uchar *>(table.data()), &len))
!getSfntTableD...data()), &len)Description
TRUEnever evaluated
FALSEnever evaluated
0
1039 return QByteArray();
never executed: return QByteArray();
0
1040 return table;
never executed: return table;
0
1041}-
1042-
1043void QFontEngine::clearGlyphCache(const void *context)-
1044{-
1045 m_glyphCaches.remove(context);-
1046}
never executed: end of block
0
1047-
1048void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cache)-
1049{-
1050 Q_ASSERT(cache);-
1051-
1052 GlyphCaches &caches = m_glyphCaches[context];-
1053 for (GlyphCaches::const_iterator it = caches.constBegin(), end = caches.constEnd(); it != end; ++it) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1054 if (cache == it->cache.data())
cache == it->cache.data()Description
TRUEnever evaluated
FALSEnever evaluated
0
1055 return;
never executed: return;
0
1056 }
never executed: end of block
0
1057-
1058 // Limit the glyph caches to 4 per context. This covers all 90 degree rotations,-
1059 // and limits memory use when there is continuous or random rotation-
1060 if (caches.size() == 4)
caches.size() == 4Description
TRUEnever evaluated
FALSEnever evaluated
0
1061 caches.removeLast();
never executed: caches.removeLast();
0
1062-
1063 GlyphCacheEntry entry;-
1064 entry.cache = cache;-
1065 caches.push_front(entry);-
1066-
1067}
never executed: end of block
0
1068-
1069QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat format, const QTransform &transform) const-
1070{-
1071 const QHash<const void*, GlyphCaches>::const_iterator caches = m_glyphCaches.constFind(context);-
1072 if (caches == m_glyphCaches.cend())
caches == m_glyphCaches.cend()Description
TRUEnever evaluated
FALSEnever evaluated
0
1073 return Q_NULLPTR;
never executed: return nullptr;
0
1074-
1075 for (GlyphCaches::const_iterator it = caches->begin(), end = caches->end(); it != end; ++it) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1076 QFontEngineGlyphCache *cache = it->cache.data();-
1077 if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform))
format == cache->glyphFormat()Description
TRUEnever evaluated
FALSEnever evaluated
qtransform_equ...rm, transform)Description
TRUEnever evaluated
FALSEnever evaluated
0
1078 return cache;
never executed: return cache;
0
1079 }
never executed: end of block
0
1080-
1081 return Q_NULLPTR;
never executed: return nullptr;
0
1082}-
1083-
1084static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)-
1085{-
1086 uint left_right = (left << 16) + right;-
1087-
1088 left = 0, right = numPairs - 1;-
1089 while (left <= right) {
left <= rightDescription
TRUEnever evaluated
FALSEnever evaluated
0
1090 int middle = left + ( ( right - left ) >> 1 );-
1091-
1092 if(pairs[middle].left_right == left_right)
pairs[middle].... == left_rightDescription
TRUEnever evaluated
FALSEnever evaluated
0
1093 return pairs[middle].adjust;
never executed: return pairs[middle].adjust;
0
1094-
1095 if (pairs[middle].left_right < left_right)
pairs[middle]....t < left_rightDescription
TRUEnever evaluated
FALSEnever evaluated
0
1096 left = middle + 1;
never executed: left = middle + 1;
0
1097 else-
1098 right = middle - 1;
never executed: right = middle - 1;
0
1099 }-
1100 return 0;
never executed: return 0;
0
1101}-
1102-
1103void QFontEngine::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
1104{-
1105 int numPairs = kerning_pairs.size();-
1106 if(!numPairs)
!numPairsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1107 return;
never executed: return;
0
1108-
1109 const KernPair *pairs = kerning_pairs.constData();-
1110-
1111 if (flags & DesignMetrics) {
flags & DesignMetricsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1112 for(int i = 0; i < glyphs->numGlyphs - 1; ++i)
i < glyphs->numGlyphs - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1113 glyphs->advances[i] += kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs);
never executed: glyphs->advances[i] += kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs);
0
1114 } else {
never executed: end of block
0
1115 for(int i = 0; i < glyphs->numGlyphs - 1; ++i)
i < glyphs->numGlyphs - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1116 glyphs->advances[i] += qRound(kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs));
never executed: glyphs->advances[i] += qRound(kerning(glyphs->glyphs[i], glyphs->glyphs[i+1] , pairs, numPairs));
0
1117 }
never executed: end of block
0
1118}-
1119-
1120void QFontEngine::loadKerningPairs(QFixed scalingFactor)-
1121{-
1122 kerning_pairs.clear();-
1123-
1124 QByteArray tab = getSfntTable(MAKE_TAG('k', 'e', 'r', 'n'));-
1125 if (tab.isEmpty())
tab.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1126 return;
never executed: return;
0
1127-
1128 const uchar *table = reinterpret_cast<const uchar *>(tab.constData());-
1129 const uchar *end = table + tab.size();-
1130-
1131 quint16 version;-
1132 if (!qSafeFromBigEndian(table, end, &version))
!qSafeFromBigE...end, &version)Description
TRUEnever evaluated
FALSEnever evaluated
0
1133 return;
never executed: return;
0
1134-
1135 if (version != 0) {
version != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1136// qDebug("wrong version");-
1137 return;
never executed: return;
0
1138 }-
1139-
1140 quint16 numTables;-
1141 if (!qSafeFromBigEndian(table + 2, end, &numTables))
!qSafeFromBigE...d, &numTables)Description
TRUEnever evaluated
FALSEnever evaluated
0
1142 return;
never executed: return;
0
1143-
1144 {-
1145 int offset = 4;-
1146 for(int i = 0; i < numTables; ++i) {
i < numTablesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1147 const uchar *header = table + offset;-
1148-
1149 quint16 version;-
1150 if (!qSafeFromBigEndian(header, end, &version))
!qSafeFromBigE...end, &version)Description
TRUEnever evaluated
FALSEnever evaluated
0
1151 goto end;
never executed: goto end;
0
1152-
1153 quint16 length;-
1154 if (!qSafeFromBigEndian(header + 2, end, &length))
!qSafeFromBigE... end, &length)Description
TRUEnever evaluated
FALSEnever evaluated
0
1155 goto end;
never executed: goto end;
0
1156-
1157 quint16 coverage;-
1158 if (!qSafeFromBigEndian(header + 4, end, &coverage))
!qSafeFromBigE...nd, &coverage)Description
TRUEnever evaluated
FALSEnever evaluated
0
1159 goto end;
never executed: goto end;
0
1160-
1161// qDebug("subtable: version=%d, coverage=%x",version, coverage);-
1162 if(version == 0 && coverage == 0x0001) {
version == 0Description
TRUEnever evaluated
FALSEnever evaluated
coverage == 0x0001Description
TRUEnever evaluated
FALSEnever evaluated
0
1163 if (offset + length > tab.size()) {
offset + length > tab.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1164// qDebug("length ouf ot bounds");-
1165 goto end;
never executed: goto end;
0
1166 }-
1167 const uchar *data = table + offset + 6;-
1168-
1169 quint16 nPairs;-
1170 if (!qSafeFromBigEndian(data, end, &nPairs))
!qSafeFromBigE... end, &nPairs)Description
TRUEnever evaluated
FALSEnever evaluated
0
1171 goto end;
never executed: goto end;
0
1172-
1173 if(nPairs * 6 + 8 > length - 6) {
nPairs * 6 + 8 > length - 6Description
TRUEnever evaluated
FALSEnever evaluated
0
1174// qDebug("corrupt table!");-
1175 // corrupt table-
1176 goto end;
never executed: goto end;
0
1177 }-
1178-
1179 int off = 8;-
1180 for(int i = 0; i < nPairs; ++i) {
i < nPairsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1181 QFontEngine::KernPair p;-
1182-
1183 quint16 tmp;-
1184 if (!qSafeFromBigEndian(data + off, end, &tmp))
!qSafeFromBigE...ff, end, &tmp)Description
TRUEnever evaluated
FALSEnever evaluated
0
1185 goto end;
never executed: goto end;
0
1186-
1187 p.left_right = uint(tmp) << 16;-
1188 if (!qSafeFromBigEndian(data + off + 2, end, &tmp))
!qSafeFromBigE... 2, end, &tmp)Description
TRUEnever evaluated
FALSEnever evaluated
0
1189 goto end;
never executed: goto end;
0
1190-
1191 p.left_right |= tmp;-
1192-
1193 if (!qSafeFromBigEndian(data + off + 4, end, &tmp))
!qSafeFromBigE... 4, end, &tmp)Description
TRUEnever evaluated
FALSEnever evaluated
0
1194 goto end;
never executed: goto end;
0
1195-
1196 p.adjust = QFixed(int(short(tmp))) / scalingFactor;-
1197 kerning_pairs.append(p);-
1198 off += 6;-
1199 }
never executed: end of block
0
1200 }
never executed: end of block
0
1201 offset += length;-
1202 }
never executed: end of block
0
1203 }-
1204end:
code before this statement never executed: end:
0
1205 std::sort(kerning_pairs.begin(), kerning_pairs.end());-
1206// for (int i = 0; i < kerning_pairs.count(); ++i)-
1207// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;-
1208}
never executed: end of block
0
1209-
1210-
1211int QFontEngine::glyphCount() const-
1212{-
1213 QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));-
1214 if (maxpTable.size() < 6)
maxpTable.size() < 6Description
TRUEnever evaluated
FALSEnever evaluated
0
1215 return 0;
never executed: return 0;
0
1216-
1217 const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);-
1218 const uchar *end = source + maxpTable.size();-
1219-
1220 quint16 count = 0;-
1221 qSafeFromBigEndian(source, end, &count);-
1222 return count;
never executed: return count;
0
1223}-
1224-
1225Qt::HANDLE QFontEngine::handle() const-
1226{-
1227 return Q_NULLPTR;
never executed: return nullptr;
0
1228}-
1229-
1230const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)-
1231{-
1232 const uchar *header = table;-
1233 const uchar *endPtr = table + tableSize;-
1234-
1235 // version check-
1236 quint16 version;-
1237 if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)
!qSafeFromBigE...Ptr, &version)Description
TRUEnever evaluated
FALSEnever evaluated
version != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1238 return 0;
never executed: return 0;
0
1239-
1240 quint16 numTables;-
1241 if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))
!qSafeFromBigE...r, &numTables)Description
TRUEnever evaluated
FALSEnever evaluated
0
1242 return 0;
never executed: return 0;
0
1243-
1244 const uchar *maps = table + 4;-
1245-
1246 enum {-
1247 Invalid,-
1248 AppleRoman,-
1249 Symbol,-
1250 Unicode11,-
1251 Unicode,-
1252 MicrosoftUnicode,-
1253 MicrosoftUnicodeExtended-
1254 };-
1255-
1256 int symbolTable = -1;-
1257 int tableToUse = -1;-
1258 int score = Invalid;-
1259 for (int n = 0; n < numTables; ++n) {
n < numTablesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1260 quint16 platformId;-
1261 if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
!qSafeFromBigE..., &platformId)Description
TRUEnever evaluated
FALSEnever evaluated
0
1262 return 0;
never executed: return 0;
0
1263-
1264 quint16 platformSpecificId;-
1265 if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))
!qSafeFromBigE...ormSpecificId)Description
TRUEnever evaluated
FALSEnever evaluated
0
1266 return 0;
never executed: return 0;
0
1267-
1268 switch (platformId) {-
1269 case 0: // Unicode
never executed: case 0:
0
1270 if (score < Unicode &&
score < UnicodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1271 (platformSpecificId == 0 ||
platformSpecificId == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1272 platformSpecificId == 2 ||
platformSpecificId == 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1273 platformSpecificId == 3)) {
platformSpecificId == 3Description
TRUEnever evaluated
FALSEnever evaluated
0
1274 tableToUse = n;-
1275 score = Unicode;-
1276 } else if (score < Unicode11 && platformSpecificId == 1) {
never executed: end of block
score < Unicode11Description
TRUEnever evaluated
FALSEnever evaluated
platformSpecificId == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1277 tableToUse = n;-
1278 score = Unicode11;-
1279 }
never executed: end of block
0
1280 break;
never executed: break;
0
1281 case 1: // Apple
never executed: case 1:
0
1282 if (score < AppleRoman && platformSpecificId == 0) { // Apple Roman
score < AppleRomanDescription
TRUEnever evaluated
FALSEnever evaluated
platformSpecificId == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1283 tableToUse = n;-
1284 score = AppleRoman;-
1285 }
never executed: end of block
0
1286 break;
never executed: break;
0
1287 case 3: // Microsoft
never executed: case 3:
0
1288 switch (platformSpecificId) {-
1289 case 0:
never executed: case 0:
0
1290 symbolTable = n;-
1291 if (score < Symbol) {
score < SymbolDescription
TRUEnever evaluated
FALSEnever evaluated
0
1292 tableToUse = n;-
1293 score = Symbol;-
1294 }
never executed: end of block
0
1295 break;
never executed: break;
0
1296 case 1:
never executed: case 1:
0
1297 if (score < MicrosoftUnicode) {
score < MicrosoftUnicodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1298 tableToUse = n;-
1299 score = MicrosoftUnicode;-
1300 }
never executed: end of block
0
1301 break;
never executed: break;
0
1302 case 0xa:
never executed: case 0xa:
0
1303 if (score < MicrosoftUnicodeExtended) {
score < Micros...nicodeExtendedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1304 tableToUse = n;-
1305 score = MicrosoftUnicodeExtended;-
1306 }
never executed: end of block
0
1307 break;
never executed: break;
0
1308 default:
never executed: default:
0
1309 break;
never executed: break;
0
1310 }-
1311 default:
code before this statement never executed: default:
never executed: default:
0
1312 break;
never executed: break;
0
1313 }-
1314 }-
1315 if(tableToUse < 0)
tableToUse < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1316 return 0;
never executed: return 0;
0
1317-
1318resolveTable:
code before this statement never executed: resolveTable:
0
1319 *isSymbolFont = (symbolTable > -1);-
1320-
1321 quint32 unicode_table;-
1322 if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
!qSafeFromBigE...unicode_table)Description
TRUEnever evaluated
FALSEnever evaluated
0
1323 return 0;
never executed: return 0;
0
1324-
1325 if (!unicode_table)
!unicode_tableDescription
TRUEnever evaluated
FALSEnever evaluated
0
1326 return 0;
never executed: return 0;
0
1327-
1328 // get the header of the unicode table-
1329 header = table + unicode_table;-
1330-
1331 quint16 format;-
1332 if (!qSafeFromBigEndian(header, endPtr, &format))
!qSafeFromBigE...dPtr, &format)Description
TRUEnever evaluated
FALSEnever evaluated
0
1333 return 0;
never executed: return 0;
0
1334-
1335 quint32 length;-
1336 if (format < 8) {
format < 8Description
TRUEnever evaluated
FALSEnever evaluated
0
1337 quint16 tmp;-
1338 if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))
!qSafeFromBigE... endPtr, &tmp)Description
TRUEnever evaluated
FALSEnever evaluated
0
1339 return 0;
never executed: return 0;
0
1340 length = tmp;-
1341 } else {
never executed: end of block
0
1342 if (!qSafeFromBigEndian(header + 4, endPtr, &length))
!qSafeFromBigE...dPtr, &length)Description
TRUEnever evaluated
FALSEnever evaluated
0
1343 return 0;
never executed: return 0;
0
1344 }
never executed: end of block
0
1345-
1346 if (table + unicode_table + length > endPtr)
table + unicod...ength > endPtrDescription
TRUEnever evaluated
FALSEnever evaluated
0
1347 return 0;
never executed: return 0;
0
1348 *cmapSize = length;-
1349-
1350 // To support symbol fonts that contain a unicode table for the symbol area-
1351 // we check the cmap tables and fall back to symbol font unless that would-
1352 // involve losing information from the unicode table-
1353 if (symbolTable > -1 && ((score == Unicode) || (score == Unicode11))) {
symbolTable > -1Description
TRUEnever evaluated
FALSEnever evaluated
(score == Unicode)Description
TRUEnever evaluated
FALSEnever evaluated
(score == Unicode11)Description
TRUEnever evaluated
FALSEnever evaluated
0
1354 const uchar *selectedTable = table + unicode_table;-
1355-
1356 // Check that none of the latin1 range are in the unicode table-
1357 bool unicodeTableHasLatin1 = false;-
1358 for (int uc=0x00; uc<0x100; ++uc) {
uc<0x100Description
TRUEnever evaluated
FALSEnever evaluated
0
1359 if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
getTrueTypeGly...ngth, uc) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1360 unicodeTableHasLatin1 = true;-
1361 break;
never executed: break;
0
1362 }-
1363 }
never executed: end of block
0
1364-
1365 // Check that at least one symbol char is in the unicode table-
1366 bool unicodeTableHasSymbols = false;-
1367 if (!unicodeTableHasLatin1) {
!unicodeTableHasLatin1Description
TRUEnever evaluated
FALSEnever evaluated
0
1368 for (int uc=0xf000; uc<0xf100; ++uc) {
uc<0xf100Description
TRUEnever evaluated
FALSEnever evaluated
0
1369 if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
getTrueTypeGly...ngth, uc) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1370 unicodeTableHasSymbols = true;-
1371 break;
never executed: break;
0
1372 }-
1373 }
never executed: end of block
0
1374 }
never executed: end of block
0
1375-
1376 // Fall back to symbol table-
1377 if (!unicodeTableHasLatin1 && unicodeTableHasSymbols) {
!unicodeTableHasLatin1Description
TRUEnever evaluated
FALSEnever evaluated
unicodeTableHasSymbolsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1378 tableToUse = symbolTable;-
1379 score = Symbol;-
1380 goto resolveTable;
never executed: goto resolveTable;
0
1381 }-
1382 }
never executed: end of block
0
1383-
1384 return table + unicode_table;
never executed: return table + unicode_table;
0
1385}-
1386-
1387quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)-
1388{-
1389 const uchar *end = cmap + cmapSize;-
1390 quint16 format;-
1391 if (!qSafeFromBigEndian(cmap, end, &format))
!qSafeFromBigE... end, &format)Description
TRUEnever evaluated
FALSEnever evaluated
0
1392 return 0;
never executed: return 0;
0
1393-
1394 if (format == 0) {
format == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1395 const uchar *ptr = cmap + 6 + unicode;-
1396 if (unicode < 256 && ptr < end)
unicode < 256Description
TRUEnever evaluated
FALSEnever evaluated
ptr < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1397 return quint32(*ptr);
never executed: return quint32(*ptr);
0
1398 } else if (format == 4) {
never executed: end of block
format == 4Description
TRUEnever evaluated
FALSEnever evaluated
0
1399 /* some fonts come with invalid cmap tables, where the last segment-
1400 specified end = start = rangeoffset = 0xffff, delta = 0x0001-
1401 Since 0xffff is never a valid Unicode char anyway, we just get rid of the issue-
1402 by returning 0 for 0xffff-
1403 */-
1404 if(unicode >= 0xffff)
unicode >= 0xffffDescription
TRUEnever evaluated
FALSEnever evaluated
0
1405 return 0;
never executed: return 0;
0
1406-
1407 quint16 segCountX2;-
1408 if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
!qSafeFromBigE..., &segCountX2)Description
TRUEnever evaluated
FALSEnever evaluated
0
1409 return 0;
never executed: return 0;
0
1410-
1411 const unsigned char *ends = cmap + 14;-
1412-
1413 int i = 0;-
1414 for (; i < segCountX2/2; ++i) {
i < segCountX2/2Description
TRUEnever evaluated
FALSEnever evaluated
0
1415 quint16 codePoint;-
1416 if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
!qSafeFromBigE...d, &codePoint)Description
TRUEnever evaluated
FALSEnever evaluated
0
1417 return 0;
never executed: return 0;
0
1418 if (codePoint >= unicode)
codePoint >= unicodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1419 break;
never executed: break;
0
1420 }
never executed: end of block
0
1421-
1422 const unsigned char *idx = ends + segCountX2 + 2 + 2*i;-
1423-
1424 quint16 startIndex;-
1425 if (!qSafeFromBigEndian(idx, end, &startIndex))
!qSafeFromBigE..., &startIndex)Description
TRUEnever evaluated
FALSEnever evaluated
0
1426 return 0;
never executed: return 0;
0
1427 if (startIndex > unicode)
startIndex > unicodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1428 return 0;
never executed: return 0;
0
1429-
1430 idx += segCountX2;-
1431-
1432 quint16 tmp;-
1433 if (!qSafeFromBigEndian(idx, end, &tmp))
!qSafeFromBigE...dx, end, &tmp)Description
TRUEnever evaluated
FALSEnever evaluated
0
1434 return 0;
never executed: return 0;
0
1435 qint16 idDelta = qint16(tmp);-
1436-
1437 idx += segCountX2;-
1438-
1439 quint16 idRangeoffset_t;-
1440 if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
!qSafeFromBigE...Rangeoffset_t)Description
TRUEnever evaluated
FALSEnever evaluated
0
1441 return 0;
never executed: return 0;
0
1442-
1443 quint16 glyphIndex;-
1444 if (idRangeoffset_t) {
idRangeoffset_tDescription
TRUEnever evaluated
FALSEnever evaluated
0
1445 quint16 id;-
1446 if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
!qSafeFromBigE...idx, end, &id)Description
TRUEnever evaluated
FALSEnever evaluated
0
1447 return 0;
never executed: return 0;
0
1448-
1449 if (id)
idDescription
TRUEnever evaluated
FALSEnever evaluated
0
1450 glyphIndex = (idDelta + id) % 0x10000;
never executed: glyphIndex = (idDelta + id) % 0x10000;
0
1451 else-
1452 glyphIndex = 0;
never executed: glyphIndex = 0;
0
1453 } else {-
1454 glyphIndex = (idDelta + unicode) % 0x10000;-
1455 }
never executed: end of block
0
1456 return glyphIndex;
never executed: return glyphIndex;
0
1457 } else if (format == 6) {
format == 6Description
TRUEnever evaluated
FALSEnever evaluated
0
1458 quint16 tableSize;-
1459 if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
!qSafeFromBigE...d, &tableSize)Description
TRUEnever evaluated
FALSEnever evaluated
0
1460 return 0;
never executed: return 0;
0
1461-
1462 quint16 firstCode6;-
1463 if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
!qSafeFromBigE..., &firstCode6)Description
TRUEnever evaluated
FALSEnever evaluated
0
1464 return 0;
never executed: return 0;
0
1465 if (unicode < firstCode6)
unicode < firstCode6Description
TRUEnever evaluated
FALSEnever evaluated
0
1466 return 0;
never executed: return 0;
0
1467-
1468 quint16 entryCount6;-
1469 if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
!qSafeFromBigE... &entryCount6)Description
TRUEnever evaluated
FALSEnever evaluated
0
1470 return 0;
never executed: return 0;
0
1471 if (entryCount6 * 2 + 10 > tableSize)
entryCount6 * ...10 > tableSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1472 return 0;
never executed: return 0;
0
1473-
1474 quint16 sentinel6 = firstCode6 + entryCount6;-
1475 if (unicode >= sentinel6)
unicode >= sentinel6Description
TRUEnever evaluated
FALSEnever evaluated
0
1476 return 0;
never executed: return 0;
0
1477-
1478 quint16 entryIndex6 = unicode - firstCode6;-
1479-
1480 quint16 index = 0;-
1481 qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);-
1482 return index;
never executed: return index;
0
1483 } else if (format == 12) {
format == 12Description
TRUEnever evaluated
FALSEnever evaluated
0
1484 quint32 nGroups;-
1485 if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
!qSafeFromBigE...end, &nGroups)Description
TRUEnever evaluated
FALSEnever evaluated
0
1486 return 0;
never executed: return 0;
0
1487-
1488 cmap += 16; // move to start of groups-
1489-
1490 int left = 0, right = nGroups - 1;-
1491 while (left <= right) {
left <= rightDescription
TRUEnever evaluated
FALSEnever evaluated
0
1492 int middle = left + ( ( right - left ) >> 1 );-
1493-
1494 quint32 startCharCode;-
1495 if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
!qSafeFromBigE...startCharCode)Description
TRUEnever evaluated
FALSEnever evaluated
0
1496 return 0;
never executed: return 0;
0
1497-
1498 if(unicode < startCharCode)
unicode < startCharCodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1499 right = middle - 1;
never executed: right = middle - 1;
0
1500 else {-
1501 quint32 endCharCode;-
1502 if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
!qSafeFromBigE... &endCharCode)Description
TRUEnever evaluated
FALSEnever evaluated
0
1503 return 0;
never executed: return 0;
0
1504-
1505 if (unicode <= endCharCode) {
unicode <= endCharCodeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1506 quint32 index;-
1507 if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
!qSafeFromBigE..., end, &index)Description
TRUEnever evaluated
FALSEnever evaluated
0
1508 return 0;
never executed: return 0;
0
1509-
1510 return index + unicode - startCharCode;
never executed: return index + unicode - startCharCode;
0
1511 }-
1512 left = middle + 1;-
1513 }
never executed: end of block
0
1514 }-
1515 } else {
never executed: end of block
0
1516 qDebug("cmap table of format %d not implemented", format);-
1517 }
never executed: end of block
0
1518-
1519 return 0;
never executed: return 0;
0
1520}-
1521-
1522QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &family)-
1523{-
1524 QByteArray f = family;-
1525 f.replace(' ', "");-
1526 f.replace('(', "");-
1527 f.replace(')', "");-
1528 f.replace('<', "");-
1529 f.replace('>', "");-
1530 f.replace('[', "");-
1531 f.replace(']', "");-
1532 f.replace('{', "");-
1533 f.replace('}', "");-
1534 f.replace('/', "");-
1535 f.replace('%', "");-
1536 return f;
never executed: return f;
0
1537}-
1538-
1539// Allow font engines (e.g. Windows) that can not reliably create-
1540// outline paths for distance-field rendering to switch the scene-
1541// graph over to native text rendering.-
1542bool QFontEngine::hasUnreliableGlyphOutline() const-
1543{-
1544 // Color glyphs (Emoji) are generally not suited for outlining-
1545 return glyphFormat == QFontEngine::Format_ARGB;
never executed: return glyphFormat == QFontEngine::Format_ARGB;
0
1546}-
1547-
1548QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)-
1549{-
1550 if (glyphs.numGlyphs >= 1) {
glyphs.numGlyphs >= 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1551 glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1];-
1552 glyph_metrics_t gi = boundingBox(glyph);-
1553 if (gi.isValid())
gi.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1554 return round ? qRound(gi.rightBearing()) : gi.rightBearing();
never executed: return round ? qRound(gi.rightBearing()) : gi.rightBearing();
0
1555 }
never executed: end of block
0
1556 return 0;
never executed: return 0;
0
1557}-
1558-
1559-
1560QFontEngine::GlyphCacheEntry::GlyphCacheEntry()-
1561{-
1562}-
1563-
1564QFontEngine::GlyphCacheEntry::GlyphCacheEntry(const GlyphCacheEntry &o)-
1565 : cache(o.cache)-
1566{-
1567}
never executed: end of block
0
1568-
1569QFontEngine::GlyphCacheEntry::~GlyphCacheEntry()-
1570{-
1571}-
1572-
1573QFontEngine::GlyphCacheEntry &QFontEngine::GlyphCacheEntry::operator=(const GlyphCacheEntry &o)-
1574{-
1575 cache = o.cache;-
1576 return *this;
never executed: return *this;
0
1577}-
1578-
1579// -------------------------------------------------------------------
1580// The box font engine-
1581// -------------------------------------------------------------------
1582-
1583QFontEngineBox::QFontEngineBox(int size)-
1584 : QFontEngine(Box),-
1585 _size(size)-
1586{-
1587 cache_cost = sizeof(QFontEngineBox);-
1588}
never executed: end of block
0
1589-
1590QFontEngineBox::QFontEngineBox(Type type, int size)-
1591 : QFontEngine(type),-
1592 _size(size)-
1593{-
1594 cache_cost = sizeof(QFontEngineBox);-
1595}
never executed: end of block
0
1596-
1597QFontEngineBox::~QFontEngineBox()-
1598{-
1599}-
1600-
1601glyph_t QFontEngineBox::glyphIndex(uint ucs4) const-
1602{-
1603 Q_UNUSED(ucs4)-
1604 return 0;
never executed: return 0;
0
1605}-
1606-
1607bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const-
1608{-
1609 Q_ASSERT(glyphs->numGlyphs >= *nglyphs);-
1610 if (*nglyphs < len) {
*nglyphs < lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1611 *nglyphs = len;-
1612 return false;
never executed: return false;
0
1613 }-
1614-
1615 int ucs4Length = 0;-
1616 QStringIterator it(str, str + len);-
1617 while (it.hasNext()) {
it.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
1618 it.advance();-
1619 glyphs->glyphs[ucs4Length++] = 0;-
1620 }
never executed: end of block
0
1621-
1622 *nglyphs = ucs4Length;-
1623 glyphs->numGlyphs = ucs4Length;-
1624-
1625 if (!(flags & GlyphIndicesOnly))
!(flags & GlyphIndicesOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
1626 recalcAdvances(glyphs, flags);
never executed: recalcAdvances(glyphs, flags);
0
1627-
1628 return true;
never executed: return true;
0
1629}-
1630-
1631void QFontEngineBox::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const-
1632{-
1633 for (int i = 0; i < glyphs->numGlyphs; i++)
i < glyphs->numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1634 glyphs->advances[i] = _size;
never executed: glyphs->advances[i] = _size;
0
1635}
never executed: end of block
0
1636-
1637void QFontEngineBox::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)-
1638{-
1639 if (!glyphs.numGlyphs)
!glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1640 return;
never executed: return;
0
1641-
1642 QVarLengthArray<QFixedPoint> positions;-
1643 QVarLengthArray<glyph_t> positioned_glyphs;-
1644 QTransform matrix = QTransform::fromTranslate(x, y - _size);-
1645 getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);-
1646-
1647 QSize s(_size - 3, _size - 3);-
1648 for (int k = 0; k < positions.size(); k++)
k < positions.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1649 path->addRect(QRectF(positions[k].toPointF(), s));
never executed: path->addRect(QRectF(positions[k].toPointF(), s));
0
1650}
never executed: end of block
0
1651-
1652glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs)-
1653{-
1654 glyph_metrics_t overall;-
1655 overall.width = _size*glyphs.numGlyphs;-
1656 overall.height = _size;-
1657 overall.xoff = overall.width;-
1658 return overall;
never executed: return overall;
0
1659}-
1660-
1661void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti)-
1662{-
1663 if (!ti.glyphs.numGlyphs)
!ti.glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1664 return;
never executed: return;
0
1665-
1666 // any fixes here should probably also be done in QPaintEnginePrivate::drawBoxTextItem-
1667 QSize s(_size - 3, _size - 3);-
1668-
1669 QVarLengthArray<QFixedPoint> positions;-
1670 QVarLengthArray<glyph_t> glyphs;-
1671 QTransform matrix = QTransform::fromTranslate(x, y - _size);-
1672 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);-
1673 if (glyphs.size() == 0)
glyphs.size() == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1674 return;
never executed: return;
0
1675-
1676-
1677 QPainter *painter = p->painter();-
1678 painter->save();-
1679 painter->setBrush(Qt::NoBrush);-
1680 QPen pen = painter->pen();-
1681 pen.setWidthF(lineThickness().toReal());-
1682 painter->setPen(pen);-
1683 for (int k = 0; k < positions.size(); k++)
k < positions.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1684 painter->drawRect(QRectF(positions[k].toPointF(), s));
never executed: painter->drawRect(QRectF(positions[k].toPointF(), s));
0
1685 painter->restore();-
1686}
never executed: end of block
0
1687-
1688glyph_metrics_t QFontEngineBox::boundingBox(glyph_t)-
1689{-
1690 return glyph_metrics_t(0, -_size, _size, _size, _size, 0);
never executed: return glyph_metrics_t(0, -_size, _size, _size, _size, 0);
0
1691}-
1692-
1693QFontEngine *QFontEngineBox::cloneWithSize(qreal pixelSize) const-
1694{-
1695 QFontEngineBox *fe = new QFontEngineBox(pixelSize);-
1696 return fe;
never executed: return fe;
0
1697}-
1698-
1699QFixed QFontEngineBox::ascent() const-
1700{-
1701 return _size;
never executed: return _size;
0
1702}-
1703-
1704QFixed QFontEngineBox::descent() const-
1705{-
1706 return 0;
never executed: return 0;
0
1707}-
1708-
1709QFixed QFontEngineBox::leading() const-
1710{-
1711 QFixed l = _size * QFixed::fromReal(qreal(0.15));-
1712 return l.ceil();
never executed: return l.ceil();
0
1713}-
1714-
1715qreal QFontEngineBox::maxCharWidth() const-
1716{-
1717 return _size;
never executed: return _size;
0
1718}-
1719-
1720bool QFontEngineBox::canRender(const QChar *, int) const-
1721{-
1722 return true;
never executed: return true;
0
1723}-
1724-
1725QImage QFontEngineBox::alphaMapForGlyph(glyph_t)-
1726{-
1727 QImage image(_size, _size, QImage::Format_Alpha8);-
1728 image.fill(0);-
1729-
1730 // FIXME: use qpainter-
1731 for (int i=2; i <= _size-3; ++i) {
i <= _size-3Description
TRUEnever evaluated
FALSEnever evaluated
0
1732 image.setPixel(i, 2, 255);-
1733 image.setPixel(i, _size-3, 255);-
1734 image.setPixel(2, i, 255);-
1735 image.setPixel(_size-3, i, 255);-
1736 }
never executed: end of block
0
1737 return image;
never executed: return image;
0
1738}-
1739-
1740// -------------------------------------------------------------------
1741// Multi engine-
1742// -------------------------------------------------------------------
1743-
1744static inline uchar highByte(glyph_t glyph)-
1745{
never executed: return glyph >> 24;
return glyph >> 24; }
never executed: return glyph >> 24;
0
1746-
1747// strip high byte from glyph-
1748static inline glyph_t stripped(glyph_t glyph)-
1749{
never executed: return glyph & 0x00ffffff;
return glyph & 0x00ffffff; }
never executed: return glyph & 0x00ffffff;
0
1750-
1751QFontEngineMulti::QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies)-
1752 : QFontEngine(Multi),-
1753 m_fallbackFamilies(fallbackFamilies),-
1754 m_script(script),-
1755 m_fallbackFamiliesQueried(!m_fallbackFamilies.isEmpty())-
1756{-
1757 Q_ASSERT(engine && engine->type() != QFontEngine::Multi);-
1758-
1759 if (m_fallbackFamilies.isEmpty()) {
m_fallbackFamilies.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1760 // defer obtaining the fallback families until loadEngine(1)-
1761 m_fallbackFamilies << QString();-
1762 }
never executed: end of block
0
1763-
1764 m_engines.resize(m_fallbackFamilies.size() + 1);-
1765-
1766 engine->ref.ref();-
1767 m_engines[0] = engine;-
1768-
1769 fontDef = engine->fontDef;-
1770 cache_cost = engine->cache_cost;-
1771}
never executed: end of block
0
1772-
1773QFontEngineMulti::~QFontEngineMulti()-
1774{-
1775 for (int i = 0; i < m_engines.size(); ++i) {
i < m_engines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1776 QFontEngine *fontEngine = m_engines.at(i);-
1777 if (fontEngine && !fontEngine->ref.deref())
fontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
!fontEngine->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
1778 delete fontEngine;
never executed: delete fontEngine;
0
1779 }
never executed: end of block
0
1780}
never executed: end of block
0
1781-
1782QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script);-
1783-
1784void QFontEngineMulti::ensureFallbackFamiliesQueried()-
1785{-
1786 QFont::StyleHint styleHint = QFont::StyleHint(fontDef.styleHint);-
1787 if (styleHint == QFont::AnyStyle && fontDef.fixedPitch)
styleHint == QFont::AnyStyleDescription
TRUEnever evaluated
FALSEnever evaluated
fontDef.fixedPitchDescription
TRUEnever evaluated
FALSEnever evaluated
0
1788 styleHint = QFont::TypeWriter;
never executed: styleHint = QFont::TypeWriter;
0
1789-
1790 setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.family, QFont::Style(fontDef.style), styleHint, QChar::Script(m_script)));-
1791}
never executed: end of block
0
1792-
1793void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamilies)-
1794{-
1795 Q_ASSERT(!m_fallbackFamiliesQueried);-
1796-
1797 m_fallbackFamilies = fallbackFamilies;-
1798 if (m_fallbackFamilies.isEmpty()) {
m_fallbackFamilies.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1799 // turns out we lied about having any fallback at all-
1800 Q_ASSERT(m_engines.size() == 2); // see c-tor for details-
1801 QFontEngine *engine = m_engines.at(0);-
1802 engine->ref.ref();-
1803 m_engines[1] = engine;-
1804 m_fallbackFamilies << fontDef.family;-
1805 } else {
never executed: end of block
0
1806 m_engines.resize(m_fallbackFamilies.size() + 1);-
1807 }
never executed: end of block
0
1808-
1809 m_fallbackFamiliesQueried = true;-
1810}
never executed: end of block
0
1811-
1812void QFontEngineMulti::ensureEngineAt(int at)-
1813{-
1814 if (!m_fallbackFamiliesQueried)
!m_fallbackFamiliesQueriedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1815 ensureFallbackFamiliesQueried();
never executed: ensureFallbackFamiliesQueried();
0
1816 Q_ASSERT(at < m_engines.size());-
1817 if (!m_engines.at(at)) {
!m_engines.at(at)Description
TRUEnever evaluated
FALSEnever evaluated
0
1818 QFontEngine *engine = loadEngine(at);-
1819 if (!engine)
!engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1820 engine = new QFontEngineBox(fontDef.pixelSize);
never executed: engine = new QFontEngineBox(fontDef.pixelSize);
0
1821 Q_ASSERT(engine && engine->type() != QFontEngine::Multi);-
1822 engine->ref.ref();-
1823 m_engines[at] = engine;-
1824 }
never executed: end of block
0
1825}
never executed: end of block
0
1826-
1827QFontEngine *QFontEngineMulti::loadEngine(int at)-
1828{-
1829 QFontDef request(fontDef);-
1830 request.styleStrategy |= QFont::NoFontMerging;-
1831 request.family = fallbackFamilyAt(at - 1);-
1832-
1833 if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {
QFontEngine *e...est, m_script)Description
TRUEnever evaluated
FALSEnever evaluated
0
1834 engine->fontDef.weight = request.weight;-
1835 if (request.style > QFont::StyleNormal)
request.style ...t::StyleNormalDescription
TRUEnever evaluated
FALSEnever evaluated
0
1836 engine->fontDef.style = request.style;
never executed: engine->fontDef.style = request.style;
0
1837 return engine;
never executed: return engine;
0
1838 }-
1839-
1840 return 0;
never executed: return 0;
0
1841}-
1842-
1843glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const-
1844{-
1845 glyph_t glyph = engine(0)->glyphIndex(ucs4);-
1846 if (glyph == 0 && ucs4 != QChar::LineSeparator) {
glyph == 0Description
TRUEnever evaluated
FALSEnever evaluated
ucs4 != QChar::LineSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1847 if (!m_fallbackFamiliesQueried)
!m_fallbackFamiliesQueriedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1848 const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
never executed: const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
0
1849 for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
x < nDescription
TRUEnever evaluated
FALSEnever evaluated
0
1850 QFontEngine *engine = m_engines.at(x);-
1851 if (!engine) {
!engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1852 if (!shouldLoadFontEngineForCharacter(x, ucs4))
!shouldLoadFon...acter(x, ucs4)Description
TRUEnever evaluated
FALSEnever evaluated
0
1853 continue;
never executed: continue;
0
1854 const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);-
1855 engine = m_engines.at(x);-
1856 }
never executed: end of block
0
1857 Q_ASSERT(engine != 0);-
1858 if (engine->type() == Box)
engine->type() == BoxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1859 continue;
never executed: continue;
0
1860-
1861 glyph = engine->glyphIndex(ucs4);-
1862 if (glyph != 0) {
glyph != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1863 // set the high byte to indicate which engine the glyph came from-
1864 glyph |= (x << 24);-
1865 break;
never executed: break;
0
1866 }-
1867 }
never executed: end of block
0
1868 }
never executed: end of block
0
1869-
1870 return glyph;
never executed: return glyph;
0
1871}-
1872-
1873bool QFontEngineMulti::stringToCMap(const QChar *str, int len,-
1874 QGlyphLayout *glyphs, int *nglyphs,-
1875 QFontEngine::ShaperFlags flags) const-
1876{-
1877 if (!engine(0)->stringToCMap(str, len, glyphs, nglyphs, flags))
!engine(0)->st...glyphs, flags)Description
TRUEnever evaluated
FALSEnever evaluated
0
1878 return false;
never executed: return false;
0
1879-
1880 int glyph_pos = 0;-
1881 QStringIterator it(str, str + len);-
1882 while (it.hasNext()) {
it.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
1883 const uint ucs4 = it.peekNext();-
1884 if (glyphs->glyphs[glyph_pos] == 0 && ucs4 != QChar::LineSeparator) {
glyphs->glyphs[glyph_pos] == 0Description
TRUEnever evaluated
FALSEnever evaluated
ucs4 != QChar::LineSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1885 if (!m_fallbackFamiliesQueried)
!m_fallbackFamiliesQueriedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1886 const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
never executed: const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
0
1887 for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
x < nDescription
TRUEnever evaluated
FALSEnever evaluated
0
1888 QFontEngine *engine = m_engines.at(x);-
1889 if (!engine) {
!engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1890 if (!shouldLoadFontEngineForCharacter(x, ucs4))
!shouldLoadFon...acter(x, ucs4)Description
TRUEnever evaluated
FALSEnever evaluated
0
1891 continue;
never executed: continue;
0
1892 const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);-
1893 engine = m_engines.at(x);-
1894 if (!engine)
!engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1895 continue;
never executed: continue;
0
1896 }
never executed: end of block
0
1897 Q_ASSERT(engine != 0);-
1898 if (engine->type() == Box)
engine->type() == BoxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1899 continue;
never executed: continue;
0
1900-
1901 glyph_t glyph = engine->glyphIndex(ucs4);-
1902 if (glyph != 0) {
glyph != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1903 glyphs->glyphs[glyph_pos] = glyph;-
1904 if (!(flags & GlyphIndicesOnly)) {
!(flags & GlyphIndicesOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
1905 QGlyphLayout g = glyphs->mid(glyph_pos, 1);-
1906 engine->recalcAdvances(&g, flags);-
1907 }
never executed: end of block
0
1908 // set the high byte to indicate which engine the glyph came from-
1909 glyphs->glyphs[glyph_pos] |= (x << 24);-
1910 break;
never executed: break;
0
1911 }-
1912 }
never executed: end of block
0
1913 }
never executed: end of block
0
1914-
1915 it.advance();-
1916 ++glyph_pos;-
1917 }
never executed: end of block
0
1918-
1919 *nglyphs = glyph_pos;-
1920 glyphs->numGlyphs = glyph_pos;-
1921-
1922 return true;
never executed: return true;
0
1923}-
1924-
1925bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const-
1926{-
1927 Q_UNUSED(at);-
1928 Q_UNUSED(ucs4);-
1929 return true;
never executed: return true;
0
1930}-
1931-
1932glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)-
1933{-
1934 if (glyphs.numGlyphs <= 0)
glyphs.numGlyphs <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1935 return glyph_metrics_t();
never executed: return glyph_metrics_t();
0
1936-
1937 glyph_metrics_t overall;-
1938-
1939 int which = highByte(glyphs.glyphs[0]);-
1940 int start = 0;-
1941 int end, i;-
1942 for (end = 0; end < glyphs.numGlyphs; ++end) {
end < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1943 const int e = highByte(glyphs.glyphs[end]);-
1944 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
1945 continue;
never executed: continue;
0
1946-
1947 // set the high byte to zero-
1948 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1949 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
never executed: glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
0
1950-
1951 // merge the bounding box for this run-
1952 const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));-
1953-
1954 overall.x = qMin(overall.x, gm.x);-
1955 overall.y = qMin(overall.y, gm.y);-
1956 overall.width = overall.xoff + gm.width;-
1957 overall.height = qMax(overall.height + overall.y, gm.height + gm.y) --
1958 qMin(overall.y, gm.y);-
1959 overall.xoff += gm.xoff;-
1960 overall.yoff += gm.yoff;-
1961-
1962 // reset the high byte for all glyphs-
1963 const int hi = which << 24;-
1964 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1965 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
never executed: glyphs.glyphs[i] = hi | glyphs.glyphs[i];
0
1966-
1967 // change engine-
1968 start = end;-
1969 which = e;-
1970 }
never executed: end of block
0
1971-
1972 // set the high byte to zero-
1973 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1974 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
never executed: glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
0
1975-
1976 // merge the bounding box for this run-
1977 const glyph_metrics_t gm = engine(which)->boundingBox(glyphs.mid(start, end - start));-
1978-
1979 overall.x = qMin(overall.x, gm.x);-
1980 overall.y = qMin(overall.y, gm.y);-
1981 overall.width = overall.xoff + gm.width;-
1982 overall.height = qMax(overall.height + overall.y, gm.height + gm.y) --
1983 qMin(overall.y, gm.y);-
1984 overall.xoff += gm.xoff;-
1985 overall.yoff += gm.yoff;-
1986-
1987 // reset the high byte for all glyphs-
1988 const int hi = which << 24;-
1989 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1990 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
never executed: glyphs.glyphs[i] = hi | glyphs.glyphs[i];
0
1991-
1992 return overall;
never executed: return overall;
0
1993}-
1994-
1995void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)-
1996{-
1997 int which = highByte(glyph);-
1998 ensureEngineAt(which);-
1999 engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);-
2000}
never executed: end of block
0
2001-
2002void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,-
2003 QPainterPath *path, QTextItem::RenderFlags flags)-
2004{-
2005 if (glyphs.numGlyphs <= 0)
glyphs.numGlyphs <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2006 return;
never executed: return;
0
2007-
2008 int which = highByte(glyphs.glyphs[0]);-
2009 int start = 0;-
2010 int end, i;-
2011 if (flags & QTextItem::RightToLeft) {
flags & QTextItem::RightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
2012 for (int gl = 0; gl < glyphs.numGlyphs; gl++)
gl < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2013 x += glyphs.advances[gl].toReal();
never executed: x += glyphs.advances[gl].toReal();
0
2014 }
never executed: end of block
0
2015 for (end = 0; end < glyphs.numGlyphs; ++end) {
end < glyphs.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2016 const int e = highByte(glyphs.glyphs[end]);-
2017 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
2018 continue;
never executed: continue;
0
2019-
2020 if (flags & QTextItem::RightToLeft) {
flags & QTextItem::RightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
2021 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2022 x -= glyphs.advances[i].toReal();
never executed: x -= glyphs.advances[i].toReal();
0
2023 }
never executed: end of block
0
2024-
2025 // set the high byte to zero-
2026 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2027 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
never executed: glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
0
2028 engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);-
2029 // reset the high byte for all glyphs and update x and y-
2030 const int hi = which << 24;-
2031 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2032 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
never executed: glyphs.glyphs[i] = hi | glyphs.glyphs[i];
0
2033-
2034 if (!(flags & QTextItem::RightToLeft)) {
!(flags & QTex...::RightToLeft)Description
TRUEnever evaluated
FALSEnever evaluated
0
2035 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2036 x += glyphs.advances[i].toReal();
never executed: x += glyphs.advances[i].toReal();
0
2037 }
never executed: end of block
0
2038-
2039 // change engine-
2040 start = end;-
2041 which = e;-
2042 }
never executed: end of block
0
2043-
2044 if (flags & QTextItem::RightToLeft) {
flags & QTextItem::RightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
2045 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2046 x -= glyphs.advances[i].toReal();
never executed: x -= glyphs.advances[i].toReal();
0
2047 }
never executed: end of block
0
2048-
2049 // set the high byte to zero-
2050 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2051 glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
never executed: glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
0
2052-
2053 engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);-
2054-
2055 // reset the high byte for all glyphs-
2056 const int hi = which << 24;-
2057 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2058 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
never executed: glyphs.glyphs[i] = hi | glyphs.glyphs[i];
0
2059}
never executed: end of block
0
2060-
2061void QFontEngineMulti::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
2062{-
2063 if (glyphs->numGlyphs <= 0)
glyphs->numGlyphs <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2064 return;
never executed: return;
0
2065-
2066 int which = highByte(glyphs->glyphs[0]);-
2067 int start = 0;-
2068 int end, i;-
2069 for (end = 0; end < glyphs->numGlyphs; ++end) {
end < glyphs->numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2070 const int e = highByte(glyphs->glyphs[end]);-
2071 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
2072 continue;
never executed: continue;
0
2073-
2074 // set the high byte to zero-
2075 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2076 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
never executed: glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
0
2077-
2078 QGlyphLayout offs = glyphs->mid(start, end - start);-
2079 engine(which)->recalcAdvances(&offs, flags);-
2080-
2081 // reset the high byte for all glyphs and update x and y-
2082 const int hi = which << 24;-
2083 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2084 glyphs->glyphs[i] = hi | glyphs->glyphs[i];
never executed: glyphs->glyphs[i] = hi | glyphs->glyphs[i];
0
2085-
2086 // change engine-
2087 start = end;-
2088 which = e;-
2089 }
never executed: end of block
0
2090-
2091 // set the high byte to zero-
2092 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2093 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
never executed: glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
0
2094-
2095 QGlyphLayout offs = glyphs->mid(start, end - start);-
2096 engine(which)->recalcAdvances(&offs, flags);-
2097-
2098 // reset the high byte for all glyphs-
2099 const int hi = which << 24;-
2100 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2101 glyphs->glyphs[i] = hi | glyphs->glyphs[i];
never executed: glyphs->glyphs[i] = hi | glyphs->glyphs[i];
0
2102}
never executed: end of block
0
2103-
2104void QFontEngineMulti::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const-
2105{-
2106 if (glyphs->numGlyphs <= 0)
glyphs->numGlyphs <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2107 return;
never executed: return;
0
2108-
2109 int which = highByte(glyphs->glyphs[0]);-
2110 int start = 0;-
2111 int end, i;-
2112 for (end = 0; end < glyphs->numGlyphs; ++end) {
end < glyphs->numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2113 const int e = highByte(glyphs->glyphs[end]);-
2114 if (e == which)
e == whichDescription
TRUEnever evaluated
FALSEnever evaluated
0
2115 continue;
never executed: continue;
0
2116-
2117 // set the high byte to zero-
2118 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2119 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
never executed: glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
0
2120-
2121 QGlyphLayout offs = glyphs->mid(start, end - start);-
2122 engine(which)->doKerning(&offs, flags);-
2123-
2124 // reset the high byte for all glyphs and update x and y-
2125 const int hi = which << 24;-
2126 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2127 glyphs->glyphs[i] = hi | glyphs->glyphs[i];
never executed: glyphs->glyphs[i] = hi | glyphs->glyphs[i];
0
2128-
2129 // change engine-
2130 start = end;-
2131 which = e;-
2132 }
never executed: end of block
0
2133-
2134 // set the high byte to zero-
2135 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2136 glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
never executed: glyphs->glyphs[i] = stripped(glyphs->glyphs[i]);
0
2137-
2138 QGlyphLayout offs = glyphs->mid(start, end - start);-
2139 engine(which)->doKerning(&offs, flags);-
2140-
2141 // reset the high byte for all glyphs-
2142 const int hi = which << 24;-
2143 for (i = start; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2144 glyphs->glyphs[i] = hi | glyphs->glyphs[i];
never executed: glyphs->glyphs[i] = hi | glyphs->glyphs[i];
0
2145}
never executed: end of block
0
2146-
2147glyph_metrics_t QFontEngineMulti::boundingBox(glyph_t glyph)-
2148{-
2149 const int which = highByte(glyph);-
2150 return engine(which)->boundingBox(stripped(glyph));
never executed: return engine(which)->boundingBox(stripped(glyph));
0
2151}-
2152-
2153QFixed QFontEngineMulti::ascent() const-
2154{
never executed: return engine(0)->ascent();
return engine(0)->ascent(); }
never executed: return engine(0)->ascent();
0
2155-
2156QFixed QFontEngineMulti::descent() const-
2157{
never executed: return engine(0)->descent();
return engine(0)->descent(); }
never executed: return engine(0)->descent();
0
2158-
2159QFixed QFontEngineMulti::leading() const-
2160{-
2161 return engine(0)->leading();
never executed: return engine(0)->leading();
0
2162}-
2163-
2164QFixed QFontEngineMulti::xHeight() const-
2165{-
2166 return engine(0)->xHeight();
never executed: return engine(0)->xHeight();
0
2167}-
2168-
2169QFixed QFontEngineMulti::averageCharWidth() const-
2170{-
2171 return engine(0)->averageCharWidth();
never executed: return engine(0)->averageCharWidth();
0
2172}-
2173-
2174QFixed QFontEngineMulti::lineThickness() const-
2175{-
2176 return engine(0)->lineThickness();
never executed: return engine(0)->lineThickness();
0
2177}-
2178-
2179QFixed QFontEngineMulti::underlinePosition() const-
2180{-
2181 return engine(0)->underlinePosition();
never executed: return engine(0)->underlinePosition();
0
2182}-
2183-
2184qreal QFontEngineMulti::maxCharWidth() const-
2185{-
2186 return engine(0)->maxCharWidth();
never executed: return engine(0)->maxCharWidth();
0
2187}-
2188-
2189qreal QFontEngineMulti::minLeftBearing() const-
2190{-
2191 return engine(0)->minLeftBearing();
never executed: return engine(0)->minLeftBearing();
0
2192}-
2193-
2194qreal QFontEngineMulti::minRightBearing() const-
2195{-
2196 return engine(0)->minRightBearing();
never executed: return engine(0)->minRightBearing();
0
2197}-
2198-
2199bool QFontEngineMulti::canRender(const QChar *string, int len) const-
2200{-
2201 if (engine(0)->canRender(string, len))
engine(0)->can...r(string, len)Description
TRUEnever evaluated
FALSEnever evaluated
0
2202 return true;
never executed: return true;
0
2203-
2204 int nglyphs = len;-
2205-
2206 QVarLengthArray<glyph_t> glyphs(nglyphs);-
2207-
2208 QGlyphLayout g;-
2209 g.numGlyphs = nglyphs;-
2210 g.glyphs = glyphs.data();-
2211 if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
!stringToCMap(...phIndicesOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
2212 Q_UNREACHABLE();
never executed: end of block
0
2213-
2214 for (int i = 0; i < nglyphs; i++) {
i < nglyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2215 if (glyphs[i] == 0)
glyphs[i] == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2216 return false;
never executed: return false;
0
2217 }
never executed: end of block
0
2218-
2219 return true;
never executed: return true;
0
2220}-
2221-
2222/* Implement alphaMapForGlyph() which is called by Lighthouse/Windows code.-
2223 * Ideally, that code should be fixed to correctly handle QFontEngineMulti. */-
2224-
2225QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph)-
2226{-
2227 const int which = highByte(glyph);-
2228 return engine(which)->alphaMapForGlyph(stripped(glyph));
never executed: return engine(which)->alphaMapForGlyph(stripped(glyph));
0
2229}-
2230-
2231QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)-
2232{-
2233 const int which = highByte(glyph);-
2234 return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition);
never executed: return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition);
0
2235}-
2236-
2237QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, const QTransform &t)-
2238{-
2239 const int which = highByte(glyph);-
2240 return engine(which)->alphaMapForGlyph(stripped(glyph), t);
never executed: return engine(which)->alphaMapForGlyph(stripped(glyph), t);
0
2241}-
2242-
2243QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
2244{-
2245 const int which = highByte(glyph);-
2246 return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition, t);
never executed: return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition, t);
0
2247}-
2248-
2249QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)-
2250{-
2251 const int which = highByte(glyph);-
2252 return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);
never executed: return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);
0
2253}-
2254-
2255/*-
2256 This is used indirectly by Qt WebKit when using QTextLayout::setRawFont-
2257-
2258 The purpose of this is to provide the necessary font fallbacks when drawing complex-
2259 text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them-
2260 the same raw font over and over again, we want to cache the corresponding multi font engine-
2261 as it may contain fallback font engines already.-
2262*/-
2263QFontEngine *QFontEngineMulti::createMultiFontEngine(QFontEngine *fe, int script)-
2264{-
2265 QFontEngine *engine = 0;-
2266 QFontCache::Key key(fe->fontDef, script, /*multi = */true);-
2267 QFontCache *fc = QFontCache::instance();-
2268 // We can't rely on the fontDef (and hence the cache Key)-
2269 // alone to distinguish webfonts, since these should not be-
2270 // accidentally shared, even if the resulting fontcache key-
2271 // is strictly identical. See:-
2272 // http://www.w3.org/TR/css3-fonts/#font-face-rule-
2273 const bool faceIsLocal = !fe->faceId().filename.isEmpty();-
2274 QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),-
2275 end = fc->engineCache.end();-
2276 while (it != end && it.key() == key) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
it.key() == keyDescription
TRUEnever evaluated
FALSEnever evaluated
0
2277 Q_ASSERT(it.value().data->type() == QFontEngine::Multi);-
2278 QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);-
2279 if (fe == cachedEngine->engine(0) || (faceIsLocal && fe->faceId().filename == cachedEngine->engine(0)->faceId().filename)) {
fe == cachedEngine->engine(0)Description
TRUEnever evaluated
FALSEnever evaluated
faceIsLocalDescription
TRUEnever evaluated
FALSEnever evaluated
fe->faceId().f...eId().filenameDescription
TRUEnever evaluated
FALSEnever evaluated
0
2280 engine = cachedEngine;-
2281 fc->updateHitCountAndTimeStamp(it.value());-
2282 break;
never executed: break;
0
2283 }-
2284 ++it;-
2285 }
never executed: end of block
0
2286 if (!engine) {
!engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2287 engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));-
2288 fc->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);-
2289 }
never executed: end of block
0
2290 Q_ASSERT(engine);-
2291 return engine;
never executed: return engine;
0
2292}-
2293-
2294QTestFontEngine::QTestFontEngine(int size)-
2295 : QFontEngineBox(TestFontEngine, size)-
2296{}
never executed: end of block
0
2297-
2298QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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