Qt 6.x
The Qt SDK
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/private/qhighdpiscaling_p.h>
16#include <QtGui/qpainterpath.h>
17
18#include <dwrite_2.h>
19
20#include <d2d1.h>
21
23
24// Clang does not consider __declspec(nothrow) as nothrow
25QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec")
26
27// Convert from design units to logical pixels
28#define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE) \
29 QFixed::fromReal((qreal(DESIGN_UNIT_VALUE) / qreal(m_unitsPerEm)) * fontDef.pixelSize)
30
31namespace {
32
33 class GeometrySink: public IDWriteGeometrySink
34 {
35 Q_DISABLE_COPY_MOVE(GeometrySink)
36 public:
37 GeometrySink(QPainterPath *path)
38 : m_refCount(0), m_path(path)
39 {
40 Q_ASSERT(m_path != 0);
41 }
42 virtual ~GeometrySink() = default;
43
44 IFACEMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *beziers, UINT bezierCount) override;
45 IFACEMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointCount) override;
46 IFACEMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) override;
47 IFACEMETHOD(Close)() override;
48 IFACEMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd) override;
49 IFACEMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode) override;
50 IFACEMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags) override;
51
52 IFACEMETHOD_(unsigned long, AddRef)() override;
53 IFACEMETHOD_(unsigned long, Release)() override;
54 IFACEMETHOD(QueryInterface)(IID const &riid, void **ppvObject) override;
55
56 private:
57 inline static QPointF fromD2D1_POINT_2F(const D2D1_POINT_2F &inp)
58 {
59 return QPointF(inp.x, inp.y);
60 }
61
62 unsigned long m_refCount;
63 QPointF m_startPoint;
64 QPainterPath *m_path;
65 };
66
67 void GeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers,
68 UINT bezierCount) noexcept
69 {
70 for (uint i=0; i<bezierCount; ++i) {
71 QPointF c1 = fromD2D1_POINT_2F(beziers[i].point1);
72 QPointF c2 = fromD2D1_POINT_2F(beziers[i].point2);
73 QPointF p2 = fromD2D1_POINT_2F(beziers[i].point3);
74
75 m_path->cubicTo(c1, c2, p2);
76 }
77 }
78
79 void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) noexcept
80 {
81 for (uint i=0; i<pointsCount; ++i)
82 m_path->lineTo(fromD2D1_POINT_2F(points[i]));
83 }
84
85 void GeometrySink::BeginFigure(D2D1_POINT_2F startPoint,
86 D2D1_FIGURE_BEGIN /*figureBegin*/) noexcept
87 {
88 m_startPoint = fromD2D1_POINT_2F(startPoint);
89 m_path->moveTo(m_startPoint);
90 }
91
92 IFACEMETHODIMP GeometrySink::Close() noexcept
93 {
94 return E_NOTIMPL;
95 }
96
97 void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) noexcept
98 {
99 if (figureEnd == D2D1_FIGURE_END_CLOSED)
100 m_path->closeSubpath();
101 }
102
103 void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) noexcept
104 {
105 m_path->setFillRule(fillMode == D2D1_FILL_MODE_ALTERNATE
108 }
109
110 void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/) noexcept
111 {
112 /* Not implemented */
113 }
114
115 IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef() noexcept
116 {
117 return InterlockedIncrement(&m_refCount);
118 }
119
120 IFACEMETHODIMP_(unsigned long) GeometrySink::Release() noexcept
121 {
122 unsigned long newCount = InterlockedDecrement(&m_refCount);
123 if (newCount == 0)
124 {
125 delete this;
126 return 0;
127 }
128
129 return newCount;
130 }
131
132 IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject) noexcept
133 {
134 if (__uuidof(IDWriteGeometrySink) == riid) {
135 *ppvObject = this;
136 } else if (__uuidof(IUnknown) == riid) {
137 *ppvObject = this;
138 } else {
139 *ppvObject = NULL;
140 return E_FAIL;
141 }
142
143 AddRef();
144 return S_OK;
145 }
146
147}
148
149static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE renderMode)
150{
151 switch (renderMode) {
152 case DWRITE_RENDERING_MODE_GDI_CLASSIC:
153 return DWRITE_MEASURING_MODE_GDI_CLASSIC;
154 case DWRITE_RENDERING_MODE_GDI_NATURAL:
155 return DWRITE_MEASURING_MODE_GDI_NATURAL;
156 default:
157 return DWRITE_MEASURING_MODE_NATURAL;
158 }
159}
160
161static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef)
162{
164 if (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting) {
165 // Microsoft documentation recommends using asymmetric rendering for small fonts
166 // at pixel size 16 and less, and symmetric for larger fonts.
167 hintingPreference = fontDef.pixelSize > 16.0
170 }
171
172 switch (hintingPreference) {
174 return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
176 return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
177 default:
178 return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC;
179 }
180}
181
195 qreal pixelSize,
197 : QFontEngine(DirectWrite)
198 , m_fontEngineData(d)
199 , m_directWriteFontFace(directWriteFontFace)
200 , m_directWriteBitmapRenderTarget(0)
201 , m_lineThickness(-1)
202 , m_unitsPerEm(-1)
203 , m_capHeight(-1)
204 , m_xHeight(-1)
205{
206 qCDebug(lcQpaFonts) << __FUNCTION__ << pixelSize;
207
208 Q_ASSERT(m_directWriteFontFace);
209
210 m_fontEngineData->directWriteFactory->AddRef();
211 m_directWriteFontFace->AddRef();
212
213 fontDef.pixelSize = pixelSize;
214 collectMetrics();
215 cache_cost = (m_ascent.toInt() + m_descent.toInt()) * m_xHeight.toInt() * 2000;
216}
217
219{
220 qCDebug(lcQpaFonts) << __FUNCTION__;
221
222 m_fontEngineData->directWriteFactory->Release();
223 m_directWriteFontFace->Release();
224
225 if (m_directWriteBitmapRenderTarget != 0)
226 m_directWriteBitmapRenderTarget->Release();
227
228 if (!m_uniqueFamilyName.isEmpty()) {
230 static_cast<QWindowsFontDatabase *>(pfdb)->derefUniqueFont(m_uniqueFamilyName);
231 }
232}
233
234#ifndef Q_CC_MINGW
235typedef IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader;
236
238{
239 return __uuidof(IDWriteLocalFontFileLoader);
240}
241#else // !Q_CC_MINGW
242DECLARE_INTERFACE_(QIdWriteLocalFontFileLoader, IDWriteFontFileLoader)
243{
244 STDMETHOD(GetFilePathLengthFromKey)(THIS_ void const *, UINT32, UINT32*) PURE;
245 STDMETHOD(GetFilePathFromKey)(THIS_ void const *, UINT32, WCHAR *, UINT32) PURE;
246 STDMETHOD(GetLastWriteTimeFromKey)(THIS_ void const *, UINT32, FILETIME *) PURE;
247};
248
250{
251 static const UUID result = { 0xb2d9f3ec, 0xc9fe, 0x4a11, {0xa2, 0xec, 0xd8, 0x62, 0x8, 0xf7, 0xc0, 0xa2}};
252 return result;
253}
254#endif // Q_CC_MINGW
255
256QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fontFile)
257{
258 IDWriteFontFileLoader *loader = nullptr;
259
260 HRESULT hr = fontFile->GetLoader(&loader);
261 if (FAILED(hr)) {
262 qErrnoWarning("%s: GetLoader failed", __FUNCTION__);
263 return QString();
264 }
265
266 QIdWriteLocalFontFileLoader *localLoader = nullptr;
267 hr = loader->QueryInterface(uuidIdWriteLocalFontFileLoader(),
268 reinterpret_cast<void **>(&localLoader));
269
270 const void *fontFileReferenceKey = nullptr;
271 UINT32 fontFileReferenceKeySize = 0;
272 if (SUCCEEDED(hr)) {
273 hr = fontFile->GetReferenceKey(&fontFileReferenceKey,
274 &fontFileReferenceKeySize);
275 if (FAILED(hr))
276 qErrnoWarning(hr, "%s: GetReferenceKey failed", __FUNCTION__);
277 }
278
279 UINT32 filePathLength = 0;
280 if (SUCCEEDED(hr)) {
281 hr = localLoader->GetFilePathLengthFromKey(fontFileReferenceKey,
282 fontFileReferenceKeySize,
283 &filePathLength);
284 if (FAILED(hr))
285 qErrnoWarning(hr, "GetFilePathLength failed", __FUNCTION__);
286 }
287
288 QString ret;
289 if (SUCCEEDED(hr) && filePathLength > 0) {
290 QVarLengthArray<wchar_t> filePath(filePathLength + 1);
291
292 hr = localLoader->GetFilePathFromKey(fontFileReferenceKey,
293 fontFileReferenceKeySize,
294 filePath.data(),
295 filePathLength + 1);
296 if (FAILED(hr))
297 qErrnoWarning(hr, "%s: GetFilePathFromKey failed", __FUNCTION__);
298 else
299 ret = QString::fromWCharArray(filePath.data());
300 }
301
302 if (localLoader != nullptr)
303 localLoader->Release();
304
305 if (loader != nullptr)
306 loader->Release();
307 return ret;
308}
309
311{
312 if (m_fontEngineData == nullptr || m_directWriteFontFace == nullptr)
313 return NULL;
314
315 LOGFONT lf;
316 HRESULT hr = m_fontEngineData->directWriteGdiInterop->ConvertFontFaceToLOGFONT(m_directWriteFontFace,
317 &lf);
318 if (SUCCEEDED(hr)) {
319 lf.lfHeight = -qRound(fontDef.pixelSize);
320 return CreateFontIndirect(&lf);
321 } else {
322 return NULL;
323 }
324}
325
327{
328 DWRITE_FONT_METRICS metrics;
329 m_directWriteFontFace->GetMetrics(&metrics);
330
334
336}
337
338void QWindowsFontEngineDirectWrite::collectMetrics()
339{
340 DWRITE_FONT_METRICS metrics;
341
342 m_directWriteFontFace->GetMetrics(&metrics);
343 m_unitsPerEm = metrics.designUnitsPerEm;
344
345 m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness);
346 m_capHeight = DESIGN_TO_LOGICAL(metrics.capHeight);
347 m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight);
348 m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition);
349
350 IDWriteFontFile *fontFile = nullptr;
351 UINT32 numberOfFiles = 1;
352 if (SUCCEEDED(m_directWriteFontFace->GetFiles(&numberOfFiles, &fontFile))) {
353 m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile));
354 fontFile->Release();
355 }
356
357 QByteArray table = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
358 const int advanceWidthMaxLocation = 10;
359 if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) {
360 quint16 advanceWidthMax = qFromBigEndian<quint16>(table.constData() + advanceWidthMaxLocation);
361 m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax);
362 }
363}
364
366{
367 if (m_underlinePosition > 0)
368 return m_underlinePosition;
369 else
371}
372
374{
375 if (m_lineThickness > 0)
376 return m_lineThickness;
377 else
379}
380
382{
383 bool ret = false;
384
385 const void *tableData = 0;
386 UINT32 tableSize;
387 void *tableContext = 0;
388 BOOL exists;
389 HRESULT hr = m_directWriteFontFace->TryGetFontTable(qbswap<quint32>(tag),
390 &tableData, &tableSize,
391 &tableContext, &exists);
392 if (SUCCEEDED(hr)) {
393 if (exists) {
394 ret = true;
395 if (buffer && *length >= tableSize)
396 memcpy(buffer, tableData, tableSize);
397 *length = tableSize;
398 Q_ASSERT(int(*length) > 0);
399 }
400 m_directWriteFontFace->ReleaseFontTable(tableContext);
401 } else {
402 qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__);
403 }
404
405 return ret;
406}
407
409{
410 if (m_unitsPerEm > 0)
411 return m_unitsPerEm;
412 else
414}
415
417{
418 UINT16 glyphIndex;
419
420 HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(&ucs4, 1, &glyphIndex);
421 if (FAILED(hr)) {
422 qErrnoWarning("%s: glyphIndex failed", __FUNCTION__);
423 glyphIndex = 0;
424 }
425
426 return glyphIndex;
427}
428
430 int *nglyphs, QFontEngine::ShaperFlags flags) const
431{
432 Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
433 if (*nglyphs < len) {
434 *nglyphs = len;
435 return false;
436 }
437
438 QVarLengthArray<UINT32> codePoints(len);
439 int actualLength = 0;
441 while (it.hasNext())
442 codePoints[actualLength++] = it.next();
443
444 QVarLengthArray<UINT16> glyphIndices(actualLength);
445 HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength,
446 glyphIndices.data());
447 if (FAILED(hr)) {
448 qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
449 return false;
450 }
451
452 for (int i = 0; i < actualLength; ++i)
453 glyphs->glyphs[i] = glyphIndices.at(i);
454
455 *nglyphs = actualLength;
456 glyphs->numGlyphs = actualLength;
457
458 if (!(flags & GlyphIndicesOnly))
459 recalcAdvances(glyphs, {});
460
461 return true;
462}
463
465{
466 return m_faceId;
467}
468
469void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
470{
471 QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
472
473 // ### Caching?
474 for(int i=0; i<glyphs->numGlyphs; i++)
475 glyphIndices[i] = UINT16(glyphs->glyphs[i]);
476
477 QVarLengthArray<DWRITE_GLYPH_METRICS> glyphMetrics(glyphIndices.size());
478
479 HRESULT hr;
480 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
481 if (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL) {
482 hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
483 1.0f,
484 NULL,
485 TRUE,
486 glyphIndices.data(),
487 glyphIndices.size(),
488 glyphMetrics.data());
489 } else {
490 hr = m_directWriteFontFace->GetDesignGlyphMetrics(glyphIndices.data(),
491 glyphIndices.size(),
492 glyphMetrics.data());
493 }
494 if (SUCCEEDED(hr)) {
495 qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0;
496 for (int i = 0; i < glyphs->numGlyphs; ++i)
497 glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth * stretch);
498 } else {
499 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
500 }
501}
502
505 glyph_metrics_t *metric)
506{
507 float advance = 0.0f;
508 UINT16 g = glyph;
509 DWRITE_GLYPH_OFFSET offset;
510 offset.advanceOffset = 0;
511 offset.ascenderOffset = 0;
512 GeometrySink geometrySink(path);
513 HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(m_unitsPerEm,
514 &g,
515 &advance,
516 &offset,
517 1,
518 false,
519 false,
520 &geometrySink);
521 if (FAILED(hr)) {
522 qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
523 return;
524 }
525
526 DWRITE_GLYPH_METRICS glyphMetrics;
527 hr = m_directWriteFontFace->GetDesignGlyphMetrics(&g, 1, &glyphMetrics);
528 if (FAILED(hr)) {
529 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
530 return;
531 }
532
533 QFixed advanceWidth = QFixed(int(glyphMetrics.advanceWidth));
534 QFixed leftSideBearing = QFixed(glyphMetrics.leftSideBearing);
535 QFixed rightSideBearing = QFixed(glyphMetrics.rightSideBearing);
536 QFixed advanceHeight = QFixed(int(glyphMetrics.advanceHeight));
537 QFixed verticalOriginY = QFixed(glyphMetrics.verticalOriginY);
538 QFixed topSideBearing = QFixed(glyphMetrics.topSideBearing);
539 QFixed bottomSideBearing = QFixed(glyphMetrics.bottomSideBearing);
540 QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
541 QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
542 *metric = glyph_metrics_t(leftSideBearing,
543 -verticalOriginY + topSideBearing,
544 width,
545 height,
546 advanceWidth,
547 0);
548}
549
551 QPainterPath *path, QTextItem::RenderFlags flags)
552{
554 QVarLengthArray<UINT16> glyphIndices(nglyphs);
555 QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(nglyphs);
556 QVarLengthArray<FLOAT> glyphAdvances(nglyphs);
557
558 for (int i=0; i<nglyphs; ++i) {
559 glyphIndices[i] = glyphs[i];
560 glyphOffsets[i].advanceOffset = positions[i].x.toReal();
561 glyphOffsets[i].ascenderOffset = -positions[i].y.toReal();
562 glyphAdvances[i] = 0.0;
563 }
564
565 GeometrySink geometrySink(path);
566 HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(
568 glyphIndices.data(),
569 glyphAdvances.data(),
570 glyphOffsets.data(),
571 nglyphs,
572 false,
573 false,
574 &geometrySink
575 );
576
577 if (FAILED(hr))
578 qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
579}
580
582{
583 if (glyphs.numGlyphs == 0)
584 return glyph_metrics_t();
585 QFixed w = 0;
586 for (int i = 0; i < glyphs.numGlyphs; ++i)
587 w += glyphs.effectiveAdvance(i);
588
589 const QFixed leftBearing = firstLeftBearing(glyphs);
590 return glyph_metrics_t(leftBearing, -ascent(), w - leftBearing - lastRightBearing(glyphs),
591 ascent() + descent(), w, 0);
592}
593
595{
596 UINT16 glyphIndex = g;
597
598 DWRITE_GLYPH_METRICS glyphMetrics;
599 HRESULT hr = m_directWriteFontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics);
600 if (SUCCEEDED(hr)) {
601 QFixed advanceWidth = DESIGN_TO_LOGICAL(glyphMetrics.advanceWidth);
602 QFixed leftSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.leftSideBearing);
603 QFixed rightSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.rightSideBearing);
604 QFixed advanceHeight = DESIGN_TO_LOGICAL(glyphMetrics.advanceHeight);
605 QFixed verticalOriginY = DESIGN_TO_LOGICAL(glyphMetrics.verticalOriginY);
606 QFixed topSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.topSideBearing);
607 QFixed bottomSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.bottomSideBearing);
608 QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
609 QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
610 return glyph_metrics_t(leftSideBearing,
611 -verticalOriginY + topSideBearing,
612 width,
613 height,
614 advanceWidth,
615 0);
616 } else {
617 qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
618 }
619
620 return glyph_metrics_t();
621}
622
624{
625 if (m_capHeight <= 0)
626 return calculatedCapHeight();
627
628 return m_capHeight;
629}
630
632{
633 return m_xHeight;
634}
635
637{
638 return m_maxAdvanceWidth.toReal();
639}
640
642 const QFixedPoint &subPixelPosition,
643 const QTransform &t)
644{
645 QImage im = imageForGlyph(glyph, subPixelPosition, glyphMargin(Format_A8), t);
646
647 QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
648
649 for (int y=0; y<im.height(); ++y) {
650 const uint *src = reinterpret_cast<const uint *>(im.constScanLine(y));
651 uchar *dst = alphaMap.scanLine(y);
652 for (int x=0; x<im.width(); ++x) {
653 *dst = 255 - (m_fontEngineData->pow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.);
654 ++dst;
655 ++src;
656 }
657 }
658
659 return alphaMap;
660}
661
663 const QFixedPoint &subPixelPosition)
664{
665 return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
666}
667
669{
670 return true;
671}
672
674{
675 IDWriteFontFace2 *directWriteFontFace2;
676 if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
677 reinterpret_cast<void **>(&directWriteFontFace2)))) {
678 DWRITE_FONT_METRICS1 metrics;
679 directWriteFontFace2->GetMetrics(&metrics);
680
682 p.emSquare = metrics.designUnitsPerEm;
683 p.boundingBox = QRectF(metrics.glyphBoxLeft,
684 -metrics.glyphBoxTop,
685 metrics.glyphBoxRight - metrics.glyphBoxLeft,
686 metrics.glyphBoxTop - metrics.glyphBoxBottom);
687 p.ascent = metrics.ascent;
688 p.descent = metrics.descent;
689 p.leading = metrics.lineGap;
690 p.capHeight = metrics.capHeight;
691 p.lineWidth = metrics.underlineThickness;
692
693 directWriteFontFace2->Release();
694 return p;
695 } else {
697 }
698}
699
700QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
701 const QFixedPoint &subPixelPosition,
702 int margin,
703 const QTransform &originalTransform,
704 const QColor &color)
705{
706 UINT16 glyphIndex = t;
707 FLOAT glyphAdvance = 0;
708
709 DWRITE_GLYPH_OFFSET glyphOffset;
710 glyphOffset.advanceOffset = 0;
711 glyphOffset.ascenderOffset = 0;
712
713 DWRITE_GLYPH_RUN glyphRun;
714 glyphRun.fontFace = m_directWriteFontFace;
715 glyphRun.fontEmSize = fontDef.pixelSize;
716 glyphRun.glyphCount = 1;
717 glyphRun.glyphIndices = &glyphIndex;
718 glyphRun.glyphAdvances = &glyphAdvance;
719 glyphRun.isSideways = false;
720 glyphRun.bidiLevel = 0;
721 glyphRun.glyphOffsets = &glyphOffset;
722
723 QTransform xform = originalTransform;
725 xform.scale(fontDef.stretch / 100.0, 1.0);
726
727 DWRITE_MATRIX transform;
728 transform.dx = subPixelPosition.x.toReal();
729 transform.dy = 0;
730 transform.m11 = xform.m11();
731 transform.m12 = xform.m12();
732 transform.m21 = xform.m21();
733 transform.m22 = xform.m22();
734
735 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
736 DWRITE_MEASURING_MODE measureMode =
737 renderModeToMeasureMode(renderMode);
738
739 DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
740 ? DWRITE_GRID_FIT_MODE_DISABLED
741 : DWRITE_GRID_FIT_MODE_DEFAULT;
742
743 IDWriteFactory2 *factory2 = nullptr;
744 HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
745 reinterpret_cast<void **>(&factory2));
746 IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
747 if (!SUCCEEDED(hr)) {
748 qErrnoWarning(hr, "%s: Failed to query IDWriteFactory2 interface.", __FUNCTION__);
749 hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
750 &glyphRun,
751 1.0f,
752 &transform,
753 renderMode,
754 measureMode,
755 0.0, 0.0,
756 &glyphAnalysis
757 );
758 } else {
759 hr = factory2->CreateGlyphRunAnalysis(
760 &glyphRun,
761 &transform,
762 renderMode,
763 measureMode,
764 gridFitMode,
765 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
766 0.0, 0.0,
767 &glyphAnalysis
768 );
769 }
770
771 if (SUCCEEDED(hr)) {
772 RECT rect;
773 glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
774
775 if (rect.top == rect.bottom || rect.left == rect.right)
776 return QImage();
777
778 QRect boundingRect = QRect(QPoint(rect.left - margin,
779 rect.top - margin),
780 QPoint(rect.right + margin,
781 rect.bottom + margin));
782
783
784 const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect
785 const int height = boundingRect.height() - 1;
786
788 HRESULT hr = DWRITE_E_NOCOLOR;
789 IDWriteColorGlyphRunEnumerator *enumerator = 0;
790 if (glyphFormat == QFontEngine::Format_ARGB && factory2 != nullptr) {
791 hr = factory2->TranslateColorGlyphRun(0.0f,
792 0.0f,
793 &glyphRun,
794 NULL,
795 measureMode,
796 NULL,
797 0,
798 &enumerator);
800 image.fill(0);
801 } else {
803 image.fill(0xffffffff);
804 }
805
806 BOOL ok = true;
807
808 if (SUCCEEDED(hr)) {
809 while (SUCCEEDED(hr) && ok) {
810 const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0;
811 hr = enumerator->GetCurrentRun(&colorGlyphRun);
812 if (FAILED(hr)) { // No colored runs, only outline
813 qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::GetCurrentRun failed", __FUNCTION__);
814 break;
815 }
816
817 IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL;
818 hr = factory2->CreateGlyphRunAnalysis(
819 &colorGlyphRun->glyphRun,
820 &transform,
821 renderMode,
822 measureMode,
823 gridFitMode,
824 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
825 0.0, 0.0,
826 &colorGlyphsAnalysis
827 );
828
829 if (FAILED(hr)) {
830 qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__);
831 break;
832 }
833
834 float r, g, b, a;
835 if (colorGlyphRun->paletteIndex == 0xFFFF) {
836 r = float(color.redF());
837 g = float(color.greenF());
838 b = float(color.blueF());
839 a = float(color.alphaF());
840 } else {
841 r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f);
842 g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f);
843 b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f);
844 a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f);
845 }
846
847 if (!qFuzzyIsNull(a)) {
848 renderGlyphRun(&image,
849 r,
850 g,
851 b,
852 a,
853 colorGlyphsAnalysis,
855 }
856 colorGlyphsAnalysis->Release();
857
858 hr = enumerator->MoveNext(&ok);
859 if (FAILED(hr)) {
860 qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::MoveNext failed", __FUNCTION__);
861 break;
862 }
863 }
864 } else {
865 float r, g, b, a;
867 r = float(color.redF());
868 g = float(color.greenF());
869 b = float(color.blueF());
870 a = float(color.alphaF());
871 } else {
872 r = g = b = a = 0.0;
873 }
874
875 renderGlyphRun(&image,
876 r,
877 g,
878 b,
879 a,
880 glyphAnalysis,
882 }
883
884 glyphAnalysis->Release();
885 return image;
886 } else {
887 qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed", __FUNCTION__);
888 return QImage();
889 }
890}
891
892
893void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
894 float r,
895 float g,
896 float b,
897 float a,
898 IDWriteGlyphRunAnalysis *glyphAnalysis,
899 const QRect &boundingRect)
900{
901 const int width = destination->width();
902 const int height = destination->height();
903
904 r *= 255.0;
905 g *= 255.0;
906 b *= 255.0;
907
908 const int size = width * height * 3;
909 if (size > 0) {
910 RECT rect;
911 rect.left = boundingRect.left();
912 rect.top = boundingRect.top();
913 rect.right = boundingRect.right();
914 rect.bottom = boundingRect.bottom();
915
916 QVarLengthArray<BYTE, 1024> alphaValueArray(size);
917 BYTE *alphaValues = alphaValueArray.data();
918 memset(alphaValues, 0, size);
919
920 HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
921 &rect,
922 alphaValues,
923 size);
924 if (SUCCEEDED(hr)) {
925 if (destination->hasAlphaChannel()) {
926 for (int y = 0; y < height; ++y) {
927 uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
928 BYTE *src = alphaValues + width * 3 * y;
929
930 for (int x = 0; x < width; ++x) {
931 float redAlpha = a * *src++ / 255.0;
932 float greenAlpha = a * *src++ / 255.0;
933 float blueAlpha = a * *src++ / 255.0;
934 float averageAlpha = (redAlpha + greenAlpha + blueAlpha) / 3.0;
935
936 QRgb currentRgb = dest[x];
937 dest[x] = qRgba(qRound(qRed(currentRgb) * (1.0 - averageAlpha) + averageAlpha * r),
938 qRound(qGreen(currentRgb) * (1.0 - averageAlpha) + averageAlpha * g),
939 qRound(qBlue(currentRgb) * (1.0 - averageAlpha) + averageAlpha * b),
940 qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
941 }
942 }
943
944 } else {
945 for (int y = 0; y < height; ++y) {
946 uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
947 BYTE *src = alphaValues + width * 3 * y;
948
949 for (int x = 0; x < width; ++x) {
950 dest[x] = *(src + 0) << 16
951 | *(src + 1) << 8
952 | *(src + 2);
953
954 src += 3;
955 }
956 }
957 }
958 } else {
959 qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
960 }
961 } else {
962 glyphAnalysis->Release();
963 qWarning("%s: Glyph has no bounds", __FUNCTION__);
964 }
965}
966
968 const QFixedPoint &subPixelPosition,
969 const QTransform &xform)
970{
971 QImage mask = imageForGlyph(t,
972 subPixelPosition,
974 xform);
975
976 return mask.depth() == 32
977 ? mask
978 : mask.convertToFormat(QImage::Format_RGB32);
979}
980
982{
983 QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace,
984 pixelSize,
985 m_fontEngineData);
986
987 fontEngine->fontDef = fontDef;
988 fontEngine->fontDef.pixelSize = pixelSize;
989 if (!m_uniqueFamilyName.isEmpty()) {
990 fontEngine->setUniqueFamilyName(m_uniqueFamilyName);
992 static_cast<QWindowsFontDatabase *>(pfdb)->refUniqueFont(m_uniqueFamilyName);
993 }
994
995 return fontEngine;
996}
997
999{
1000 return m_directWriteFontFace;
1001}
1002
1004 int dpi)
1005{
1006 fontDef = request;
1007
1008 if (fontDef.pointSize < 0)
1009 fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
1010 else if (fontDef.pixelSize == -1)
1011 fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.);
1012}
1013
1015{
1016 const QString substitute =
1017 QWinRegistryKey(HKEY_LOCAL_MACHINE,
1018 LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)")
1019 .stringValue(familyName);
1020 return substitute.isEmpty() ? familyName : substitute;
1021}
1022
1024 const QFixedPoint &subPixelPosition,
1025 const QTransform &originalTransform,
1026 GlyphFormat format)
1027{
1029
1030 QTransform matrix = originalTransform;
1032 matrix.scale(fontDef.stretch / 100.0, 1.0);
1033
1034 glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance
1035
1036 UINT16 glyphIndex = glyph;
1037 FLOAT glyphAdvance = 0;
1038
1039 DWRITE_GLYPH_OFFSET glyphOffset;
1040 glyphOffset.advanceOffset = 0;
1041 glyphOffset.ascenderOffset = 0;
1042
1043 DWRITE_GLYPH_RUN glyphRun;
1044 glyphRun.fontFace = m_directWriteFontFace;
1045 glyphRun.fontEmSize = fontDef.pixelSize;
1046 glyphRun.glyphCount = 1;
1047 glyphRun.glyphIndices = &glyphIndex;
1048 glyphRun.glyphAdvances = &glyphAdvance;
1049 glyphRun.isSideways = false;
1050 glyphRun.bidiLevel = 0;
1051 glyphRun.glyphOffsets = &glyphOffset;
1052
1053 DWRITE_MATRIX transform;
1054 transform.dx = subPixelPosition.x.toReal();
1055 transform.dy = 0;
1056 transform.m11 = matrix.m11();
1057 transform.m12 = matrix.m12();
1058 transform.m21 = matrix.m21();
1059 transform.m22 = matrix.m22();
1060
1061 DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
1062 DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode);
1063 DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
1064 ? DWRITE_GRID_FIT_MODE_DISABLED
1065 : DWRITE_GRID_FIT_MODE_DEFAULT;
1066
1067 IDWriteFactory2 *factory2 = nullptr;
1068 HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
1069 reinterpret_cast<void **>(&factory2));
1070
1071 IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
1072 if (SUCCEEDED(hr)) {
1073 hr = factory2->CreateGlyphRunAnalysis(
1074 &glyphRun,
1075 &transform,
1076 renderMode,
1077 measureMode,
1078 gridFitMode,
1079 DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1080 0.0, 0.0,
1081 &glyphAnalysis
1082 );
1083 } else {
1084 hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
1085 &glyphRun,
1086 1.0f,
1087 &transform,
1088 renderMode,
1089 measureMode,
1090 0.0, 0.0,
1091 &glyphAnalysis
1092 );
1093 }
1094
1095 if (SUCCEEDED(hr)) {
1096 RECT rect;
1097 glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
1098 glyphAnalysis->Release();
1099
1100 int margin = glyphMargin(format);
1101
1102 if (rect.left == rect.right || rect.top == rect.bottom)
1103 return glyph_metrics_t();
1104
1105 return glyph_metrics_t(rect.left,
1106 rect.top,
1107 rect.right - rect.left + margin * 2,
1108 rect.bottom - rect.top + margin * 2,
1109 bbox.xoff, bbox.yoff);
1110 } else {
1111 return glyph_metrics_t();
1112 }
1113}
1114
1116 const QFixedPoint &subPixelPosition,
1117 const QTransform &t,
1118 const QColor &color)
1119{
1120 return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_ARGB), t, color);
1121}
1122
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qchar.h:48
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
QFixed calculatedCapHeight() const
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:52
@ PreferNoHinting
Definition qfont.h:54
@ PreferVerticalHinting
Definition qfont.h:55
@ PreferDefaultHinting
Definition qfont.h:53
@ AnyStretch
Definition qfont.h:81
static QPlatformIntegration * platformIntegration()
static bool isActive()
\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
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:1657
\inmodule QtGui
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
virtual QPlatformFontDatabase * fontDatabase() const
Accessor for the platform integration's fontdatabase.
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:499
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:496
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:497
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:498
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
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
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 m11() const
Returns the horizontal scaling factor.
Definition qtransform.h:199
qreal m22() const
Returns the vertical scaling factor.
Definition qtransform.h:215
constexpr size_type size() const noexcept
const T & at(qsizetype idx) const
T * data() noexcept
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
bool 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)
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
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
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
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
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
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 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:27
unsigned short quint16
Definition qtypes.h:43
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
IUIViewSettingsInterop __RPC__in REFIID riid
long HRESULT
static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef)
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
constexpr int toInt() const
Definition qfixed_p.h:41
constexpr qreal toReal() const
Definition qfixed_p.h:42
uint hintingPreference
Definition qfont_p.h:66
uint stretch
Definition qfont_p.h:64
qreal pixelSize
Definition qfont_p.h:60
qreal pointSize
Definition qfont_p.h:59
QFixed effectiveAdvance(int item) const
glyph_t * glyphs
QFixed * advances
virtual HRESULT STDMETHODCALLTYPE Close(void)=0