Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsfontenginedirectwrite.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
6
7#include <QtCore/QtEndian>
8#include <QtCore/QVarLengthArray>
9#include <QtCore/QFile>
10#include <private/qstringiterator_p.h>
11#include <QtCore/private/qsystemlibrary_p.h>
12#include <QtCore/private/qwinregistry_p.h>
13#include <QtGui/private/qguiapplication_p.h>
14#include <qpa/qplatformintegration.h>
15#include <QtGui/qpainterpath.h>
16
17#if QT_CONFIG(directwrite3)
19# include <dwrite_3.h>
20#else
21# include <dwrite_2.h>
22#endif
23
24#include <d2d1.h>
25
27
28// Clang does not consider __declspec(nothrow) as nothrow
29QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec")
30
31// Convert from design units to logical pixels
32#define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE) \
33 QFixed::fromReal((qreal(DESIGN_UNIT_VALUE) / qreal(m_unitsPerEm)) * fontDef.pixelSize)
34
35namespace {
36
37 class GeometrySink: public IDWriteGeometrySink
38 {
39 Q_DISABLE_COPY_MOVE(GeometrySink)
40 public:
41 GeometrySink(QPainterPath *path)
42 : m_refCount(0), m_path(path)
43 {
44 Q_ASSERT(m_path != 0);
45 }
46 virtual ~GeometrySink() = default;
47
48 IFACEMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *beziers, UINT bezierCount) override;
49 IFACEMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointCount) override;
50 IFACEMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) override;
51 IFACEMETHOD(Close)() override;
52 IFACEMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd) override;
53 IFACEMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode) override;
54 IFACEMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags) override;
55
56 IFACEMETHOD_(unsigned long, AddRef)() override;
57 IFACEMETHOD_(unsigned long, Release)() override;
58 IFACEMETHOD(QueryInterface)(IID const &riid, void **ppvObject) override;
59
60 private:
61 inline static QPointF fromD2D1_POINT_2F(const D2D1_POINT_2F &inp)
62 {
63 return QPointF(inp.x, inp.y);
64 }
65
66 unsigned long m_refCount;
67 QPointF m_startPoint;
68 QPainterPath *m_path;
69 };
70
71 void GeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers,
72 UINT bezierCount) noexcept
73 {
74 for (uint i=0; i<bezierCount; ++i) {
75 QPointF c1 = fromD2D1_POINT_2F(beziers[i].point1);
76 QPointF c2 = fromD2D1_POINT_2F(beziers[i].point2);
77 QPointF p2 = fromD2D1_POINT_2F(beziers[i].point3);
78
79 m_path->cubicTo(c1, c2, p2);
80 }
81 }
82
83 void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) noexcept
84 {
85 for (uint i=0; i<pointsCount; ++i)
86 m_path->lineTo(fromD2D1_POINT_2F(points[i]));
87 }
88
89 void GeometrySink::BeginFigure(D2D1_POINT_2F startPoint,
90 D2D1_FIGURE_BEGIN /*figureBegin*/) noexcept
91 {
92 m_startPoint = fromD2D1_POINT_2F(startPoint);
93 m_path->moveTo(m_startPoint);
94 }
95
96 IFACEMETHODIMP GeometrySink::Close() noexcept
97 {
98 return E_NOTIMPL;
99 }
100
101 void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) noexcept
102 {
103 if (figureEnd == D2D1_FIGURE_END_CLOSED)
104 m_path->closeSubpath();
105 }
106
107 void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) noexcept
108 {
109 m_path->setFillRule(fillMode == D2D1_FILL_MODE_ALTERNATE
112 }
113
114 void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/) noexcept
115 {
116 /* Not implemented */
117 }
118
119 IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef() noexcept
120 {
121 return InterlockedIncrement(&m_refCount);
122 }
123
124 IFACEMETHODIMP_(unsigned long) GeometrySink::Release() noexcept
125 {
126 unsigned long newCount = InterlockedDecrement(&m_refCount);
127 if (newCount == 0)
128 {
129 delete this;
130 return 0;
131 }
132
133 return newCount;
134 }
135
136 IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject) noexcept
137 {
138 if (__uuidof(IDWriteGeometrySink) == riid) {
139 *ppvObject = this;
140 } else if (__uuidof(IUnknown) == riid) {
141 *ppvObject = this;
142 } else {
143 *ppvObject = NULL;
144 return E_FAIL;
145 }
146
147 AddRef();
148 return S_OK;
149 }
150
151}
152
153static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE renderMode)
154{
155 switch (renderMode) {
156 case DWRITE_RENDERING_MODE_GDI_CLASSIC:
157 return DWRITE_MEASURING_MODE_GDI_CLASSIC;
158 case DWRITE_RENDERING_MODE_GDI_NATURAL:
159 return DWRITE_MEASURING_MODE_GDI_NATURAL;
160 default:
161 return DWRITE_MEASURING_MODE_NATURAL;
162 }
163}
164
165DWRITE_RENDERING_MODE QWindowsFontEngineDirectWrite::hintingPreferenceToRenderingMode(const QFontDef &fontDef) const
166{
168 return DWRITE_RENDERING_MODE_ALIASED;
169
171 if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
172 // Microsoft documentation recommends using asymmetric rendering for small fonts
173 // at pixel size 16 and less, and symmetric for larger fonts.
174 hintingPreference = fontDef.pixelSize > 16.0
177 }
178
179 switch (hintingPreference) {
181 return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
183 return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
184 default:
185 return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC;
186 }
187}
188
202 qreal pixelSize,
203 const QSharedPointer<QWindowsFontEngineData> &d)
204 : QFontEngine(DirectWrite)
205 , m_fontEngineData(d)
206 , m_directWriteFontFace(directWriteFontFace)
207 , m_directWriteBitmapRenderTarget(0)
208 , m_lineThickness(-1)
209 , m_unitsPerEm(-1)
210 , m_capHeight(-1)
211 , m_xHeight(-1)
212{
213 qCDebug(lcQpaFonts) << __FUNCTION__ << pixelSize;
214
215 Q_ASSERT(m_directWriteFontFace);
216
217 m_fontEngineData->directWriteFactory->AddRef();
218 m_directWriteFontFace->AddRef();
219
220 fontDef.pixelSize = pixelSize;
221 collectMetrics();
222 cache_cost = m_xHeight.toInt() * m_xHeight.toInt() * 2000;
223}
224
226{
227 qCDebug(lcQpaFonts) << __FUNCTION__;
228
229 m_fontEngineData->directWriteFactory->Release();
230 m_directWriteFontFace->Release();
231
232 if (m_directWriteBitmapRenderTarget != 0)
233 m_directWriteBitmapRenderTarget->Release();
234
235 if (!m_uniqueFamilyName.isEmpty()) {
237 static_cast<QWindowsFontDatabase *>(pfdb)->derefUniqueFont(m_uniqueFamilyName);
238 }
239}
240
241#ifndef Q_CC_MINGW
242typedef IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader;
243
245{
246 return __uuidof(IDWriteLocalFontFileLoader);
247}
248#else // !Q_CC_MINGW
249DECLARE_INTERFACE_(QIdWriteLocalFontFileLoader, IDWriteFontFileLoader)
250{
251 STDMETHOD(GetFilePathLengthFromKey)(THIS_ void const *, UINT32, UINT32*) PURE;
252 STDMETHOD(GetFilePathFromKey)(THIS_ void const *, UINT32, WCHAR *, UINT32) PURE;
253 STDMETHOD(GetLastWriteTimeFromKey)(THIS_ void const *, UINT32, FILETIME *) PURE;
254};
255
257{
258 static const UUID result = { 0xb2d9f3ec, 0xc9fe, 0x4a11, {0xa2, 0xec, 0xd8, 0x62, 0x8, 0xf7, 0xc0, 0xa2}};
259 return result;
260}
261#endif // Q_CC_MINGW
262
263QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fontFile)
264{
265 IDWriteFontFileLoader *loader = nullptr;
266
267 HRESULT hr = fontFile->GetLoader(&loader);
268 if (FAILED(hr)) {
269 qErrnoWarning("%s: GetLoader failed", __FUNCTION__);
270 return QString();
271 }
272
273 QIdWriteLocalFontFileLoader *localLoader = nullptr;
274 hr = loader->QueryInterface(uuidIdWriteLocalFontFileLoader(),
275 reinterpret_cast<void **>(&localLoader));
276
277 const void *fontFileReferenceKey = nullptr;
278 UINT32 fontFileReferenceKeySize = 0;
279 if (SUCCEEDED(hr)) {
280 hr = fontFile->GetReferenceKey(&fontFileReferenceKey,
281 &fontFileReferenceKeySize);
282 if (FAILED(hr))
283 qErrnoWarning(hr, "%s: GetReferenceKey failed", __FUNCTION__);
284 }
285
286 UINT32 filePathLength = 0;
287 if (SUCCEEDED(hr)) {
288 hr = localLoader->GetFilePathLengthFromKey(fontFileReferenceKey,
289 fontFileReferenceKeySize,
290 &filePathLength);
291 if (FAILED(hr))
292 qErrnoWarning(hr, "GetFilePathLength failed", __FUNCTION__);
293 }
294
295 QString ret;
296 if (SUCCEEDED(hr) && filePathLength > 0) {
297 QVarLengthArray<wchar_t> filePath(filePathLength + 1);
298
299 hr = localLoader->GetFilePathFromKey(fontFileReferenceKey,
300 fontFileReferenceKeySize,
301 filePath.data(),
302 filePathLength + 1);
303 if (FAILED(hr))
304 qErrnoWarning(hr, "%s: GetFilePathFromKey failed", __FUNCTION__);
305 else
306 ret = QString::fromWCharArray(filePath.data());
307 }
308
309 if (localLoader != nullptr)
310 localLoader->Release();
311
312 if (loader != nullptr)
313 loader->Release();
314 return ret;
315}
316
318{
319 if (m_fontEngineData == nullptr || m_directWriteFontFace == nullptr)
320 return NULL;
321
322 LOGFONT lf;
323 HRESULT hr = m_fontEngineData->directWriteGdiInterop->ConvertFontFaceToLOGFONT(m_directWriteFontFace,
324 &lf);
325 if (SUCCEEDED(hr)) {
326 lf.lfHeight = -qRound(fontDef.pixelSize);
327 return CreateFontIndirect(&lf);
328 } else {
329 return NULL;
330 }
331}
332
334{
335 DWRITE_FONT_METRICS metrics;
336 m_directWriteFontFace->GetMetrics(&metrics);
337
341
343}
344
345void QWindowsFontEngineDirectWrite::collectMetrics()
346{
347 DWRITE_FONT_METRICS metrics;
348
349 m_directWriteFontFace->GetMetrics(&metrics);
350 m_unitsPerEm = metrics.designUnitsPerEm;
351
352 m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness);
353 m_capHeight = DESIGN_TO_LOGICAL(metrics.capHeight);
354 m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight);
355 m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition);
356
357 IDWriteFontFile *fontFile = nullptr;
358 UINT32 numberOfFiles = 1;
359 if (SUCCEEDED(m_directWriteFontFace->GetFiles(&numberOfFiles, &fontFile))) {
360 m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile));
361 fontFile->Release();
362 }
363
365 const int advanceWidthMaxLocation = 10;
366 if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) {
367 quint16 advanceWidthMax = qFromBigEndian<quint16>(table.constData() + advanceWidthMaxLocation);
368 m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax);
369 }
370
372}
373
375{
376 if (m_underlinePosition > 0)
377 return m_underlinePosition;
378 else
380}
381
383{
384 if (m_lineThickness > 0)
385 return m_lineThickness;
386 else
388}
389
391{
392 bool ret = false;
393
394 const void *tableData = 0;
395 UINT32 tableSize;
396 void *tableContext = 0;
397 BOOL exists;
398 HRESULT hr = m_directWriteFontFace->TryGetFontTable(qbswap<quint32>(tag),
399 &tableData, &tableSize,
400 &tableContext, &exists);
401 if (SUCCEEDED(hr)) {
402 if (exists) {
403 ret = true;
404 if (buffer && *length >= tableSize)
405 memcpy(buffer, tableData, tableSize);
406 *length = tableSize;
407 Q_ASSERT(int(*length) > 0);
408 }
409 m_directWriteFontFace->ReleaseFontTable(tableContext);
410 } else {
411 qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__);
412 }
413
414 return ret;
415}
416
418{
419 if (m_unitsPerEm > 0)
420 return m_unitsPerEm;
421 else
423}
424
426{
427 UINT16 glyphIndex;
428
429 HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(&ucs4, 1, &glyphIndex);
430 if (FAILED(hr)) {
431 qErrnoWarning("%s: glyphIndex failed", __FUNCTION__);
432 glyphIndex = 0;
433 }
434
435 return glyphIndex;
436}
437
439 int *nglyphs, QFontEngine::ShaperFlags flags) const
440{
441 Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
442 if (*nglyphs < len) {
443 *nglyphs = len;
444 return -1;
445 }
446
447 QVarLengthArray<UINT32> codePoints(len);
448 int actualLength = 0;
450 while (it.hasNext())
451 codePoints[actualLength++] = it.next();
452
453 QVarLengthArray<UINT16> glyphIndices(actualLength);
454 HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength,
455 glyphIndices.data());
456 if (FAILED(hr)) {
457 qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
458 return -1;
459 }
460
461 int mappedGlyphs = 0;
462 for (int i = 0; i < actualLength; ++i) {
463 glyphs->glyphs[i] = glyphIndices.at(i);
464 if (glyphs->glyphs[i] != 0 || isIgnorableChar(codePoints.at(i)))
465 mappedGlyphs++;
466 }
467
468 *nglyphs = actualLength;
469 glyphs->numGlyphs = actualLength;
470
471 if (!(flags & GlyphIndicesOnly))
472 recalcAdvances(glyphs, {});
473
474 return mappedGlyphs;
475}
476
478{
479 return m_faceId;
480}
481
482void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags shaperFlags) const
483{
484 QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
485
486 // ### Caching?
487 for(int i=0; i<glyphs->numGlyphs; i++)
488 glyphIndices[i] = UINT16(glyphs->glyphs[i]);
489
490 QVarLengthArray<DWRITE_GLYPH_METRICS> glyphMetrics(glyphIndices.size());
491
492 HRESULT hr;
493 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
494 bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
495 if (!needsDesignMetrics && (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC
496 || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL
497 || renderMode == DWRITE_RENDERING_MODE_ALIASED)) {
498 hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
499 1.0f,
500 NULL,
501 renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL,
502 glyphIndices.data(),
503 glyphIndices.size(),
504 glyphMetrics.data());
505 } else {
506 hr = m_directWriteFontFace->GetDesignGlyphMetrics(glyphIndices.data(),
507 glyphIndices.size(),
508 glyphMetrics.data());
509 }
510 if (SUCCEEDED(hr)) {
511 qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0;
512 for (int i = 0; i < glyphs->numGlyphs; ++i)
513 glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth * stretch);
514 } else {
515 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
516 }
517}
518
521 glyph_metrics_t *metric)
522{
523 float advance = 0.0f;
524 UINT16 g = glyph;
525 DWRITE_GLYPH_OFFSET offset;
526 offset.advanceOffset = 0;
527 offset.ascenderOffset = 0;
528 GeometrySink geometrySink(path);
529 HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(m_unitsPerEm,
530 &g,
531 &advance,
532 &offset,
533 1,
534 false,
535 false,
536 &geometrySink);
537 if (FAILED(hr)) {
538 qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
539 return;
540 }
541
542 DWRITE_GLYPH_METRICS glyphMetrics;
543 hr = m_directWriteFontFace->GetDesignGlyphMetrics(&g, 1, &glyphMetrics);
544 if (FAILED(hr)) {
545 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
546 return;
547 }
548
549 QFixed advanceWidth = QFixed(int(glyphMetrics.advanceWidth));
550 QFixed leftSideBearing = QFixed(glyphMetrics.leftSideBearing);
551 QFixed rightSideBearing = QFixed(glyphMetrics.rightSideBearing);
552 QFixed advanceHeight = QFixed(int(glyphMetrics.advanceHeight));
553 QFixed verticalOriginY = QFixed(glyphMetrics.verticalOriginY);
554 QFixed topSideBearing = QFixed(glyphMetrics.topSideBearing);
555 QFixed bottomSideBearing = QFixed(glyphMetrics.bottomSideBearing);
556 QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
557 QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
558 *metric = glyph_metrics_t(leftSideBearing,
559 -verticalOriginY + topSideBearing,
560 width,
561 height,
562 advanceWidth,
563 0);
564}
565
567 QPainterPath *path, QTextItem::RenderFlags flags)
568{
570 QVarLengthArray<UINT16> glyphIndices(nglyphs);
571 QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(nglyphs);
572 QVarLengthArray<FLOAT> glyphAdvances(nglyphs);
573
574 for (int i=0; i<nglyphs; ++i) {
575 glyphIndices[i] = glyphs[i];
576 glyphOffsets[i].advanceOffset = positions[i].x.toReal();
577 glyphOffsets[i].ascenderOffset = -positions[i].y.toReal();
578 glyphAdvances[i] = 0.0;
579 }
580
581 GeometrySink geometrySink(path);
582 HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(
584 glyphIndices.data(),
585 glyphAdvances.data(),
586 glyphOffsets.data(),
587 nglyphs,
588 false,
589 false,
590 &geometrySink
591 );
592
593 if (FAILED(hr))
594 qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
595}
596
598{
599 if (glyphs.numGlyphs == 0)
600 return glyph_metrics_t();
601 QFixed w = 0;
602 for (int i = 0; i < glyphs.numGlyphs; ++i)
603 w += glyphs.effectiveAdvance(i);
604
605 const QFixed leftBearing = firstLeftBearing(glyphs);
606 return glyph_metrics_t(leftBearing, -ascent(), w - leftBearing - lastRightBearing(glyphs),
607 ascent() + descent(), w, 0);
608}
609
611{
612 UINT16 glyphIndex = g;
613
614 DWRITE_GLYPH_METRICS glyphMetrics;
615 HRESULT hr = m_directWriteFontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics);
616 if (SUCCEEDED(hr)) {
617 QFixed advanceWidth = DESIGN_TO_LOGICAL(glyphMetrics.advanceWidth);
618 QFixed leftSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.leftSideBearing);
619 QFixed rightSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.rightSideBearing);
620 QFixed advanceHeight = DESIGN_TO_LOGICAL(glyphMetrics.advanceHeight);
621 QFixed verticalOriginY = DESIGN_TO_LOGICAL(glyphMetrics.verticalOriginY);
622 QFixed topSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.topSideBearing);
623 QFixed bottomSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.bottomSideBearing);
624 QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
625 QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
626 return glyph_metrics_t(leftSideBearing,
627 -verticalOriginY + topSideBearing,
628 width,
629 height,
630 advanceWidth,
631 0);
632 } else {
633 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
634 }
635
636 return glyph_metrics_t();
637}
638
640{
641 if (m_capHeight <= 0)
642 return calculatedCapHeight();
643
644 return m_capHeight;
645}
646
648{
649 return m_xHeight;
650}
651
653{
654 return m_maxAdvanceWidth.toReal();
655}
656
658 const QFixedPoint &subPixelPosition,
659 const QTransform &t)
660{
661 QImage im = imageForGlyph(glyph, subPixelPosition, glyphMargin(Format_A8), t);
662
663 QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
664
665 for (int y=0; y<im.height(); ++y) {
666 const uint *src = reinterpret_cast<const uint *>(im.constScanLine(y));
667 uchar *dst = alphaMap.scanLine(y);
668 for (int x=0; x<im.width(); ++x) {
669 *dst = 255 - (m_fontEngineData->pow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.);
670 ++dst;
671 ++src;
672 }
673 }
674
675 return alphaMap;
676}
677
679 const QFixedPoint &subPixelPosition)
680{
681 return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
682}
683
685{
686 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
687 return (renderMode != DWRITE_RENDERING_MODE_GDI_CLASSIC
688 && renderMode != DWRITE_RENDERING_MODE_GDI_NATURAL
689 && renderMode != DWRITE_RENDERING_MODE_ALIASED);
690}
691
693{
694 IDWriteFontFace2 *directWriteFontFace2;
695 if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
696 reinterpret_cast<void **>(&directWriteFontFace2)))) {
697 DWRITE_FONT_METRICS1 metrics;
698 directWriteFontFace2->GetMetrics(&metrics);
699
701 p.emSquare = metrics.designUnitsPerEm;
702 p.boundingBox = QRectF(metrics.glyphBoxLeft,
703 -metrics.glyphBoxTop,
704 metrics.glyphBoxRight - metrics.glyphBoxLeft,
705 metrics.glyphBoxTop - metrics.glyphBoxBottom);
706 p.ascent = metrics.ascent;
707 p.descent = metrics.descent;
708 p.leading = metrics.lineGap;
709 p.capHeight = metrics.capHeight;
710 p.lineWidth = metrics.underlineThickness;
711
712 directWriteFontFace2->Release();
713 return p;
714 } else {
716 }
717}
718
719QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
720 const QFixedPoint &subPixelPosition,
721 int margin,
722 const QTransform &originalTransform,
723 const QColor &color)
724{
725 UINT16 glyphIndex = t;
726 FLOAT glyphAdvance = 0;
727
728 DWRITE_GLYPH_OFFSET glyphOffset;
729 glyphOffset.advanceOffset = 0;
730 glyphOffset.ascenderOffset = 0;
731
732 DWRITE_GLYPH_RUN glyphRun;
733 glyphRun.fontFace = m_directWriteFontFace;
734 glyphRun.fontEmSize = fontDef.pixelSize;
735 glyphRun.glyphCount = 1;
736 glyphRun.glyphIndices = &glyphIndex;
737 glyphRun.glyphAdvances = &glyphAdvance;
738 glyphRun.isSideways = false;
739 glyphRun.bidiLevel = 0;
740 glyphRun.glyphOffsets = &glyphOffset;
741
742 QTransform xform = originalTransform;
744 xform.scale(fontDef.stretch / 100.0, 1.0);
745
746 DWRITE_MATRIX transform;
747 transform.dx = subPixelPosition.x.toReal();
748 transform.dy = 0;
749 transform.m11 = xform.m11();
750 transform.m12 = xform.m12();
751 transform.m21 = xform.m21();
752 transform.m22 = xform.m22();
753
754 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
755 DWRITE_MEASURING_MODE measureMode =
756 renderModeToMeasureMode(renderMode);
757
758 DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
759 ? DWRITE_GRID_FIT_MODE_DISABLED
760 : DWRITE_GRID_FIT_MODE_DEFAULT;
761
762 IDWriteFactory2 *factory2 = nullptr;
763 HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
764 reinterpret_cast<void **>(&factory2));
765 IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
766 if (!SUCCEEDED(hr)) {
767 qErrnoWarning(hr, "%s: Failed to query IDWriteFactory2 interface.", __FUNCTION__);
768 hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
769 &glyphRun,
770 1.0f,
771 &transform,
772 renderMode,
773 measureMode,
774 0.0, 0.0,
775 &glyphAnalysis
776 );
777 } else {
778 hr = factory2->CreateGlyphRunAnalysis(
779 &glyphRun,
780 &transform,
781 renderMode,
782 measureMode,
783 gridFitMode,
784 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
785 0.0, 0.0,
786 &glyphAnalysis
787 );
788 }
789
790 if (SUCCEEDED(hr)) {
791 RECT rect;
792 glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED
793 ? DWRITE_TEXTURE_ALIASED_1x1
794 : DWRITE_TEXTURE_CLEARTYPE_3x1,
795 &rect);
796
797 if (rect.top == rect.bottom || rect.left == rect.right)
798 return QImage();
799
800 QRect boundingRect = QRect(QPoint(rect.left - margin,
801 rect.top - margin),
802 QPoint(rect.right + margin,
803 rect.bottom + margin));
804
805
806 const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect
807 const int height = boundingRect.height() - 1;
808
810 HRESULT hr = DWRITE_E_NOCOLOR;
811 IDWriteColorGlyphRunEnumerator *enumerator = 0;
812 if (glyphFormat == QFontEngine::Format_ARGB && factory2 != nullptr) {
813 hr = factory2->TranslateColorGlyphRun(0.0f,
814 0.0f,
815 &glyphRun,
816 NULL,
817 measureMode,
818 NULL,
819 0,
820 &enumerator);
822 image.fill(0);
823 } else {
825 image.fill(0xffffffff);
826 }
827
828 BOOL ok = true;
829
830 if (SUCCEEDED(hr)) {
831 while (SUCCEEDED(hr) && ok) {
832 const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0;
833 hr = enumerator->GetCurrentRun(&colorGlyphRun);
834 if (FAILED(hr)) { // No colored runs, only outline
835 qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::GetCurrentRun failed", __FUNCTION__);
836 break;
837 }
838
839 IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL;
840 hr = factory2->CreateGlyphRunAnalysis(
841 &colorGlyphRun->glyphRun,
842 &transform,
843 renderMode,
844 measureMode,
845 gridFitMode,
846 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
847 0.0, 0.0,
848 &colorGlyphsAnalysis
849 );
850
851 if (FAILED(hr)) {
852 qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__);
853 break;
854 }
855
856 float r, g, b, a;
857 if (colorGlyphRun->paletteIndex == 0xFFFF) {
858 r = float(color.redF());
859 g = float(color.greenF());
860 b = float(color.blueF());
861 a = float(color.alphaF());
862 } else {
863 r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f);
864 g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f);
865 b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f);
866 a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f);
867 }
868
869 if (!qFuzzyIsNull(a)) {
870 renderGlyphRun(&image,
871 r,
872 g,
873 b,
874 a,
875 colorGlyphsAnalysis,
877 renderMode);
878 }
879 colorGlyphsAnalysis->Release();
880
881 hr = enumerator->MoveNext(&ok);
882 if (FAILED(hr)) {
883 qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::MoveNext failed", __FUNCTION__);
884 break;
885 }
886 }
887 } else {
888 float r, g, b, a;
890 r = float(color.redF());
891 g = float(color.greenF());
892 b = float(color.blueF());
893 a = float(color.alphaF());
894 } else {
895 r = g = b = a = 0.0;
896 }
897
898 renderGlyphRun(&image,
899 r,
900 g,
901 b,
902 a,
903 glyphAnalysis,
905 renderMode);
906 }
907
908 glyphAnalysis->Release();
909 return image;
910 } else {
911 qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed", __FUNCTION__);
912 return QImage();
913 }
914}
915
916
917void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
918 float r,
919 float g,
920 float b,
921 float a,
922 IDWriteGlyphRunAnalysis *glyphAnalysis,
923 const QRect &boundingRect,
924 DWRITE_RENDERING_MODE renderMode)
925{
926 const int width = destination->width();
927 const int height = destination->height();
928
929 r *= 255.0;
930 g *= 255.0;
931 b *= 255.0;
932
933 const int size = width * height * 3;
934 if (size > 0) {
935 RECT rect;
936 rect.left = boundingRect.left();
937 rect.top = boundingRect.top();
938 rect.right = boundingRect.right();
939 rect.bottom = boundingRect.bottom();
940
941 QVarLengthArray<BYTE, 1024> alphaValueArray(size);
942 BYTE *alphaValues = alphaValueArray.data();
943 memset(alphaValues, 0, size);
944
945 HRESULT hr = glyphAnalysis->CreateAlphaTexture(renderMode == DWRITE_RENDERING_MODE_ALIASED
946 ? DWRITE_TEXTURE_ALIASED_1x1
947 : DWRITE_TEXTURE_CLEARTYPE_3x1,
948 &rect,
949 alphaValues,
950 size);
951 if (SUCCEEDED(hr)) {
952 if (destination->hasAlphaChannel()) { // Color glyphs
953 for (int y = 0; y < height; ++y) {
954 uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
955 BYTE *src = alphaValues + width * 3 * y;
956
957 for (int x = 0; x < width; ++x) {
958 float redAlpha = a * *src++ / 255.0;
959 float greenAlpha = a * *src++ / 255.0;
960 float blueAlpha = a * *src++ / 255.0;
961 float averageAlpha = (redAlpha + greenAlpha + blueAlpha) / 3.0;
962
963 QRgb currentRgb = dest[x];
964 dest[x] = qRgba(qRound(qRed(currentRgb) * (1.0 - averageAlpha) + averageAlpha * r),
965 qRound(qGreen(currentRgb) * (1.0 - averageAlpha) + averageAlpha * g),
966 qRound(qBlue(currentRgb) * (1.0 - averageAlpha) + averageAlpha * b),
967 qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
968 }
969 }
970 } else if (renderMode == DWRITE_RENDERING_MODE_ALIASED) {
971 for (int y = 0; y < height; ++y) {
972 uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
973 BYTE *src = alphaValues + width * y;
974
975 for (int x = 0; x < width; ++x) {
976 int alpha = *(src++);
977 dest[x] = (alpha << 16) + (alpha << 8) + alpha;
978 }
979 }
980 } else {
981 for (int y = 0; y < height; ++y) {
982 uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
983 BYTE *src = alphaValues + width * 3 * y;
984
985 for (int x = 0; x < width; ++x) {
986 dest[x] = *(src + 0) << 16
987 | *(src + 1) << 8
988 | *(src + 2);
989
990 src += 3;
991 }
992 }
993 }
994 } else {
995 qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
996 }
997 } else {
998 glyphAnalysis->Release();
999 qWarning("%s: Glyph has no bounds", __FUNCTION__);
1000 }
1001}
1002
1004 const QFixedPoint &subPixelPosition,
1005 const QTransform &xform)
1006{
1007 QImage mask = imageForGlyph(t,
1008 subPixelPosition,
1010 xform);
1011
1012 return mask.depth() == 32
1013 ? mask
1014 : mask.convertToFormat(QImage::Format_RGB32);
1015}
1016
1018{
1019 QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace,
1020 pixelSize,
1021 m_fontEngineData);
1022
1023 fontEngine->fontDef = fontDef;
1024 fontEngine->fontDef.pixelSize = pixelSize;
1025 if (!m_uniqueFamilyName.isEmpty()) {
1026 fontEngine->setUniqueFamilyName(m_uniqueFamilyName);
1028 static_cast<QWindowsFontDatabase *>(pfdb)->refUniqueFont(m_uniqueFamilyName);
1029 }
1030
1031 return fontEngine;
1032}
1033
1035{
1036 return m_directWriteFontFace;
1037}
1038
1040 int dpi)
1041{
1042 fontDef = request;
1043
1044 if (fontDef.pointSize < 0)
1045 fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
1046 else if (fontDef.pixelSize == -1)
1047 fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.);
1048
1049 m_faceId.variableAxes = request.variableAxisValues;
1050
1051#if QT_CONFIG(directwrite3)
1052 IDWriteFontFace3 *face3 = nullptr;
1053 if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace3),
1054 reinterpret_cast<void **>(&face3)))) {
1055 IDWriteLocalizedStrings *names;
1056 if (SUCCEEDED(face3->GetFaceNames(&names))) {
1057 wchar_t englishLocale[] = L"en-us";
1058 fontDef.styleName = QWindowsDirectWriteFontDatabase::localeString(names, englishLocale);
1059 names->Release();
1060 }
1061
1062 // Color font
1063 if (face3->GetPaletteEntryCount() > 0)
1065
1066 face3->Release();
1067 }
1068#endif
1069}
1070
1072{
1073 const QString substitute =
1074 QWinRegistryKey(HKEY_LOCAL_MACHINE,
1075 LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)")
1076 .stringValue(familyName);
1077 return substitute.isEmpty() ? familyName : substitute;
1078}
1079
1081 const QFixedPoint &subPixelPosition,
1082 const QTransform &originalTransform,
1083 GlyphFormat format)
1084{
1086
1087 QTransform matrix = originalTransform;
1089 matrix.scale(fontDef.stretch / 100.0, 1.0);
1090
1091 glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance
1092
1093 UINT16 glyphIndex = glyph;
1094 FLOAT glyphAdvance = 0;
1095
1096 DWRITE_GLYPH_OFFSET glyphOffset;
1097 glyphOffset.advanceOffset = 0;
1098 glyphOffset.ascenderOffset = 0;
1099
1100 DWRITE_GLYPH_RUN glyphRun;
1101 glyphRun.fontFace = m_directWriteFontFace;
1102 glyphRun.fontEmSize = fontDef.pixelSize;
1103 glyphRun.glyphCount = 1;
1104 glyphRun.glyphIndices = &glyphIndex;
1105 glyphRun.glyphAdvances = &glyphAdvance;
1106 glyphRun.isSideways = false;
1107 glyphRun.bidiLevel = 0;
1108 glyphRun.glyphOffsets = &glyphOffset;
1109
1110 DWRITE_MATRIX transform;
1111 transform.dx = subPixelPosition.x.toReal();
1112 transform.dy = 0;
1113 transform.m11 = matrix.m11();
1114 transform.m12 = matrix.m12();
1115 transform.m21 = matrix.m21();
1116 transform.m22 = matrix.m22();
1117
1118 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
1119 DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode);
1120 DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
1121 ? DWRITE_GRID_FIT_MODE_DISABLED
1122 : DWRITE_GRID_FIT_MODE_DEFAULT;
1123
1124 IDWriteFactory2 *factory2 = nullptr;
1125 HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
1126 reinterpret_cast<void **>(&factory2));
1127
1128 IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
1129 if (SUCCEEDED(hr)) {
1130 hr = factory2->CreateGlyphRunAnalysis(
1131 &glyphRun,
1132 &transform,
1133 renderMode,
1134 measureMode,
1135 gridFitMode,
1136 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1137 0.0, 0.0,
1138 &glyphAnalysis
1139 );
1140 } else {
1141 hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
1142 &glyphRun,
1143 1.0f,
1144 &transform,
1145 renderMode,
1146 measureMode,
1147 0.0, 0.0,
1148 &glyphAnalysis
1149 );
1150 }
1151
1152 if (SUCCEEDED(hr)) {
1153 RECT rect;
1154 glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED ? DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
1155 glyphAnalysis->Release();
1156
1157 int margin = glyphMargin(format);
1158
1159 if (rect.left == rect.right || rect.top == rect.bottom)
1160 return glyph_metrics_t();
1161
1162 return glyph_metrics_t(rect.left,
1163 rect.top,
1164 rect.right - rect.left + margin * 2,
1165 rect.bottom - rect.top + margin * 2,
1166 bbox.xoff, bbox.yoff);
1167 } else {
1168 return glyph_metrics_t();
1169 }
1170}
1171
1173 const QFixedPoint &subPixelPosition,
1174 const QTransform &t,
1175 const QColor &color)
1176{
1177 return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_ARGB), t, color);
1178}
1179
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
virtual QFixed descent() const
virtual Properties properties() const
void loadKerningPairs(QFixed scalingFactor)
QFixed calculatedCapHeight() const
static bool isIgnorableChar(char32_t ucs4)
QFontDef fontDef
virtual QFixed ascent() const
virtual int glyphMargin(GlyphFormat format)
QFixed firstLeftBearing(const QGlyphLayout &glyphs)
QByteArray getSfntTable(uint tag) const
virtual void initializeHeightMetrics() const
virtual QFixed lineThickness() const
virtual QFixed underlinePosition() const
GlyphFormat glyphFormat
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
QFixed lastRightBearing(const QGlyphLayout &glyphs)
virtual QFixed emSquareSize() const
HintingPreference
Definition qfont.h:55
@ PreferNoHinting
Definition qfont.h:57
@ PreferVerticalHinting
Definition qfont.h:58
@ PreferDefaultHinting
Definition qfont.h:56
@ AnyStretch
Definition qfont.h:84
@ NoAntialias
Definition qfont.h:47
static QPlatformIntegration * platformIntegration()
\inmodule QtGui
Definition qimage.h:37
int width() const
Returns the width of the image.
int height() const
Returns the height of the image.
@ Format_Alpha8
Definition qimage.h:65
@ Format_RGB32
Definition qimage.h:46
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
Definition qimage.cpp:1678
\inmodule QtGui
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
qreal m21() const
Returns the horizontal shearing factor.
Definition qtransform.h:211
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
qreal m12() const
Returns the vertical shearing factor.
Definition qtransform.h:203
qreal dx() const
Returns the horizontal translation factor.
Definition qtransform.h:235
qreal m11() const
Returns the horizontal scaling factor.
Definition qtransform.h:199
qreal m22() const
Returns the vertical scaling factor.
Definition qtransform.h:215
QString stringValue(QStringView subKey) const
Font database for Windows.
Windows font engine using Direct Write.
void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override
void setUniqueFamilyName(const QString &newName)
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.
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override
QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &, const QTransform &matrix, GlyphFormat) override
void initFontInfo(const QFontDef &request, int dpi)
QFontEngine * cloneWithSize(qreal pixelSize) const override
glyph_t glyphIndex(uint ucs4) const override
static QString fontNameSubstitute(const QString &familyName)
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override
QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace, qreal pixelSize, const QSharedPointer< QWindowsFontEngineData > &d)
QImage alphaRGBMapForGlyph(glyph_t t, const QFixedPoint &subPixelPosition, const QTransform &xform) override
QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags) override
int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override
QString str
[2]
QPixmap p2
QSet< QString >::iterator it
rect
[4]
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
void * HANDLE
@ WindingFill
@ OddEvenFill
Definition image.cpp:4
#define QT_WARNING_DISABLE_CLANG(text)
#define qApp
AudioChannelLayoutTag tag
static const QCssKnownValue positions[NumKnownPositionModes - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char * destination
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
#define qCDebug(category,...)
return ret
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum fillMode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum GLuint GLenum GLsizei length
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLenum src
GLenum GLuint buffer
GLint GLsizei width
GLuint color
[2]
GLenum GLenum dst
GLbitfield flags
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLint y
GLuint GLenum GLenum transform
GLfixed GLfixed GLint GLint GLfixed points
GLuint GLuint * names
GLuint GLenum matrix
GLdouble GLdouble t
Definition qopenglext.h:243
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLsizei void * table
static const QRectF boundingRect(const QPointF *points, int pointCount)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr int qGray(int r, int g, int b)
Definition qrgb.h:36
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
unsigned int glyph_t
#define Q_UNUSED(x)
unsigned char uchar
Definition qtypes.h:32
unsigned short quint16
Definition qtypes.h:48
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
IUIViewSettingsInterop __RPC__in REFIID riid
long HRESULT
static UUID uuidIdWriteLocalFontFileLoader()
IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader
#define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE)
static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE renderMode)
MyCustomStruct c2
QNetworkRequest request(url)
QFixed x
Definition qfixed_p.h:162
static constexpr QFixed fromReal(qreal r)
Definition qfixed_p.h:35
constexpr int toInt() const
Definition qfixed_p.h:41
constexpr qreal toReal() const
Definition qfixed_p.h:42
uint hintingPreference
Definition qfont_p.h:67
uint stretch
Definition qfont_p.h:65
uint styleStrategy
Definition qfont_p.h:64
qreal pixelSize
Definition qfont_p.h:61
QString styleName
Definition qfont_p.h:55
qreal pointSize
Definition qfont_p.h:60
QMap< QFont::Tag, float > variableAxes
The QFont::Tag type provides access to advanced font features.
Definition qfont.h:215
QFixed effectiveAdvance(int item) const
glyph_t * glyphs
QFixed * advances