Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qwindowsfontengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include <QtCore/qt_windows.h>
8#if QT_CONFIG(directwrite)
10#endif
11#include <QtGui/qpa/qplatformintegration.h>
12#include <QtGui/private/qtextengine_p.h> // glyph_metrics_t
13#include <QtGui/private/qguiapplication_p.h>
14#include <QtGui/QPaintDevice>
15#include <QtGui/QBitmap>
16#include <QtGui/QPainter>
17#include <QtGui/private/qpainter_p.h>
18#include <QtGui/QPaintEngine>
19#include <QtGui/private/qpaintengine_raster_p.h>
20#include <QtGui/private/qtgui-config_p.h>
21
22#include <QtCore/QtEndian>
23#include <QtCore/QFile>
24#include <QtCore/qmath.h>
25#include <QtCore/QTextStream>
26#include <QtCore/QThreadStorage>
27#include <QtCore/private/qsystemlibrary_p.h>
28#include <QtCore/private/qstringiterator_p.h>
29
30#include <QtCore/QDebug>
31
32#include <limits.h>
33
34#if QT_CONFIG(directwrite)
35# include <dwrite.h>
36# include <comdef.h>
37#endif
38
40
43
44//### mingw needed define
45#ifndef TT_PRIM_CSPLINE
46#define TT_PRIM_CSPLINE 3
47#endif
48
49// GetFontData expects the tags in little endian ;(
50#define MAKE_LITTLE_ENDIAN_TAG(ch1, ch2, ch3, ch4) (\
51 (((quint32)(ch4)) << 24) | \
52 (((quint32)(ch3)) << 16) | \
53 (((quint32)(ch2)) << 8) | \
54 ((quint32)(ch1)) \
55 )
56
57// common DC for all fonts
58
59// general font engine
60
62{
63 if (lineWidth > 0)
64 return lineWidth;
65
67}
68
69static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
70{
71 const auto size = GetOutlineTextMetrics(hdc, 0, nullptr);
72 auto otm = reinterpret_cast<OUTLINETEXTMETRIC *>(malloc(size));
73 GetOutlineTextMetrics(hdc, size, otm);
74 return otm;
75}
76
77bool QWindowsFontEngine::hasCFFTable() const
78{
79 HDC hdc = m_fontEngineData->hdc;
80 SelectObject(hdc, hfont);
81 return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('C', 'F', 'F', ' '), 0, 0, 0) != GDI_ERROR;
82}
83
84bool QWindowsFontEngine::hasCMapTable() const
85{
86 HDC hdc = m_fontEngineData->hdc;
87 SelectObject(hdc, hfont);
88 return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR;
89}
90
91static inline QString stringFromOutLineTextMetric(const OUTLINETEXTMETRIC *otm, PSTR offset)
92{
93 const uchar *p = reinterpret_cast<const uchar *>(otm) + quintptr(offset);
94 return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(p));
95}
96
98{
99 ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable();
100
101 cffTable = hasCFFTable();
102
103 HDC hdc = m_fontEngineData->hdc;
104 SelectObject(hdc, hfont);
105 bool symb = false;
106 if (ttf) {
107 cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
108 cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
109 cmapTable.size(), &symb, &cmapSize);
110 }
111 if (!cmap) {
112 ttf = false;
113 symb = false;
114 }
115 symbol = symb;
116 designToDevice = 1;
117 _faceId.index = 0;
118 if (cmap) {
119 OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
120 unitsPerEm = int(otm->otmEMSquare);
121 const QFixed unitsPerEmF(unitsPerEm);
122 designToDevice = unitsPerEmF / QFixed::fromReal(fontDef.pixelSize);
123 x_height = int(otm->otmsXHeight);
124 loadKerningPairs(designToDevice);
125 _faceId.filename = QFile::encodeName(stringFromOutLineTextMetric(otm, otm->otmpFullName));
126 lineWidth = otm->otmsUnderscoreSize;
127 fsType = otm->otmfsType;
128 free(otm);
129
130 } else {
131 unitsPerEm = tm.tmHeight;
132 }
133}
134
135int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs) const
136{
137 int glyph_pos = 0;
138 {
139 if (symbol) {
140 QStringIterator it(str, str + numChars);
141 while (it.hasNext()) {
142 const uint uc = it.next();
143 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
144 if (!glyphs->glyphs[glyph_pos] && uc < 0x100)
145 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
146 ++glyph_pos;
147 }
148 } else if (ttf) {
149 QStringIterator it(str, str + numChars);
150 while (it.hasNext()) {
151 const uint uc = it.next();
152 glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
153 ++glyph_pos;
154 }
155 } else {
156 QStringIterator it(str, str + numChars);
157 while (it.hasNext()) {
158 const uint uc = it.next();
159 if (uc >= tm.tmFirstChar && uc <= tm.tmLastChar)
160 glyphs->glyphs[glyph_pos] = uc;
161 else
162 glyphs->glyphs[glyph_pos] = 0;
163 ++glyph_pos;
164 }
165 }
166 }
167 glyphs->numGlyphs = glyph_pos;
168 return glyph_pos;
169}
170
180 LOGFONT lf,
181 const QSharedPointer<QWindowsFontEngineData> &fontEngineData)
182 : QFontEngine(Win),
183 m_fontEngineData(fontEngineData),
184 _name(name),
185 m_logfont(lf),
186 ttf(0),
187 hasOutline(0)
188{
189 qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight;
190 hfont = CreateFontIndirect(&m_logfont);
191 if (!hfont) {
192 qErrnoWarning("%s: CreateFontIndirect failed for family '%s'", __FUNCTION__, qPrintable(name));
194 }
195
196 HDC hdc = m_fontEngineData->hdc;
197 SelectObject(hdc, hfont);
198 const BOOL res = GetTextMetrics(hdc, &tm);
199 if (!res) {
200 qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__);
201 ZeroMemory(&tm, sizeof(TEXTMETRIC));
202 }
203
204 fontDef.pixelSize = -lf.lfHeight;
205 fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
206
207 cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000;
208 getCMap();
209
210 hasUnreliableOutline = (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) == 0;
211}
212
214{
215 if (designAdvances)
216 free(designAdvances);
217
218 if (widthCache)
219 free(widthCache);
220
221 // make sure we aren't by accident still selected
222 SelectObject(m_fontEngineData->hdc, QWindowsFontDatabase::systemFont());
223
224 if (!DeleteObject(hfont))
225 qErrnoWarning("%s: QFontEngineWin: failed to delete font...", __FUNCTION__);
226 qCDebug(lcQpaFonts) << __FUNCTION__ << _name;
227
228 if (!uniqueFamilyName.isEmpty()) {
230 QPlatformFontDatabase *pfdb = pi->fontDatabase();
231 static_cast<QWindowsFontDatabase *>(pfdb)->derefUniqueFont(uniqueFamilyName);
232 }
233 }
234}
235
237{
238 glyph_t glyph = 0;
239
240 if (symbol) {
241 glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
242 if (glyph == 0 && ucs4 < 0x100)
243 glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
244 } else if (ttf) {
245 glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
246 } else if (ucs4 >= tm.tmFirstChar && ucs4 <= tm.tmLastChar) {
247 glyph = ucs4;
248 }
249
250 return glyph;
251}
252
254{
255 LOGFONT f = m_logfont;
256 f.lfHeight = -unitsPerEm;
257 f.lfWidth = 0;
258 HFONT designFont = CreateFontIndirect(&f);
259 return SelectObject(m_fontEngineData->hdc, designFont);
260}
261
262bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
263{
264 Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
265 if (*nglyphs < len) {
266 *nglyphs = len;
267 return false;
268 }
269
270 glyphs->numGlyphs = *nglyphs;
271 *nglyphs = getGlyphIndexes(str, len, glyphs);
272
273 if (!(flags & GlyphIndicesOnly))
274 recalcAdvances(glyphs, flags);
275
276 return true;
277}
278
279inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
280{
281 GetCharWidthI(hdc, glyph, 1, 0, &width);
282}
283
284void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const
285{
286 HGDIOBJ oldFont = 0;
287 HDC hdc = m_fontEngineData->hdc;
288 if (ttf && (flags & DesignMetrics)) {
289 for(int i = 0; i < glyphs->numGlyphs; i++) {
290 unsigned int glyph = glyphs->glyphs[i];
291 if (int(glyph) >= designAdvancesSize) {
292 const int newSize = int(glyph + 256) >> 8 << 8;
293 designAdvances = reinterpret_cast<QFixed *>(realloc(designAdvances, size_t(newSize) * sizeof(QFixed)));
294 Q_CHECK_PTR(designAdvances);
295 for(int i = designAdvancesSize; i < newSize; ++i)
296 designAdvances[i] = -1000000;
297 designAdvancesSize = newSize;
298 }
299 if (designAdvances[glyph] < -999999) {
300 if (!oldFont)
301 oldFont = selectDesignFont();
302
303 int width = 0;
304 calculateTTFGlyphWidth(hdc, glyph, width);
305 designAdvances[glyph] = QFixed(width) / designToDevice;
306 }
307 glyphs->advances[i] = designAdvances[glyph];
308 }
309 if (oldFont)
310 DeleteObject(SelectObject(hdc, oldFont));
311 } else {
312 for(int i = 0; i < glyphs->numGlyphs; i++) {
313 unsigned int glyph = glyphs->glyphs[i];
314
315 if (glyph >= widthCacheSize) {
316 const uint newSize = (glyph + 256) >> 8 << 8;
317 widthCache = reinterpret_cast<unsigned char *>(realloc(widthCache, newSize * sizeof(QFixed)));
318 Q_CHECK_PTR(widthCache);
319 memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize);
320 widthCacheSize = newSize;
321 }
322 glyphs->advances[i] = widthCache[glyph];
323 // font-width cache failed
324 if (glyphs->advances[i].value() == 0) {
325 int width = 0;
326 if (!oldFont)
327 oldFont = SelectObject(hdc, hfont);
328
329 if (!ttf) {
330 QChar ch[2] = { ushort(glyph), u'\0' };
331 int chrLen = 1;
332 if (QChar::requiresSurrogates(glyph)) {
333 ch[0] = QChar::highSurrogate(glyph);
334 ch[1] = QChar::lowSurrogate(glyph);
335 ++chrLen;
336 }
337 SIZE size = {0, 0};
338 GetTextExtentPoint32(hdc, reinterpret_cast<const wchar_t *>(ch), chrLen, &size);
339 width = size.cx;
340 } else {
341 calculateTTFGlyphWidth(hdc, glyph, width);
342 }
343 glyphs->advances[i] = width;
344 // if glyph's within cache range, store it for later
345 if (width > 0 && width < 0x100)
346 widthCache[glyph] = uchar(width);
347 }
348 }
349
350 if (oldFont)
351 SelectObject(hdc, oldFont);
352 }
353}
354
356{
357 Q_ASSERT(metrics != 0);
358
359 HDC hdc = m_fontEngineData->hdc;
360
361 GLYPHMETRICS gm;
362 DWORD res = 0;
363 MAT2 mat;
364 mat.eM11.value = mat.eM22.value = 1;
365 mat.eM11.fract = mat.eM22.fract = 0;
366 mat.eM21.value = mat.eM12.value = 0;
367 mat.eM21.fract = mat.eM12.fract = 0;
368
369 if (t.type() > QTransform::TxTranslate) {
370 // We need to set the transform using the HDC's world
371 // matrix rather than using the MAT2 above, because the
372 // results provided when transforming via MAT2 does not
373 // match the glyphs that are drawn using a WorldTransform
374 XFORM xform;
375 xform.eM11 = FLOAT(t.m11());
376 xform.eM12 = FLOAT(t.m12());
377 xform.eM21 = FLOAT(t.m21());
378 xform.eM22 = FLOAT(t.m22());
379 xform.eDx = 0;
380 xform.eDy = 0;
381 SetGraphicsMode(hdc, GM_ADVANCED);
382 SetWorldTransform(hdc, &xform);
383 }
384
385 uint format = GGO_METRICS;
386 if (ttf)
387 format |= GGO_GLYPH_INDEX;
388 res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat);
389
390 if (t.type() > QTransform::TxTranslate) {
391 XFORM xform;
392 xform.eM11 = xform.eM22 = 1;
393 xform.eM12 = xform.eM21 = xform.eDx = xform.eDy = 0;
394 SetWorldTransform(hdc, &xform);
395 SetGraphicsMode(hdc, GM_COMPATIBLE);
396 }
397
398 if (res != GDI_ERROR) {
399 *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y,
400 int(gm.gmBlackBoxX), int(gm.gmBlackBoxY),
401 gm.gmCellIncX, gm.gmCellIncY);
402 return true;
403 } else {
404 return false;
405 }
406}
407
409{
410 HDC hdc = m_fontEngineData->hdc;
411 SelectObject(hdc, hfont);
412
413 glyph_metrics_t glyphMetrics;
414 bool success = getOutlineMetrics(glyph, t, &glyphMetrics);
415
416 if (!ttf && !success) {
417 // Bitmap fonts
418 wchar_t ch = wchar_t(glyph);
419 ABCFLOAT abc;
420 GetCharABCWidthsFloat(hdc, ch, ch, &abc);
421 int width = qRound(abc.abcfB);
422
423 return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t);
424 }
425
426 return glyphMetrics;
427}
428
429namespace {
430# pragma pack(1)
431
432 struct OS2Table
433 {
434 quint16 version;
435 qint16 avgCharWidth;
436 quint16 weightClass;
437 quint16 widthClass;
439 qint16 subscriptXSize;
440 qint16 subscriptYSize;
441 qint16 subscriptXOffset;
442 qint16 subscriptYOffset;
443 qint16 superscriptXSize;
444 qint16 superscriptYSize;
445 qint16 superscriptXOffset;
446 qint16 superscriptYOffset;
447 qint16 strikeOutSize;
448 qint16 strikeOutPosition;
449 qint16 familyClass;
450 quint8 panose[10];
451 quint32 unicodeRanges[4];
452 quint8 vendorID[4];
454 quint16 firstCharIndex;
455 quint16 lastCharIndex;
456 qint16 typoAscender;
457 qint16 typoDescender;
458 qint16 typoLineGap;
459 quint16 winAscent;
460 quint16 winDescent;
461 quint32 codepageRanges[2];
463 qint16 capHeight;
464 quint16 defaultChar;
465 quint16 breakChar;
466 quint16 maxContext;
467 };
468
469# pragma pack()
470}
471
473{
474 const QByteArray tableData = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
475 if (size_t(tableData.size()) >= sizeof(OS2Table)) {
476 const OS2Table *table = reinterpret_cast<const OS2Table *>(tableData.constData());
477 if (qFromBigEndian<quint16>(table->version) >= 2) {
478 qint16 capHeight = qFromBigEndian<qint16>(table->capHeight);
479 if (capHeight > 0)
480 return QFixed(capHeight) / designToDevice;
481 }
482 }
483 return calculatedCapHeight();
484}
485
487{
488 if (x_height >= 0)
489 return x_height;
490 return QFontEngine::xHeight();
491}
492
494{
495 return tm.tmAveCharWidth;
496}
497
499{
500 return tm.tmMaxCharWidth;
501}
502
503enum { max_font_count = 256 };
504static const ushort char_table[] = {
505 40,
506 67,
507 70,
508 75,
509 86,
510 88,
511 89,
512 91,
513 102,
514 114,
515 124,
516 127,
517 205,
518 645,
519 884,
520 922,
521 1070,
522 12386,
523 0
524};
525
526static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
527
528#ifndef Q_CC_MINGW
529void QWindowsFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
530{
531 HDC hdc = m_fontEngineData->hdc;
532 SelectObject(hdc, hfont);
533
534 if (ttf) {
535 ABC abcWidths;
536 GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths);
537 if (leftBearing)
538 *leftBearing = abcWidths.abcA;
539 if (rightBearing)
540 *rightBearing = abcWidths.abcC;
541 } else {
542 QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing);
543 }
544}
545#endif // Q_CC_MINGW
546
548{
549 m_ascent = tm.tmAscent;
550 m_descent = tm.tmDescent;
551 m_leading = tm.tmExternalLeading;
552
554}
555
557{
558 return hasUnreliableOutline || QFontEngine::hasUnreliableGlyphOutline();
559}
560
562{
563 if (lbearing == SHRT_MIN)
564 minRightBearing(); // calculates both
565
566 return lbearing;
567}
568
570{
571 if (rbearing == SHRT_MIN) {
572 int ml = 0;
573 int mr = 0;
574 HDC hdc = m_fontEngineData->hdc;
575 SelectObject(hdc, hfont);
576 if (ttf) {
577 ABC *abc = nullptr;
578 int n = tm.tmLastChar - tm.tmFirstChar;
579 if (n <= max_font_count) {
580 abc = new ABC[n+1];
581 GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
582 } else {
583 abc = new ABC[char_table_entries+1];
584 for(int i = 0; i < char_table_entries; i++)
585 GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i);
587 }
588 ml = abc[0].abcA;
589 mr = abc[0].abcC;
590 for (int i = 1; i < n; i++) {
591 if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) {
592 ml = qMin(ml,abc[i].abcA);
593 mr = qMin(mr,abc[i].abcC);
594 }
595 }
596 delete [] abc;
597 } else {
598 ABCFLOAT *abc = 0;
599 int n = tm.tmLastChar - tm.tmFirstChar+1;
600 if (n <= max_font_count) {
601 abc = new ABCFLOAT[n];
602 GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc);
603 } else {
604 abc = new ABCFLOAT[char_table_entries];
605 for(int i = 0; i < char_table_entries; i++)
606 GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i);
608 }
609 float fml = abc[0].abcfA;
610 float fmr = abc[0].abcfC;
611 for (int i=1; i<n; i++) {
612 if (abc[i].abcfA + abc[i].abcfB + abc[i].abcfC != 0) {
613 fml = qMin(fml,abc[i].abcfA);
614 fmr = qMin(fmr,abc[i].abcfC);
615 }
616 }
617 ml = qFloor(fml);
618 mr = qFloor(fmr);
619 delete [] abc;
620 }
621 lbearing = ml;
622 rbearing = mr;
623 }
624
625 return rbearing;
626}
627
628static inline double qt_fixed_to_double(const FIXED &p) {
629 return ((p.value << 16) + p.fract) / 65536.0;
630}
631
632static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale, qreal stretch) {
633 return QPointF(qt_fixed_to_double(pt.x) * scale * stretch, -qt_fixed_to_double(pt.y) * scale);
634}
635
636#ifndef GGO_UNHINTED
637#define GGO_UNHINTED 0x0100
638#endif
639
640static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
641 QPainterPath *path, bool ttf, glyph_metrics_t *metric = nullptr,
642 qreal scale = 1.0, qreal stretch = 1.0)
643{
644 MAT2 mat;
645 mat.eM11.value = mat.eM22.value = 1;
646 mat.eM11.fract = mat.eM22.fract = 0;
647 mat.eM21.value = mat.eM12.value = 0;
648 mat.eM21.fract = mat.eM12.fract = 0;
649
650 GLYPHMETRICS gMetric;
651 memset(&gMetric, 0, sizeof(GLYPHMETRICS));
652
653 if (metric) {
654 // If metrics requested, retrieve first using GGO_METRICS, because the returned
655 // values are incorrect for OpenType PS fonts if obtained at the same time as the
656 // glyph paths themselves (ie. with GGO_NATIVE as the format).
657 uint format = GGO_METRICS;
658 if (ttf)
659 format |= GGO_GLYPH_INDEX;
660 if (GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat) == GDI_ERROR)
661 return false;
662 // #### obey scale
663 *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y,
664 int(gMetric.gmBlackBoxX), int(gMetric.gmBlackBoxY),
665 gMetric.gmCellIncX, gMetric.gmCellIncY);
666 }
667
668 uint glyphFormat = GGO_NATIVE;
669
670 if (ttf)
671 glyphFormat |= GGO_GLYPH_INDEX;
672
673 const DWORD bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
674 if (bufferSize == GDI_ERROR)
675 return false;
676
677 char *dataBuffer = new char[bufferSize];
678 DWORD ret = GDI_ERROR;
679 ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat);
680 if (ret == GDI_ERROR) {
681 delete [] dataBuffer;
682 return false;
683 }
684
685 DWORD offset = 0;
686 DWORD headerOffset = 0;
687
688 QPointF oset = position.toPointF();
689 while (headerOffset < bufferSize) {
690 const TTPOLYGONHEADER *ttph = reinterpret_cast<const TTPOLYGONHEADER *>(dataBuffer + headerOffset);
691
692 QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale, stretch));
693 path->moveTo(lastPoint + oset);
694 offset += sizeof(TTPOLYGONHEADER);
695 while (offset < headerOffset + ttph->cb) {
696 const TTPOLYCURVE *curve = reinterpret_cast<const TTPOLYCURVE *>(dataBuffer + offset);
697 switch (curve->wType) {
698 case TT_PRIM_LINE: {
699 for (int i=0; i<curve->cpfx; ++i) {
700 QPointF p = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset;
701 path->lineTo(p);
702 }
703 break;
704 }
705 case TT_PRIM_QSPLINE: {
706 const QPainterPath::Element &elm = path->elementAt(path->elementCount()-1);
707 QPointF prev(elm.x, elm.y);
708 QPointF endPoint;
709 for (int i=0; i<curve->cpfx - 1; ++i) {
710 QPointF p1 = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset;
711 QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale, stretch) + oset;
712 if (i < curve->cpfx - 2) {
713 endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2);
714 } else {
715 endPoint = p2;
716 }
717
718 path->quadTo(p1, endPoint);
719 prev = endPoint;
720 }
721
722 break;
723 }
724 case TT_PRIM_CSPLINE: {
725 for (int i=0; i<curve->cpfx; ) {
726 QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
727 QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
728 QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
729 path->cubicTo(p2, p3, p4);
730 }
731 break;
732 }
733 default:
734 qWarning("QFontEngineWin::addOutlineToPath, unhandled switch case");
735 }
736 offset += sizeof(TTPOLYCURVE) + (curve->cpfx-1) * sizeof(POINTFX);
737 }
738 path->closeSubpath();
739 headerOffset += ttph->cb;
740 }
741 delete [] dataBuffer;
742
743 return true;
744}
745
747 QPainterPath *path, QTextItem::RenderFlags)
748{
749 LOGFONT lf = m_logfont;
750 // The sign must be negative here to make sure we match against character height instead of
751 // hinted cell height. This ensures that we get linear matching, and we need this for
752 // paths since we later on apply a scaling transform to the glyph outline to get the
753 // font at the correct pixel size.
754 lf.lfHeight = -unitsPerEm;
755 lf.lfWidth = 0;
756 HFONT hf = CreateFontIndirect(&lf);
757 HDC hdc = m_fontEngineData->hdc;
758 HGDIOBJ oldfont = SelectObject(hdc, hf);
759
760 qreal scale = qreal(fontDef.pixelSize) / unitsPerEm;
761 qreal stretch = fontDef.stretch ? qreal(fontDef.stretch) / 100 : 1.0;
762 for(int i = 0; i < nglyphs; ++i) {
763 if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0,
764 scale, stretch)) {
765 // Some windows fonts, like "Modern", are vector stroke
766 // fonts, which are reported as TMPF_VECTOR but do not
767 // support GetGlyphOutline, and thus we set this bit so
768 // that addOutLineToPath can check it and return safely...
769 hasOutline = false;
770 break;
771 }
772 }
773 DeleteObject(SelectObject(hdc, oldfont));
774}
775
777 QPainterPath *path, QTextItem::RenderFlags flags)
778{
779 if (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) {
780 hasOutline = true;
782 if (hasOutline) {
783 // has_outline is set to false if addGlyphToPath gets
784 // false from GetGlyphOutline, meaning its not an outline
785 // font.
786 return;
787 }
788 }
790}
791
793{
794 return _faceId;
795}
796
798#include <qdebug.h>
800
802{
803 if (synthesized_flags == -1) {
804 synthesized_flags = 0;
805 if (ttf) {
806 const DWORD HEAD = MAKE_LITTLE_ENDIAN_TAG('h', 'e', 'a', 'd');
807 HDC hdc = m_fontEngineData->hdc;
808 SelectObject(hdc, hfont);
809 uchar data[4];
810 GetFontData(hdc, HEAD, 44, &data, 4);
811 USHORT macStyle = qt_getUShort(data);
812 if (tm.tmItalic && !(macStyle & 2))
813 synthesized_flags = SynthesizedItalic;
814 if (fontDef.stretch != 100 && ttf)
815 synthesized_flags |= SynthesizedStretch;
816 if (tm.tmWeight >= 500 && tm.tmWeight < 750 && !(macStyle & 1))
817 synthesized_flags |= SynthesizedBold;
818 //qDebug() << "font is" << _name <<
819 // "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags;
820 }
821 }
822 return synthesized_flags;
823}
824
826{
827 return unitsPerEm;
828}
829
831{
832 LOGFONT lf = m_logfont;
833 lf.lfHeight = unitsPerEm;
834 HFONT hf = CreateFontIndirect(&lf);
835 HDC hdc = m_fontEngineData->hdc;
836 HGDIOBJ oldfont = SelectObject(hdc, hf);
837 OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
839 p.emSquare = unitsPerEm;
840 p.italicAngle = otm->otmItalicAngle;
841 const QByteArray name = stringFromOutLineTextMetric(otm, otm->otmpFamilyName).toLatin1()
842 + stringFromOutLineTextMetric(otm, otm->otmpStyleName).toLatin1();
844 p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top,
845 otm->otmrcFontBox.right - otm->otmrcFontBox.left,
846 otm->otmrcFontBox.top - otm->otmrcFontBox.bottom);
847 p.ascent = otm->otmAscent;
848 p.descent = -otm->otmDescent;
849 p.leading = int(otm->otmLineGap);
850 p.capHeight = 0;
851 p.lineWidth = otm->otmsUnderscoreSize;
852 free(otm);
853 DeleteObject(SelectObject(hdc, oldfont));
854 return p;
855}
856
858{
859 LOGFONT lf = m_logfont;
860 lf.lfHeight = -unitsPerEm;
861 int flags = synthesized();
863 lf.lfItalic = false;
864 lf.lfWidth = 0;
865 HFONT hf = CreateFontIndirect(&lf);
866 HDC hdc = m_fontEngineData->hdc;
867 HGDIOBJ oldfont = SelectObject(hdc, hf);
869 p.x = 0;
870 p.y = 0;
871 addGlyphToPath(glyph, p, hdc, path, ttf, metrics);
872 DeleteObject(SelectObject(hdc, oldfont));
873}
874
876{
877 if (!ttf && !cffTable)
878 return false;
879 HDC hdc = m_fontEngineData->hdc;
880 SelectObject(hdc, hfont);
881 DWORD t = qbswap<quint32>(tag);
882 *length = GetFontData(hdc, t, 0, buffer, *length);
883 Q_ASSERT(*length == GDI_ERROR || int(*length) > 0);
884 return *length != GDI_ERROR;
885}
886
887#if !defined(CLEARTYPE_QUALITY)
888# define CLEARTYPE_QUALITY 5
889#endif
890
891QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, int margin,
892 const QTransform &t,
893 QImage::Format mask_format)
894{
895 Q_UNUSED(mask_format);
896 glyph_metrics_t gm = boundingBox(glyph);
897
898// printf(" -> for glyph %4x\n", glyph);
899
900 int gx = gm.x.toInt();
901 int gy = gm.y.toInt();
902 int iw = gm.width.toInt();
903 int ih = gm.height.toInt();
904
905 if (iw <= 0 || ih <= 0)
906 return 0;
907
908 bool has_transformation = t.type() > QTransform::TxTranslate;
909
910 unsigned int options = ttf ? ETO_GLYPH_INDEX : 0;
911 XFORM xform;
912
913 if (has_transformation) {
914 xform.eM11 = FLOAT(t.m11());
915 xform.eM12 = FLOAT(t.m12());
916 xform.eM21 = FLOAT(t.m21());
917 xform.eM22 = FLOAT(t.m22());
918 xform.eDx = margin;
919 xform.eDy = margin;
920
921 const HDC hdc = m_fontEngineData->hdc;
922
923 SetGraphicsMode(hdc, GM_ADVANCED);
924 SetWorldTransform(hdc, &xform);
925 HGDIOBJ old_font = SelectObject(hdc, font);
926
927 const UINT ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0);
928 GLYPHMETRICS tgm;
929 MAT2 mat;
930 memset(&mat, 0, sizeof(mat));
931 mat.eM11.value = mat.eM22.value = 1;
932
933 const DWORD result = GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat);
934
935 XFORM identity = {1, 0, 0, 1, 0, 0};
936 SetWorldTransform(hdc, &identity);
937 SetGraphicsMode(hdc, GM_COMPATIBLE);
938 SelectObject(hdc, old_font);
939
940 if (result == GDI_ERROR) {
941 const int errorCode = int(GetLastError());
942 qErrnoWarning(errorCode, "QWinFontEngine: unable to query transformed glyph metrics (GetGlyphOutline() failed, error %d)...", errorCode);
943 return 0;
944 }
945
946 iw = int(tgm.gmBlackBoxX);
947 ih = int(tgm.gmBlackBoxY);
948
949 xform.eDx -= tgm.gmptGlyphOrigin.x;
950 xform.eDy += tgm.gmptGlyphOrigin.y;
951 }
952
953 // The padding here needs to be kept in sync with the values in alphaMapBoundingBox.
954 QWindowsNativeImage *ni = new QWindowsNativeImage(iw + 2 * margin,
955 ih + 2 * margin,
957
958 /*If cleartype is enabled we use the standard system format even on Windows CE
959 and not the special textbuffer format we have to use if cleartype is disabled*/
960
961 ni->image().fill(0xffffffff);
962
963 HDC hdc = ni->hdc();
964
965 SelectObject(hdc, GetStockObject(NULL_BRUSH));
966 SelectObject(hdc, GetStockObject(BLACK_PEN));
967 SetTextColor(hdc, RGB(0,0,0));
968 SetBkMode(hdc, TRANSPARENT);
969 SetTextAlign(hdc, TA_BASELINE);
970
971 HGDIOBJ old_font = SelectObject(hdc, font);
972
973 if (has_transformation) {
974 SetGraphicsMode(hdc, GM_ADVANCED);
975 SetWorldTransform(hdc, &xform);
976 ExtTextOut(hdc, 0, 0, options, 0, reinterpret_cast<LPCWSTR>(&glyph), 1, 0);
977 } else {
978 ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, reinterpret_cast<LPCWSTR>(&glyph), 1, 0);
979 }
980
981 SelectObject(hdc, old_font);
982 return ni;
983}
984
986 const QFixedPoint &,
987 const QTransform &matrix,
989{
990 int margin = 0;
994 gm.width += margin * 2;
995 gm.height += margin * 2;
996 return gm;
997}
998
1000{
1001 HFONT font = hfont;
1002
1003 bool clearTypeTemporarilyDisabled = (m_fontEngineData->clearTypeEnabled && m_logfont.lfQuality != NONANTIALIASED_QUALITY);
1004 if (clearTypeTemporarilyDisabled) {
1005 LOGFONT lf = m_logfont;
1006 lf.lfQuality = ANTIALIASED_QUALITY;
1007 font = CreateFontIndirect(&lf);
1008 }
1010 mask_format = QImage::Format_RGB32;
1011
1012 const QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format);
1013 if (mask == 0) {
1014 if (m_fontEngineData->clearTypeEnabled)
1015 DeleteObject(font);
1016 return QImage();
1017 }
1018
1019 QImage alphaMap(mask->width(), mask->height(), QImage::Format_Alpha8);
1020
1021
1022 // Copy data... Cannot use QPainter here as GDI has messed up the
1023 // Alpha channel of the ni.image pixels...
1024 for (int y=0; y<mask->height(); ++y) {
1025 uchar *dest = alphaMap.scanLine(y);
1026 if (mask->image().format() == QImage::Format_RGB16) {
1027 const qint16 *src = reinterpret_cast<const qint16 *>(mask->image().constScanLine(y));
1028 for (int x=0; x<mask->width(); ++x)
1029 dest[x] = 255 - qGray(src[x]);
1030 } else {
1031 const uint *src = reinterpret_cast<const uint *>(mask->image().constScanLine(y));
1032 for (int x=0; x<mask->width(); ++x) {
1034 dest[x] = 255 - qGray(src[x]);
1035 else
1036 dest[x] = 255 - (m_fontEngineData->pow_gamma[qGray(src[x])] * 255. / 2047.);
1037 }
1038 }
1039 }
1040
1041 // Cleanup...
1042 delete mask;
1043 if (clearTypeTemporarilyDisabled) {
1044 DeleteObject(font);
1045 }
1046
1047 return alphaMap;
1048}
1049
1050#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
1051#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D
1052
1054 const QFixedPoint &,
1055 const QTransform &t)
1056{
1057 HFONT font = hfont;
1058
1059 UINT contrast;
1060 SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0);
1061 SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast<void *>(quintptr(1000)), 0);
1062
1064 QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32);
1065 SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast<void *>(quintptr(contrast)), 0);
1066
1067 if (mask == 0)
1068 return QImage();
1069
1070 // Gracefully handle the odd case when the display is 16-bit
1071 const QImage source = mask->image().depth() == 32
1072 ? mask->image()
1073 : mask->image().convertToFormat(QImage::Format_RGB32);
1074
1075 QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32);
1076 for (int y=0; y<mask->height(); ++y) {
1077 auto dest = reinterpret_cast<uint *>(rgbMask.scanLine(y));
1078 const uint *src = reinterpret_cast<const uint *>(source.constScanLine(y));
1079 for (int x=0; x<mask->width(); ++x) {
1080 dest[x] = 0xffffffff - (0x00ffffff & src[x]);
1081 }
1082 }
1083
1084 delete mask;
1085
1086 return rgbMask;
1087}
1088
1090{
1092 QString actualFontName = request.families.first();
1093 if (!uniqueFamilyName.isEmpty())
1094 request.families = QStringList(uniqueFamilyName);
1095 request.pixelSize = pixelSize;
1096 const QString faceName = QString::fromWCharArray(m_logfont.lfFaceName);
1097
1098 QFontEngine *fontEngine =
1101 m_fontEngineData);
1102 if (fontEngine) {
1103 fontEngine->fontDef.families = QStringList(actualFontName);
1104 if (!uniqueFamilyName.isEmpty()) {
1105 static_cast<QWindowsFontEngine *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
1107 QPlatformFontDatabase *pfdb = pi->fontDatabase();
1108 static_cast<QWindowsFontDatabase *>(pfdb)->refUniqueFont(uniqueFamilyName);
1109 }
1110 }
1111 }
1112 return fontEngine;
1113}
1114
1116{
1117 return hfont;
1118}
1119
1121 int dpi)
1122{
1123 fontDef = request; // most settings are equal
1124 HDC dc = m_fontEngineData->hdc;
1125 SelectObject(dc, hfont);
1126 wchar_t n[64];
1127 GetTextFace(dc, 64, n);
1129 fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1130 if (fontDef.pointSize < 0) {
1131 fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
1132 } else if (fontDef.pixelSize == -1) {
1133 fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.);
1134 }
1135}
1136
1138{
1139 // Support all transformations for ttf files, and translations for raster fonts
1140 return ttf || transform.type() <= QTransform::TxTranslate;
1141}
1142
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
\inmodule QtCore
Definition qchar.h:48
static constexpr bool requiresSurrogates(char32_t ucs4) noexcept
Returns true if the UCS-4-encoded character specified by ucs4 can be split into the high and low part...
Definition qchar.h:504
static constexpr char16_t highSurrogate(char32_t ucs4) noexcept
Returns the high surrogate part of a UCS-4-encoded code point.
Definition qchar.h:518
static constexpr char16_t lowSurrogate(char32_t ucs4) noexcept
Returns the low surrogate part of a UCS-4-encoded code point.
Definition qchar.h:522
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
void loadKerningPairs(QFixed scalingFactor)
QFixed calculatedCapHeight() const
static const uchar * getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily)
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing=nullptr, qreal *rightBearing=nullptr)
QFontDef fontDef
virtual int glyphMargin(GlyphFormat format)
QByteArray getSfntTable(uint tag) const
virtual void initializeHeightMetrics() const
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags)
virtual QFixed lineThickness() const
void addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags)
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
virtual bool hasUnreliableGlyphOutline() const
virtual QFixed xHeight() const
static QPlatformIntegration * platformIntegration()
\inmodule QtGui
Definition qimage.h:37
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition qimage.cpp:1615
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_Alpha8
Definition qimage.h:65
@ Format_RGB32
Definition qimage.h:46
@ Format_RGB16
Definition qimage.h:49
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition qimage.cpp:1738
int depth() const
\inmodule QtGui
\inmodule QtGui
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
The QPlatformIntegration class is the entry for WindowSystem specific functionality.
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
Font database for Windows.
static QFontEngine * createEngine(const QFontDef &request, const QString &faceName, int dpi, const QSharedPointer< QWindowsFontEngineData > &data)
Standard Windows font engine.
QFixed averageCharWidth() const override
bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const
QFixed xHeight() const override
void setUniqueFamilyName(const QString &newName)
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags) override
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override
glyph_metrics_t boundingBox(glyph_t g) override
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const
glyph_t glyphIndex(uint ucs4) const override
HGDIOBJ selectDesignFont() const
FaceId faceId() const override
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override
Returns true if the font table idetified by tag exists in the font; returns false otherwise.
void initFontInfo(const QFontDef &request, int dpi)
void initializeHeightMetrics() const override
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override
QFixed emSquareSize() const override
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &, const QTransform &matrix, GlyphFormat) override
qreal minLeftBearing() const override
bool hasUnreliableGlyphOutline() const override
QFontEngine * cloneWithSize(qreal pixelSize) const override
QWindowsFontEngine(const QString &name, LOGFONT lf, const QSharedPointer< QWindowsFontEngineData > &fontEngineData)
void getGlyphBearings(glyph_t glyph, qreal *leftBearing=nullptr, qreal *rightBearing=nullptr) override
QFixed capHeight() const override
QFixed lineThickness() const override
QImage alphaRGBMapForGlyph(glyph_t t, const QFixedPoint &subPixelPosition, const QTransform &xform) override
bool supportsTransformation(const QTransform &transform) const override
qreal minRightBearing() const override
QImage alphaMapForGlyph(glyph_t t) override
Qt::HANDLE handle() const override
void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override
Properties properties() const override
int synthesized() const override
qreal maxCharWidth() const override
Windows Native image.
static QImage::Format systemFormat()
QString str
[2]
QPixmap p2
QPixmap p1
[0]
double pi
[0]
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
void * HANDLE
AudioChannelLayoutTag tag
static const QCssKnownValue positions[NumKnownPositionModes - 1]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define MAKE_TAG(ch1, ch2, ch3, ch4)
#define qWarning
Definition qlogging.h:162
#define qCDebug(category,...)
return ret
#define SIZE(large, small, mini)
int qFloor(T v)
Definition qmath.h:42
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1369
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLfloat GLfloat f
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLenum src
GLenum GLuint buffer
GLint GLsizei width
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLuint name
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat n
GLint GLsizei GLsizei GLenum format
GLint y
GLsizei GLsizei GLchar * source
GLuint GLenum GLenum transform
GLuint res
GLenum GLsizei len
GLuint GLenum matrix
GLdouble GLdouble t
Definition qopenglext.h:243
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLenum GLenum GLenum GLenum scale
GLenum GLenum GLsizei void * table
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
constexpr int qGray(int r, int g, int b)
Definition qrgb.h:36
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Definition qstring.h:1391
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
unsigned int glyph_t
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
short qint16
Definition qtypes.h:42
unsigned short quint16
Definition qtypes.h:43
size_t quintptr
Definition qtypes.h:72
unsigned int uint
Definition qtypes.h:29
unsigned short ushort
Definition qtypes.h:28
double qreal
Definition qtypes.h:92
unsigned char quint8
Definition qtypes.h:41
quint16 qt_getUShort(const unsigned char *p)
static OUTLINETEXTMETRIC * getOutlineTextMetric(HDC hdc)
static const ushort char_table[]
static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, QPainterPath *path, bool ttf, glyph_metrics_t *metric=nullptr, qreal scale=1.0, qreal stretch=1.0)
#define TT_PRIM_CSPLINE
void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
static QString stringFromOutLineTextMetric(const OUTLINETEXTMETRIC *otm, PSTR offset)
#define SPI_SETFONTSMOOTHINGCONTRAST
@ max_font_count
#define MAKE_LITTLE_ENDIAN_TAG(ch1, ch2, ch3, ch4)
static const int char_table_entries
static double qt_fixed_to_double(const FIXED &p)
static QPointF qt_to_qpointf(const POINTFX &pt, qreal scale, qreal stretch)
#define SPI_GETFONTSMOOTHINGCONTRAST
Q_CHECK_PTR(a=new int[80])
QItemSelection * selection
[0]
QNetworkRequest request(url)
static constexpr QFixed fromReal(qreal r)
Definition qfixed_p.h:35
constexpr int value() const
Definition qfixed_p.h:38
constexpr int toInt() const
Definition qfixed_p.h:41
uint stretch
Definition qfont_p.h:64
uint fixedPitch
Definition qfont_p.h:70
qreal pixelSize
Definition qfont_p.h:60
QStringList families
Definition qfont_p.h:54
qreal pointSize
Definition qfont_p.h:59
glyph_t * glyphs
QFixed * advances
glyph_metrics_t transformed(const QTransform &xform) const