Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qwindowsfontdatabase.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
5#ifndef QT_NO_FREETYPE
6# include "qwindowsfontdatabase_ft_p.h" // for default font
7#endif
9#include <QtCore/qt_windows.h>
10
11#include <QtGui/QFont>
12#include <QtGui/QGuiApplication>
13#include <QtGui/private/qhighdpiscaling_p.h>
14#include <QtGui/private/qtgui-config_p.h>
15
16#include <QtCore/qmath.h>
17#include <QtCore/QDebug>
18#include <QtCore/QFile>
19#include <QtCore/QtEndian>
20#include <QtCore/QStandardPaths>
21#include <QtCore/private/qduplicatetracker_p.h>
22#include <QtCore/private/qwinregistry_p.h>
23
24#include <wchar.h>
25
26#if QT_CONFIG(directwrite)
27# if QT_CONFIG(directwrite3)
29# endif
30# include <dwrite_2.h>
31# include <d2d1.h>
33#endif
34
36
37using namespace Qt::StringLiterals;
38
39#if QT_CONFIG(directwrite)
40static inline bool useDirectWrite(QFont::HintingPreference hintingPreference,
41 const QString &familyName = QString(),
42 bool isColorFont = false)
43{
44 const unsigned options = QWindowsFontDatabase::fontOptions();
46 return false;
47
48 // At some scales, GDI will misrender the MingLiU font, so we force use of
49 // DirectWrite to work around the issue.
50 if (Q_UNLIKELY(familyName.startsWith("MingLiU"_L1)))
51 return true;
52
53 if (isColorFont)
54 return (options & QWindowsFontDatabase::DontUseColorFonts) == 0;
55
56 return hintingPreference == QFont::PreferNoHinting
57 || hintingPreference == QFont::PreferVerticalHinting
58 || (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting);
59}
60#endif // !QT_NO_DIRECTWRITE
61
70{
71 // from qapplication_win.cpp
72 UINT result = 0;
73 if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
74 clearTypeEnabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
75
76 const qreal gray_gamma = 2.31;
77 for (int i=0; i<256; ++i)
78 pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
79
80 HDC displayDC = GetDC(0);
81 hdc = CreateCompatibleDC(displayDC);
82 ReleaseDC(0, displayDC);
83}
84
85unsigned QWindowsFontDatabase::m_fontOptions = 0;
86
88{
89 m_fontOptions = options & (QWindowsFontDatabase::DontUseDirectWriteFonts |
91}
92
94{
95 return m_fontOptions;
96}
97
99{
100 int winSmooth;
101 qreal result = 1;
102 if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
103 result = qreal(winSmooth) / qreal(1000.0);
104
105 // Safeguard ourselves against corrupt registry values...
106 if (result > 5 || result < 1)
107 result = qreal(1.4);
108 return result;
109}
110
124#ifndef QT_NO_DEBUG_STREAM
126{
127 QDebugStateSaver saver(d);
128 d.nospace();
129 d.noquote();
130 d << "QFontDef(Family=\"" << def.families.first() << '"';
131 if (!def.styleName.isEmpty())
132 d << ", stylename=" << def.styleName;
133 d << ", pointsize=" << def.pointSize << ", pixelsize=" << def.pixelSize
134 << ", styleHint=" << def.styleHint << ", weight=" << def.weight
135 << ", stretch=" << def.stretch << ", hintingPreference="
136 << def.hintingPreference << ')';
137 return d;
138}
139
141{
142 d << "LOGFONT(\"" << QString::fromWCharArray(lf.lfFaceName)
143 << "\", lfWidth=" << lf.lfWidth << ", lfHeight=" << lf.lfHeight << ')';
144}
145
146QDebug operator<<(QDebug d, const LOGFONT &lf)
147{
148 QDebugStateSaver saver(d);
149 d.nospace();
150 d.noquote();
152 return d;
153}
154#endif // !QT_NO_DEBUG_STREAM
155
157{
158 switch (charSet) {
159 case ANSI_CHARSET:
160 case EASTEUROPE_CHARSET:
161 case BALTIC_CHARSET:
162 case TURKISH_CHARSET:
164 case GREEK_CHARSET:
166 case RUSSIAN_CHARSET:
168 case HEBREW_CHARSET:
170 case ARABIC_CHARSET:
172 case THAI_CHARSET:
173 return QFontDatabase::Thai;
174 case GB2312_CHARSET:
176 case CHINESEBIG5_CHARSET:
178 case SHIFTJIS_CHARSET:
180 case HANGUL_CHARSET:
181 case JOHAB_CHARSET:
183 case VIETNAMESE_CHARSET:
185 case SYMBOL_CHARSET:
187 default:
188 break;
189 }
190 return QFontDatabase::Any;
191}
192
193#ifdef MAKE_TAG
194#undef MAKE_TAG
195#endif
196// GetFontData expects the tags in little endian ;(
197#define MAKE_TAG(ch1, ch2, ch3, ch4) (\
198 (((quint32)(ch4)) << 24) | \
199 (((quint32)(ch3)) << 16) | \
200 (((quint32)(ch2)) << 8) | \
201 ((quint32)(ch1)) \
202 )
203
205{
206 const QChar *c = name.unicode();
207 for (int i = 0; i < name.length(); ++i) {
208 if (c[i].unicode() >= 0x100)
209 return true;
210 }
211 return false;
212}
213
214namespace {
215
216static QString readName(bool unicode, const uchar *string, int length)
217{
218 QString out;
219 if (unicode) {
220 // utf16
221
222 length /= 2;
223 out.resize(length);
224 QChar *uc = out.data();
225 for (int i = 0; i < length; ++i)
226 uc[i] = qt_getUShort(string + 2*i);
227 } else {
228 // Apple Roman
229
230 out.resize(length);
231 QChar *uc = out.data();
232 for (int i = 0; i < length; ++i)
233 uc[i] = QLatin1Char(char(string[i]));
234 }
235 return out;
236}
237
238enum FieldTypeValue {
239 FamilyId = 1,
240 StyleId = 2,
241 PreferredFamilyId = 16,
242 PreferredStyleId = 17,
243};
244
245enum PlatformFieldValue {
246 PlatformId_Unicode = 0,
247 PlatformId_Apple = 1,
248 PlatformId_Microsoft = 3
249};
250
252{
254 const int NameRecordSize = 12;
255 const int MS_LangIdEnglish = 0x009;
256
257 // get the name table
259 quint16 string_offset;
260 const unsigned char *names;
261
262 if (bytes < 8)
263 return out;
264
265 if (qt_getUShort(table) != 0)
266 return out;
267
268 count = qt_getUShort(table + 2);
269 string_offset = qt_getUShort(table + 4);
270 names = table + 6;
271
272 if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
273 return out;
274
275 enum PlatformIdType {
276 NotFound = 0,
277 Unicode = 1,
278 Apple = 2,
279 Microsoft = 3
280 };
281
282 PlatformIdType idStatus[4] = { NotFound, NotFound, NotFound, NotFound };
283 int ids[4] = { -1, -1, -1, -1 };
284
285 for (int i = 0; i < count; ++i) {
286 // search for the correct name entries
287
288 quint16 platform_id = qt_getUShort(names + i*NameRecordSize);
289 quint16 encoding_id = qt_getUShort(names + 2 + i*NameRecordSize);
290 quint16 language_id = qt_getUShort(names + 4 + i*NameRecordSize);
291 quint16 name_id = qt_getUShort(names + 6 + i*NameRecordSize);
292
293 PlatformIdType *idType = nullptr;
294 int *id = nullptr;
295
296 switch (name_id) {
297 case FamilyId:
298 idType = &idStatus[0];
299 id = &ids[0];
300 break;
301 case StyleId:
302 idType = &idStatus[1];
303 id = &ids[1];
304 break;
305 case PreferredFamilyId:
306 idType = &idStatus[2];
307 id = &ids[2];
308 break;
309 case PreferredStyleId:
310 idType = &idStatus[3];
311 id = &ids[3];
312 break;
313 default:
314 continue;
315 }
316
317 quint16 length = qt_getUShort(names + 8 + i*NameRecordSize);
318 quint16 offset = qt_getUShort(names + 10 + i*NameRecordSize);
319 if (DWORD(string_offset + offset + length) > bytes)
320 continue;
321
322 if ((platform_id == PlatformId_Microsoft
323 && (encoding_id == 0 || encoding_id == 1))
324 && ((language_id & 0x3ff) == MS_LangIdEnglish
325 || *idType < Microsoft)) {
326 *id = i;
327 *idType = Microsoft;
328 }
329 // not sure if encoding id 4 for Unicode is utf16 or ucs4...
330 else if (platform_id == PlatformId_Unicode && encoding_id < 4 && *idType < Unicode) {
331 *id = i;
332 *idType = Unicode;
333 }
334 else if (platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0 && *idType < Apple) {
335 *id = i;
336 *idType = Apple;
337 }
338 }
339
340 QString strings[4];
341 for (int i = 0; i < 4; ++i) {
342 if (idStatus[i] == NotFound)
343 continue;
344 int id = ids[i];
345 quint16 length = qt_getUShort(names + 8 + id * NameRecordSize);
346 quint16 offset = qt_getUShort(names + 10 + id * NameRecordSize);
347 const unsigned char *string = table + string_offset + offset;
348 strings[i] = readName(idStatus[i] != Apple, string, length);
349 }
350
351 out.name = strings[0];
352 out.style = strings[1];
353 out.preferredName = strings[2];
354 out.preferredStyle = strings[3];
355 return out;
356}
357
358} // namespace
359
360QString qt_getEnglishName(const QString &familyName, bool includeStyle)
361{
362 QString i18n_name;
363 QString faceName = familyName;
364 faceName.truncate(LF_FACESIZE - 1);
365
366 HDC hdc = GetDC( 0 );
367 LOGFONT lf;
368 memset(&lf, 0, sizeof(LOGFONT));
369 faceName.toWCharArray(lf.lfFaceName);
370 lf.lfFaceName[faceName.size()] = 0;
371 lf.lfCharSet = DEFAULT_CHARSET;
372 HFONT hfont = CreateFontIndirect(&lf);
373
374 if (!hfont) {
375 ReleaseDC(0, hdc);
376 return QString();
377 }
378
379 HGDIOBJ oldobj = SelectObject( hdc, hfont );
380
381 const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
382
383 // get the name table
384 unsigned char *table = 0;
385
386 DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 );
387 if ( bytes == GDI_ERROR ) {
388 // ### Unused variable
389 // int err = GetLastError();
390 goto error;
391 }
392
393 table = new unsigned char[bytes];
394 GetFontData(hdc, name_tag, 0, table, bytes);
395 if ( bytes == GDI_ERROR )
396 goto error;
397
398 {
400 i18n_name = names.name;
401 if (includeStyle)
402 i18n_name += u' ' + names.style;
403 }
404error:
405 delete [] table;
406 SelectObject( hdc, oldobj );
407 DeleteObject( hfont );
408 ReleaseDC( 0, hdc );
409
410 //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
411 return i18n_name;
412}
413
414// Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions.
416{
417 QFontNames fontNames;
418 HDC hdc = GetDC(0);
419 HFONT hfont = CreateFontIndirect(&lf);
420
421 if (!hfont) {
422 ReleaseDC(0, hdc);
423 return fontNames;
424 }
425
426 HGDIOBJ oldobj = SelectObject(hdc, hfont);
427
428 // get the name table
430 const DWORD name_tag = MAKE_TAG('n', 'a', 'm', 'e');
431 DWORD bytes = GetFontData(hdc, name_tag, 0, 0, 0);
432 if (bytes != GDI_ERROR) {
433 table.resize(bytes);
434
435 if (GetFontData(hdc, name_tag, 0, table.data(), bytes) != GDI_ERROR)
436 fontNames = qt_getCanonicalFontNames(reinterpret_cast<const uchar*>(table.constData()), bytes);
437 }
438
439 SelectObject(hdc, oldobj);
440 DeleteObject(hfont);
441 ReleaseDC(0, hdc);
442
443 return fontNames;
444}
445
446static QChar *createFontFile(const QString &faceName)
447{
448 QChar *faceNamePtr = nullptr;
449 if (!faceName.isEmpty()) {
450 const int nameLength = qMin(faceName.length(), LF_FACESIZE - 1);
451 faceNamePtr = new QChar[nameLength + 1];
452 memcpy(static_cast<void *>(faceNamePtr), faceName.data(), sizeof(wchar_t) * nameLength);
453 faceNamePtr[nameLength] = u'\0';
454 }
455 return faceNamePtr;
456}
457
458namespace {
459 struct StoreFontPayload {
460 StoreFontPayload(const QString &family,
461 QWindowsFontDatabase *fontDatabase)
462 : populatedFontFamily(family)
463 , windowsFontDatabase(fontDatabase)
464 {}
465
466 QString populatedFontFamily;
467 QDuplicateTracker<FontAndStyle> foundFontAndStyles;
468 QWindowsFontDatabase *windowsFontDatabase;
469 };
470}
471
472static bool addFontToDatabase(QString familyName,
473 QString styleName,
474 const LOGFONT &logFont,
475 const TEXTMETRIC *textmetric,
476 const FONTSIGNATURE *signature,
477 int type,
478 StoreFontPayload *sfp)
479{
480 // the "@family" fonts are just the same as "family". Ignore them.
481 if (familyName.isEmpty() || familyName.at(0) == u'@' || familyName.startsWith("WST_"_L1))
482 return false;
483
484 uchar charSet = logFont.lfCharSet;
485
486 static const int SMOOTH_SCALABLE = 0xffff;
487 const QString foundryName; // No such concept.
488 const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH);
489 const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE);
490 const bool unreliableTextMetrics = type == 0;
491 const bool scalable = (textmetric->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE))
492 && !unreliableTextMetrics;
493 const int size = scalable ? SMOOTH_SCALABLE : textmetric->tmHeight;
494 const QFont::Style style = textmetric->tmItalic ? QFont::StyleItalic : QFont::StyleNormal;
495 const bool antialias = false;
496 const QFont::Weight weight = static_cast<QFont::Weight>(textmetric->tmWeight);
497 const QFont::Stretch stretch = QFont::Unstretched;
498
499#ifndef QT_NO_DEBUG_OUTPUT
500 if (lcQpaFonts().isDebugEnabled()) {
503 str << __FUNCTION__ << ' ' << familyName << ' ' << charSet << " TTF=" << ttf;
504 if (type & DEVICE_FONTTYPE)
505 str << " DEVICE";
506 if (type & RASTER_FONTTYPE)
507 str << " RASTER";
508 if (type & TRUETYPE_FONTTYPE)
509 str << " TRUETYPE";
510 str << " scalable=" << scalable << " Size=" << size
511 << " Style=" << style << " Weight=" << weight
512 << " stretch=" << stretch << " styleName=" << styleName;
513 qCDebug(lcQpaFonts) << message;
514 }
515#endif
516 QString englishName;
517 QString faceName;
518
519 QString subFamilyName;
520 QString subFamilyStyle;
521 // Look-up names registered in the font
522 QFontNames canonicalNames = qt_getCanonicalFontNames(logFont);
523 if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
524 englishName = canonicalNames.name;
525 if (!canonicalNames.preferredName.isEmpty()) {
526 subFamilyName = familyName;
527 subFamilyStyle = styleName;
528 faceName = familyName; // Remember the original name for later lookups
529 familyName = canonicalNames.preferredName;
530 // Preferred style / typographic subfamily name:
531 // "If it is absent, then name ID 2 is considered to be the typographic subfamily name."
532 // From: https://docs.microsoft.com/en-us/windows/win32/directwrite/opentype-variable-fonts
533 // Name ID 2 is already stored in the styleName variable. Furthermore, for variable fonts,
534 // styleName holds the variation instance name, which should be used over name ID 2.
535 if (!canonicalNames.preferredStyle.isEmpty())
536 styleName = canonicalNames.preferredStyle;
537 }
538
539 QSupportedWritingSystems writingSystems;
540 if (type & TRUETYPE_FONTTYPE) {
541 Q_ASSERT(signature);
542 quint32 unicodeRange[4] = {
543 signature->fsUsb[0], signature->fsUsb[1],
544 signature->fsUsb[2], signature->fsUsb[3]
545 };
546 quint32 codePageRange[2] = {
547 signature->fsCsb[0], signature->fsCsb[1]
548 };
549 writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
550 // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
551 // the symbol for Baht, and Windows thus reports that it supports the Thai script.
552 // Since it's the default UI font on this platform, most widgets will be unable to
553 // display Thai text by default. As a temporary work around, we special case Segoe UI
554 // and remove the Thai script from its list of supported writing systems.
555 if (writingSystems.supported(QFontDatabase::Thai) &&
556 familyName == "Segoe UI"_L1)
557 writingSystems.setSupported(QFontDatabase::Thai, false);
558 } else {
560 if (ws != QFontDatabase::Any)
561 writingSystems.setSupported(ws);
562 }
563
564 // We came here from populating a different font family, so we have
565 // to ensure the entire typographic family is populated before we
566 // mark it as such inside registerFont()
567 if (!subFamilyName.isEmpty()
568 && familyName != subFamilyName
569 && sfp->populatedFontFamily != familyName
571 sfp->windowsFontDatabase->populateFamily(familyName);
572 }
573
574 QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
575 style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
576
577 // add fonts windows can generate for us:
578 if (weight <= QFont::DemiBold && styleName.isEmpty())
579 QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
580 style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
581 if (style != QFont::StyleItalic && styleName.isEmpty())
582 QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
583 QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
584 if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
585 QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
586 QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
587
588 if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
589 QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
590 style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
591 }
592
593 if (!englishName.isEmpty() && englishName != familyName)
595
596 return true;
597}
598
599static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric,
600 DWORD type, LPARAM lparam)
601{
602 const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
603 const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
604 const QString styleName = QString::fromWCharArray(f->elfStyle);
605
606 // NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according
607 // to the documentation is identical to a TEXTMETRIC except for the last four
608 // members, which we don't use anyway
609 const FONTSIGNATURE *signature = nullptr;
610 StoreFontPayload *sfp = reinterpret_cast<StoreFontPayload *>(lparam);
611 Q_ASSERT(sfp != nullptr);
612 if (type & TRUETYPE_FONTTYPE) {
613 signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
614 // We get a callback for each script-type supported, but we register them all
615 // at once using the signature, so we only need one call to addFontToDatabase().
616 if (sfp->foundFontAndStyles.hasSeen({familyName, styleName}))
617 return 1;
618 }
619 addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, sfp);
620
621 // keep on enumerating
622 return 1;
623}
624
626{
627 Q_UNUSED(missingFamily);
628
629 if (m_hasPopulatedAliases)
630 return false;
631
633 for (const QString &family : families)
634 populateFamily(family);
635 m_hasPopulatedAliases = true;
636
637 return true;
638}
639
641{
642 qCDebug(lcQpaFonts) << familyName;
643 if (familyName.size() >= LF_FACESIZE) { // Field length of LOGFONT::lfFaceName
644 qCDebug(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\'';
645 return;
646 }
647 HDC dummy = GetDC(0);
648 LOGFONT lf;
649 lf.lfCharSet = DEFAULT_CHARSET;
650 familyName.toWCharArray(lf.lfFaceName);
651 lf.lfFaceName[familyName.size()] = 0;
652 lf.lfPitchAndFamily = 0;
653 StoreFontPayload sfp(familyName, this);
654 EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&sfp), 0);
655 ReleaseDC(0, dummy);
656}
657
658static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric,
659 DWORD, LPARAM)
660{
661 // the "@family" fonts are just the same as "family". Ignore them.
662 const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
663 const wchar_t *faceNameW = f->elfLogFont.lfFaceName;
664 if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) {
665 const QString faceName = QString::fromWCharArray(faceNameW);
667 // Register current font's english name as alias
668 const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE);
669 if (ttf && qt_localizedName(faceName)) {
670 const QString englishName = qt_getEnglishName(faceName);
671 if (!englishName.isEmpty())
673 }
674 }
675 return 1; // continue
676}
677
678namespace {
679
680QString resolveFontPath(const QString &fontPath)
681{
682 if (fontPath.isEmpty())
683 return QString();
684
685 if (QFile::exists(fontPath))
686 return fontPath;
687
688 // resolve the path relatively to Windows Fonts directory
690}
691
692}
693
694void QWindowsFontDatabase::addDefaultEUDCFont()
695{
696 const QString path = QWinRegistryKey(HKEY_CURRENT_USER, LR"(EUDC\1252)")
697 .stringValue(L"SystemDefaultEUDCFont");
698 if (path.isEmpty()) {
699 qCDebug(lcQpaFonts) << "There's no default EUDC font specified";
700 return;
701 }
702
703 const QString absolutePath = resolveFontPath(path);
704 if (absolutePath.isEmpty()) {
705 qCDebug(lcQpaFonts) << "Unable to locate default EUDC font:" << path;
706 return;
707 }
708
711 qCWarning(lcQpaFonts) << "Unable to open default EUDC font:" << absolutePath;
712 return;
713 }
714
716}
717
719{
720 HDC dummy = GetDC(0);
721 LOGFONT lf;
722 lf.lfCharSet = DEFAULT_CHARSET;
723 lf.lfFaceName[0] = 0;
724 lf.lfPitchAndFamily = 0;
725 EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0);
726 ReleaseDC(0, dummy);
727 // Work around EnumFontFamiliesEx() not listing the system font.
728 const QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().families().first();
729 if (QPlatformFontDatabase::resolveFontFamilyAlias(systemDefaultFamily) == systemDefaultFamily)
731 addDefaultEUDCFont();
732}
733
735{
736 removeApplicationFonts();
737}
738
740{
741 // Properties accessed by QWin32PrintEngine (Qt Print Support)
742 static const int hfontMetaTypeId = qRegisterMetaType<HFONT>();
743 static const int logFontMetaTypeId = qRegisterMetaType<LOGFONT>();
744 Q_UNUSED(hfontMetaTypeId);
745 Q_UNUSED(logFontMetaTypeId);
746
747 if (lcQpaFonts().isDebugEnabled()) {
749 qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: "
750 << d->clearTypeEnabled << "gamma: " << d->fontSmoothingGamma;
751 }
752}
753
755{
756 removeApplicationFonts();
757}
758
760{
761 const QString faceName(static_cast<const QChar*>(handle));
762 QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, faceName,
764 data());
765 qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle;
766 return fe;
767}
768
770{
773
774#if QT_CONFIG(directwrite)
775 if (!useDirectWrite(hintingPreference))
776#endif
777 {
778 GUID guid;
779 CoCreateGuid(&guid);
780
782QT_WARNING_DISABLE_GCC("-Wstrict-aliasing")
783 QString uniqueFamilyName = u'f'
784 + QString::number(guid.Data1, 36) + u'-'
785 + QString::number(guid.Data2, 36) + u'-'
786 + QString::number(guid.Data3, 36) + u'-'
787 + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
789
790 QString actualFontName = font.changeFamilyName(uniqueFamilyName);
791 if (actualFontName.isEmpty()) {
792 qWarning("%s: Can't change family name of font", __FUNCTION__);
793 return 0;
794 }
795
796 DWORD count = 0;
797 QByteArray newFontData = font.data();
798 HANDLE fontHandle =
799 AddFontMemResourceEx(const_cast<char *>(newFontData.constData()),
800 DWORD(newFontData.size()), 0, &count);
801 if (count == 0 && fontHandle != 0) {
802 RemoveFontMemResourceEx(fontHandle);
803 fontHandle = 0;
804 }
805
806 if (fontHandle == 0) {
807 qWarning("%s: AddFontMemResourceEx failed", __FUNCTION__);
808 } else {
810 request.families = QStringList(uniqueFamilyName);
811 request.pixelSize = pixelSize;
812 request.styleStrategy = QFont::PreferMatch;
813 request.hintingPreference = hintingPreference;
814 request.stretch = QFont::Unstretched;
815
818 data());
819
820 if (fontEngine) {
821 if (request.families != fontEngine->fontDef.families) {
822 qWarning("%s: Failed to load font. Got fallback instead: %s", __FUNCTION__,
824 if (fontEngine->ref.loadRelaxed() == 0)
825 delete fontEngine;
826 fontEngine = 0;
827 } else {
829
830 // Override the generated font name
831 switch (fontEngine->type()) {
832 case QFontEngine::Win:
833 static_cast<QWindowsFontEngine *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
834 fontEngine->fontDef.families = QStringList(actualFontName);
835 break;
836#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
838 static_cast<QWindowsFontEngineDirectWrite *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
839 fontEngine->fontDef.families = QStringList(actualFontName);
840 break;
841#endif // directwrite && direct2d
842
843 default:
844 Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled font engine.");
845 }
846
847 UniqueFontData uniqueData;
848 uniqueData.handle = fontHandle;
849 uniqueData.refCount.ref();
850 m_uniqueFontData[uniqueFamilyName] = uniqueData;
851 }
852 } else {
853 RemoveFontMemResourceEx(fontHandle);
854 }
855 }
856
857 // Get style and weight info
858 if (fontEngine != nullptr)
859 font.updateFromOS2Table(fontEngine);
860 }
861#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
862 else {
863 fontEngine = QWindowsFontDatabaseBase::fontEngine(fontData, pixelSize, hintingPreference);
864 }
865#endif // directwrite && direct2d
866
867 qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fontEngine;
868 return fontEngine;
869}
870
872{
874 const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
875 if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
876 if (headerTag != MAKE_TAG(0, 1, 0, 0)
877 && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
878 && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
879 && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
880 return offsets;
881 offsets << 0;
882 return offsets;
883 }
884 const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
885 for (uint i = 0; i < numFonts; ++i) {
886 offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
887 }
888 return offsets;
889}
890
891static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
892{
893 const quint16 numTables = qFromBigEndian<quint16>(data + 4);
894 for (uint i = 0; i < numTables; ++i) {
895 const quint32 offset = 12 + 16 * i;
896 if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
897 *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
898 *length = qFromBigEndian<quint32>(data + offset + 12);
899 return;
900 }
901 }
902 *table = 0;
903 *length = 0;
904 return;
905}
906
908 QList<QFontNames> *families,
909 QList<FONTSIGNATURE> *signatures,
911{
912 const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
913
915 if (offsets.isEmpty())
916 return;
917
918 for (int i = 0; i < offsets.count(); ++i) {
919 const uchar *font = data + offsets.at(i);
920 const uchar *table;
922 getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
923 if (!table)
924 continue;
926 if (names.name.isEmpty())
927 continue;
928
929 families->append(std::move(names));
930
931 if (values || signatures)
932 getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
933
934 if (values) {
935 QFontValues fontValues;
936 if (table && length >= 64) {
937 // Read in some details about the font, offset calculated based on the specification
938 fontValues.weight = qFromBigEndian<quint16>(table + 4);
939
940 quint16 fsSelection = qFromBigEndian<quint16>(table + 62);
941 fontValues.isItalic = (fsSelection & 1) != 0;
942 fontValues.isUnderlined = (fsSelection & (1 << 1)) != 0;
943 fontValues.isOverstruck = (fsSelection & (1 << 4)) != 0;
944 }
945 values->append(std::move(fontValues));
946 }
947
948 if (signatures) {
949 FONTSIGNATURE signature;
950 if (table && length >= 86) {
951 // Offsets taken from OS/2 table in the TrueType spec
952 signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
953 signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46);
954 signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50);
955 signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54);
956
957 signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
958 signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
959 } else {
960 memset(&signature, 0, sizeof(signature));
961 }
962 signatures->append(signature);
963 }
964 }
965}
966
968{
969 WinApplicationFont font;
970 font.fileName = fileName;
971 QList<FONTSIGNATURE> signatures;
972 QList<QFontValues> fontValues;
973 QList<QFontNames> families;
974 QStringList familyNames;
975
976 if (!fontData.isEmpty()) {
977 getFamiliesAndSignatures(fontData, &families, &signatures, &fontValues);
978 if (families.isEmpty())
979 return familyNames;
980
981 DWORD dummy = 0;
982 font.handle =
983 AddFontMemResourceEx(const_cast<char *>(fontData.constData()),
984 DWORD(fontData.size()), 0, &dummy);
985 if (font.handle == 0)
986 return QStringList();
987
988 // Memory fonts won't show up in enumeration, so do add them the hard way.
989 for (int j = 0; j < families.count(); ++j) {
990 const auto &family = families.at(j);
991 const QString &familyName = family.name;
992 const QString &styleName = family.style;
993 familyNames << familyName;
994 HDC hdc = GetDC(0);
995 LOGFONT lf;
996 memset(&lf, 0, sizeof(LOGFONT));
997 memcpy(lf.lfFaceName, familyName.data(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size()));
998 lf.lfCharSet = DEFAULT_CHARSET;
999 const QFontValues &values = fontValues.at(j);
1000 lf.lfWeight = values.weight;
1001 if (values.isItalic)
1002 lf.lfItalic = TRUE;
1003 if (values.isOverstruck)
1004 lf.lfStrikeOut = TRUE;
1005 if (values.isUnderlined)
1006 lf.lfUnderline = TRUE;
1007 HFONT hfont = CreateFontIndirect(&lf);
1008 HGDIOBJ oldobj = SelectObject(hdc, hfont);
1009
1010 if (applicationFont != nullptr) {
1013 properties.weight = static_cast<int>(values.weight);
1014 properties.familyName = familyName;
1015 properties.styleName = styleName;
1016
1017 applicationFont->properties.append(properties);
1018 }
1019
1020 TEXTMETRIC textMetrics;
1021 GetTextMetrics(hdc, &textMetrics);
1022
1023 StoreFontPayload sfp(familyName, this);
1024 addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j),
1025 TRUETYPE_FONTTYPE, &sfp);
1026
1027 SelectObject(hdc, oldobj);
1028 DeleteObject(hfont);
1029 ReleaseDC(0, hdc);
1030 }
1031 } else {
1032 QFile f(fileName);
1033 if (!f.open(QIODevice::ReadOnly))
1034 return QStringList();
1035 QByteArray data = f.readAll();
1036 f.close();
1037
1038
1039 getFamiliesAndSignatures(data, &families, nullptr, applicationFont != nullptr ? &fontValues : nullptr);
1040
1041 if (families.isEmpty())
1042 return QStringList();
1043
1044 if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0)
1045 return QStringList();
1046
1047 font.handle = 0;
1048
1049 // Fonts based on files are added via populate, as they will show up in font enumeration.
1050 for (int j = 0; j < families.count(); ++j) {
1051 const QString familyName = families.at(j).name;
1052 familyNames << familyName;
1053
1054 if (applicationFont != nullptr) {
1055 const QString &styleName = families.at(j).style;
1056 const QFontValues &values = fontValues.at(j);
1057
1060 properties.weight = static_cast<int>(values.weight);
1061 properties.familyName = familyName;
1062 properties.styleName = styleName;
1063
1064 applicationFont->properties.append(properties);
1065 }
1066
1067 populateFamily(familyName);
1068 }
1069 }
1070
1071 m_applicationFonts << font;
1072
1073 return familyNames;
1074}
1075
1076void QWindowsFontDatabase::removeApplicationFonts()
1077{
1078 for (const WinApplicationFont &font : std::as_const(m_applicationFonts)) {
1079 if (font.handle) {
1080 RemoveFontMemResourceEx(font.handle);
1081 } else {
1082 RemoveFontResourceExW(reinterpret_cast<LPCWSTR>(font.fileName.utf16()),
1083 FR_PRIVATE, nullptr);
1084 }
1085 }
1086 m_applicationFonts.clear();
1087 m_eudcFonts.clear();
1088}
1089
1091{
1092 const QChar *faceName = reinterpret_cast<const QChar *>(handle);
1093 delete[] faceName;
1094}
1095
1097{
1099 qCDebug(lcQpaFonts) << __FUNCTION__ << result;
1100 return result;
1101}
1102
1104{
1105 return false;
1106}
1107
1109{
1110 if (m_uniqueFontData.contains(uniqueFont)) {
1111 if (!m_uniqueFontData[uniqueFont].refCount.deref()) {
1112 RemoveFontMemResourceEx(m_uniqueFontData[uniqueFont].handle);
1113 m_uniqueFontData.remove(uniqueFont);
1114 }
1115 }
1116}
1117
1119{
1120 if (m_uniqueFontData.contains(uniqueFont))
1121 m_uniqueFontData[uniqueFont].refCount.ref();
1122}
1123
1125{
1127 result.append(familyForStyleHint(styleHint));
1128 result.append(m_eudcFonts);
1129 result.append(extraTryFontsForFamily(family));
1130 result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
1131
1132 qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
1133 << script << result;
1134 return result;
1135}
1136
1137
1139 int dpi,
1141{
1142 QFontEngine *fe = nullptr;
1143
1144 LOGFONT lf = fontDefToLOGFONT(request, faceName);
1145 const bool preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY;
1146
1147 if (request.stretch != 100) {
1148 HFONT hfont = CreateFontIndirect(&lf);
1149 if (!hfont) {
1150 qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__);
1152 }
1153
1154 HGDIOBJ oldObj = SelectObject(data->hdc, hfont);
1155 TEXTMETRIC tm;
1156 if (!GetTextMetrics(data->hdc, &tm))
1157 qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__);
1158 else
1159 lf.lfWidth = tm.tmAveCharWidth * request.stretch / 100;
1160 SelectObject(data->hdc, oldObj);
1161
1162 DeleteObject(hfont);
1163 }
1164
1165#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
1166 if (data->directWriteFactory != nullptr) {
1167 const QString fam = QString::fromWCharArray(lf.lfFaceName);
1169 if (nameSubstitute != fam) {
1170 const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
1171 memcpy(lf.lfFaceName, nameSubstitute.data(), nameSubstituteLength * sizeof(wchar_t));
1172 lf.lfFaceName[nameSubstituteLength] = 0;
1173 }
1174
1175 HFONT hfont = CreateFontIndirect(&lf);
1176 if (!hfont) {
1177 qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__);
1178 } else {
1179 HGDIOBJ oldFont = SelectObject(data->hdc, hfont);
1180
1181 const QFont::HintingPreference hintingPreference =
1182 static_cast<QFont::HintingPreference>(request.hintingPreference);
1183 bool useDw = useDirectWrite(hintingPreference, fam);
1184
1185 IDWriteFontFace *directWriteFontFace = NULL;
1186 HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace);
1187 if (SUCCEEDED(hr)) {
1188 bool isColorFont = false;
1189#if QT_CONFIG(direct2d)
1190 IDWriteFontFace2 *directWriteFontFace2 = nullptr;
1191 if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
1192 reinterpret_cast<void **>(&directWriteFontFace2)))) {
1193 if (directWriteFontFace2->IsColorFont())
1194 isColorFont = directWriteFontFace2->GetPaletteEntryCount() > 0;
1195
1196 directWriteFontFace2->Release();
1197 }
1198#endif // direct2d
1199 useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont);
1200 qCDebug(lcQpaFonts)
1201 << __FUNCTION__ << request.families.first() << request.pointSize << "pt"
1202 << "hintingPreference=" << hintingPreference << "color=" << isColorFont
1203 << dpi << "dpi"
1204 << "useDirectWrite=" << useDw;
1205 if (useDw) {
1206 QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
1207 request.pixelSize,
1208 data);
1209
1210 wchar_t n[64];
1211 GetTextFace(data->hdc, 64, n);
1212
1213 QFontDef fontDef = request;
1215
1216 if (isColorFont)
1218 fedw->initFontInfo(fontDef, dpi);
1219 fe = fedw;
1220 }
1221 directWriteFontFace->Release();
1222 } else if (useDw) {
1223 const QString errorString = qt_error_string(int(hr));
1224 qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed ("
1225 << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
1226 }
1227
1228 SelectObject(data->hdc, oldFont);
1229 DeleteObject(hfont);
1230 }
1231 }
1232#endif // directwrite direct2d
1233
1234 if (!fe) {
1235 QWindowsFontEngine *few = new QWindowsFontEngine(request.families.first(), lf, data);
1236 if (preferClearTypeAA)
1238 few->initFontInfo(request, dpi);
1239 fe = few;
1240 }
1241
1242 return fe;
1243}
1244
1246{
1247 return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family);
1248}
1249
T loadRelaxed() const noexcept
\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
constexpr char16_t unicode() const noexcept
Returns the numeric Unicode value of the QChar.
Definition qchar.h:458
Script
Definition qchar.h:144
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
WritingSystem
\value Any \value Latin \value Greek \value Cyrillic \value Armenian \value Hebrew \value Arabic \val...
static QStringList families(WritingSystem writingSystem=Any)
Returns a sorted list of the available font families which support the writingSystem.
QFontDef fontDef
Type type() const
QAtomicInt ref
GlyphFormat glyphFormat
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:23
QStringList families() const
Definition qfont.cpp:2469
HintingPreference
Definition qfont.h:52
@ PreferNoHinting
Definition qfont.h:54
@ PreferVerticalHinting
Definition qfont.h:55
@ PreferDefaultHinting
Definition qfont.h:53
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:80
@ Unstretched
Definition qfont.h:86
@ PreferMatch
Definition qfont.h:42
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:60
@ DemiBold
Definition qfont.h:66
@ Bold
Definition qfont.h:67
Style
This enum describes the different styles of glyphs that are used to display text.
Definition qfont.h:73
@ StyleItalic
Definition qfont.h:75
@ StyleNormal
Definition qfont.h:74
static bool isActive()
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
qsizetype count() const noexcept
Definition qlist.h:387
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
bool contains(const Key &key) const
Definition qmap.h:340
size_type remove(const Key &key)
Definition qmap.h:299
virtual QString fontDir() const
Returns the directory containing the fonts used by the database.
static QSupportedWritingSystems writingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
Helper function that determines the writing systems support by a given unicodeRange and codePageRange...
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
Returns a list of alternative fonts for the specified family and style and script using the styleHint...
static bool isFamilyPopulated(const QString &familyName)
Helper function that returns true if the font family has already been registered and populated.
virtual bool isPrivateFontFamily(const QString &family) const
Returns true if the font family is private.
virtual QString resolveFontFamilyAlias(const QString &family) const
Resolve alias to actual font family names.
static void registerAliasToFontFamily(const QString &familyName, const QString &alias)
Helper function that register the alias for the familyName.
static void registerFontFamily(const QString &familyName)
Registers a font family with the font database.
static void registerFont(const QString &familyname, const QString &stylename, const QString &foundryname, QFont::Weight weight, QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize, bool fixedPitch, const QSupportedWritingSystems &writingSystems, void *handle)
Registers a font with the given set of attributes describing the font's foundry, family name,...
\inmodule QtCore
static QString locate(StandardLocation type, const QString &fileName, LocateOptions options=LocateFile)
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype toWCharArray(wchar_t *array) const
Definition qstring.h:1146
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
qsizetype length() const
Returns the number of characters in this string.
Definition qstring.h:187
The QSupportedWritingSystems class is used when registering fonts with the internal Qt fontdatabase.
bool supported(QFontDatabase::WritingSystem) const
Returns true if the writing system specified by writingSystem is supported; otherwise returns false.
void setSupported(QFontDatabase::WritingSystem, bool supported=true)
Sets or clears support for the specified writingSystem based on the value given by support.
\inmodule QtCore
QString stringValue(QStringView subKey) const
QFontEngine * fontEngine(const QFontDef &fontDef, void *handle) override
Returns the font engine that can be used to render the font described by the font definition,...
static QStringList extraTryFontsForFamily(const QString &family)
static QSharedPointer< QWindowsFontEngineData > data()
static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName)
static QString familyForStyleHint(QFont::StyleHint styleHint)
Font database for Windows.
static unsigned fontOptions()
void populateFontDatabase() override
This function is called once at startup by Qt's internal font database.
QFontEngine * fontEngine(const QFontDef &fontDef, void *handle) override
Returns the font engine that can be used to render the font described by the font definition,...
void populateFamily(const QString &familyName) override
This function is called whenever a lazily populated family, populated through registerFontFamily(),...
void releaseHandle(void *handle) override
Releases the specified font handle.
QString fontDir() const override
Returns the directory containing the fonts used by the database.
void derefUniqueFont(const QString &uniqueFont)
void invalidate() override
This function is called whenever the font database is invalidated.
static void setFontOptions(unsigned options)
bool isPrivateFontFamily(const QString &family) const override
Returns true if the font family is private.
bool populateFamilyAliases(const QString &missingFamily) override
void refUniqueFont(const QString &uniqueFont)
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont=nullptr) override
Adds an application font described by the font contained supplied fontData or using the font containe...
static QFontEngine * createEngine(const QFontDef &request, const QString &faceName, int dpi, const QSharedPointer< QWindowsFontEngineData > &data)
bool fontsAlwaysScalable() const override
Return true if all fonts are considered scalable when using this font database.
static void debugFormat(QDebug &d, const LOGFONT &lf)
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override
Returns a list of alternative fonts for the specified family and style and script using the styleHint...
Windows font engine using Direct Write.
void initFontInfo(const QFontDef &request, int dpi)
static QString fontNameSubstitute(const QString &familyName)
Standard Windows font engine.
void initFontInfo(const QFontDef &request, int dpi)
QString str
[2]
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
void * HANDLE
#define Q_UNLIKELY(x)
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define Q_FUNC_INFO
#define QT_WARNING_PUSH
AudioChannelLayoutTag tag
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError * error
INT_PTR intptr_t
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define SMOOTH_SCALABLE
static Q_CONSTINIT qreal fontSmoothingGamma
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define qWarning
Definition qlogging.h:162
#define qCWarning(category,...)
#define qCDebug(category,...)
auto qPow(T1 x, T2 y)
Definition qmath.h:180
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLenum GLsizei GLsizei GLint * values
[15]
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei const GLuint * ids
GLsizei const GLchar ** strings
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLenum type
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLuint name
GLfloat n
GLenum GLsizeiptr const void * fontData
const GLubyte * c
GLuint GLuint * names
GLuint GLsizei const GLuint const GLintptr * offsets
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLenum GLenum GLsizei void * table
static QString absolutePath(const QString &path)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define qPrintable(string)
Definition qstring.h:1391
#define CLEARTYPE_QUALITY
Definition qt_windows.h:100
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
unsigned long long quint64
Definition qtypes.h:56
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
long HRESULT
QFontNames qt_getCanonicalFontNames(const LOGFONT &lf)
QString qt_getEnglishName(const QString &familyName, bool includeStyle)
static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, DWORD type, LPARAM lparam)
bool qt_localizedName(const QString &name)
static QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet)
#define MAKE_TAG(ch1, ch2, ch3, ch4)
static QList< quint32 > getTrueTypeFontOffsets(const uchar *fontData)
static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric, DWORD, LPARAM)
static QChar * createFontFile(const QString &faceName)
static bool addFontToDatabase(QString familyName, QString styleName, const LOGFONT &logFont, const TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, int type, StoreFontPayload *sfp)
static void getFamiliesAndSignatures(const QByteArray &fontData, QList< QFontNames > *families, QList< FONTSIGNATURE > *signatures, QList< QFontValues > *values)
static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
QDebug operator<<(QDebug d, const QFontDef &def)
quint16 qt_getUShort(const unsigned char *p)
QFile file
[0]
QTextStream out(stdout)
[7]
QNetworkRequest request(url)
uint hintingPreference
Definition qfont_p.h:66
uint stretch
Definition qfont_p.h:64
qreal pixelSize
Definition qfont_p.h:60
uint weight
Definition qfont_p.h:69
QStringList families
Definition qfont_p.h:54
QString styleName
Definition qfont_p.h:55
uint styleHint
Definition qfont_p.h:68
qreal pointSize
Definition qfont_p.h:59
\inmodule QtCore \reentrant
Definition qchar.h:17