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