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
qcoretextfontdatabase.mm
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
4#include "qglobal.h"
5
6#include <sys/param.h>
7
8#if defined(Q_OS_MACOS)
9#import <AppKit/AppKit.h>
10#import <IOKit/graphics/IOGraphicsLib.h>
11#elif defined(QT_PLATFORM_UIKIT)
12#import <UIKit/UIFont.h>
13#endif
14
15#include <QtCore/qelapsedtimer.h>
16#include <QtCore/private/qcore_mac_p.h>
17
20#if QT_CONFIG(settings)
21#include <QtCore/QSettings>
22#endif
23#include <QtCore/QtEndian>
24#ifndef QT_NO_FREETYPE
25#include <QtGui/private/qfontengine_ft_p.h>
26#endif
27
28#include <QtGui/qpa/qwindowsysteminterface.h>
29
31
32using namespace Qt::StringLiterals;
33
34QT_IMPL_METATYPE_EXTERN_TAGGED(QCFType<CGFontRef>, QCFType_CGFontRef)
35QT_IMPL_METATYPE_EXTERN_TAGGED(QCFType<CFURLRef>, QCFType_CFURLRef)
36
37// this could become a list of all languages used for each writing
38// system, instead of using the single most common language.
39static const char languageForWritingSystem[][8] = {
40 "", // Any
41 "en", // Latin
42 "el", // Greek
43 "ru", // Cyrillic
44 "hy", // Armenian
45 "he", // Hebrew
46 "ar", // Arabic
47 "syr", // Syriac
48 "div", // Thaana
49 "hi", // Devanagari
50 "bn", // Bengali
51 "pa", // Gurmukhi
52 "gu", // Gujarati
53 "or", // Oriya
54 "ta", // Tamil
55 "te", // Telugu
56 "kn", // Kannada
57 "ml", // Malayalam
58 "si", // Sinhala
59 "th", // Thai
60 "lo", // Lao
61 "bo", // Tibetan
62 "my", // Myanmar
63 "ka", // Georgian
64 "km", // Khmer
65 "zh-Hans", // SimplifiedChinese
66 "zh-Hant", // TraditionalChinese
67 "ja", // Japanese
68 "ko", // Korean
69 "vi", // Vietnamese
70 "", // Symbol
71 "sga", // Ogham
72 "non", // Runic
73 "man" // N'Ko
74};
76
78 : m_hasPopulatedAliases(false)
79{
80#if defined(Q_OS_MACOS)
81 m_fontSetObserver = QMacNotificationObserver(nil, NSFontSetChangedNotification, [] {
82 qCDebug(lcQpaFonts) << "Fonts have changed";
84 });
85#endif
86}
87
92
93CTFontDescriptorRef descriptorForFamily(const QString &familyName)
94{
95 return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
96 (id)kCTFontFamilyNameAttribute: familyName.toNSString()
97 }));
98}
100{
101 qCDebug(lcQpaFonts) << "Populating font database...";
103 if (lcQpaFonts().isDebugEnabled())
104 elapsed.start();
105
106 QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
107 for (NSString *familyName in familyNames.as<const NSArray *>())
108 QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
109
110 // Some fonts has special handling since macOS Catalina: It is available
111 // on the platform, so that it may be used by applications directly, but does not
112 // get enumerated. Since there are no alternatives, we hardcode it.
114 && !qEnvironmentVariableIsSet("QT_NO_HARDCODED_FALLBACK_FONTS")) {
115 m_hardcodedFallbackFonts[QChar::Script_Adlam] = QStringLiteral("Noto Sans Adlam");
116 m_hardcodedFallbackFonts[QChar::Script_Ahom] = QStringLiteral("Noto Serif Ahom");
117 m_hardcodedFallbackFonts[QChar::Script_Avestan] = QStringLiteral("Noto Sans Avestan");
118 m_hardcodedFallbackFonts[QChar::Script_Balinese] = QStringLiteral("Noto Serif Balinese");
119 m_hardcodedFallbackFonts[QChar::Script_Bamum] = QStringLiteral("Noto Sans Bamum");
120 m_hardcodedFallbackFonts[QChar::Script_BassaVah] = QStringLiteral("Noto Sans Bassa Vah");
121 m_hardcodedFallbackFonts[QChar::Script_Batak] = QStringLiteral("Noto Sans Batak");
122 m_hardcodedFallbackFonts[QChar::Script_Bhaiksuki] = QStringLiteral("Noto Sans Bhaiksuki");
123 m_hardcodedFallbackFonts[QChar::Script_Brahmi] = QStringLiteral("Noto Sans Brahmi");
124 m_hardcodedFallbackFonts[QChar::Script_Buginese] = QStringLiteral("Noto Sans Buginese");
125 m_hardcodedFallbackFonts[QChar::Script_Buhid] = QStringLiteral("Noto Sans Buhid");
126 m_hardcodedFallbackFonts[QChar::Script_Carian] = QStringLiteral("Noto Sans Carian");
127 m_hardcodedFallbackFonts[QChar::Script_CaucasianAlbanian] = QStringLiteral("Noto Sans Caucasian Albanian");
128 m_hardcodedFallbackFonts[QChar::Script_Chakma] = QStringLiteral("Noto Sans Chakma");
129 m_hardcodedFallbackFonts[QChar::Script_Cham] = QStringLiteral("Noto Sans Cham");
130 m_hardcodedFallbackFonts[QChar::Script_Coptic] = QStringLiteral("Noto Sans Coptic");
131 m_hardcodedFallbackFonts[QChar::Script_Cuneiform] = QStringLiteral("Noto Sans Cuneiform");
132 m_hardcodedFallbackFonts[QChar::Script_Cypriot] = QStringLiteral("Noto Sans Cypriot");
133 m_hardcodedFallbackFonts[QChar::Script_Duployan] = QStringLiteral("Noto Sans Duployan");
134 m_hardcodedFallbackFonts[QChar::Script_EgyptianHieroglyphs] = QStringLiteral("Noto Sans Egyptian Hieroglyphs");
135 m_hardcodedFallbackFonts[QChar::Script_Elbasan] = QStringLiteral("Noto Sans Elbasan");
136 m_hardcodedFallbackFonts[QChar::Script_Glagolitic] = QStringLiteral("Noto Sans Glagolitic");
137 m_hardcodedFallbackFonts[QChar::Script_Gothic] = QStringLiteral("Noto Sans Gothic");
138 m_hardcodedFallbackFonts[QChar::Script_HanifiRohingya] = QStringLiteral("Noto Sans Hanifi Rohingya");
139 m_hardcodedFallbackFonts[QChar::Script_Hanunoo] = QStringLiteral("Noto Sans Hanunoo");
140 m_hardcodedFallbackFonts[QChar::Script_Hatran] = QStringLiteral("Noto Sans Hatran");
141 m_hardcodedFallbackFonts[QChar::Script_ImperialAramaic] = QStringLiteral("Noto Sans Imperial Aramaic");
142 m_hardcodedFallbackFonts[QChar::Script_InscriptionalPahlavi] = QStringLiteral("Noto Sans Inscriptional Pahlavi");
143 m_hardcodedFallbackFonts[QChar::Script_InscriptionalParthian] = QStringLiteral("Noto Sans Inscriptional Parthian");
144 m_hardcodedFallbackFonts[QChar::Script_Javanese] = QStringLiteral("Noto Sans Javanese");
145 m_hardcodedFallbackFonts[QChar::Script_Kaithi] = QStringLiteral("Noto Sans Kaithi");
146 m_hardcodedFallbackFonts[QChar::Script_KayahLi] = QStringLiteral("Noto Sans Kayah Li");
147 m_hardcodedFallbackFonts[QChar::Script_Kharoshthi] = QStringLiteral("Noto Sans Kharoshthi");
148 m_hardcodedFallbackFonts[QChar::Script_Khojki] = QStringLiteral("Noto Sans Khojki");
149 m_hardcodedFallbackFonts[QChar::Script_Khudawadi] = QStringLiteral("Noto Sans Khudawadi");
150 m_hardcodedFallbackFonts[QChar::Script_Lepcha] = QStringLiteral("Noto Sans Lepcha");
151 m_hardcodedFallbackFonts[QChar::Script_Limbu] = QStringLiteral("Noto Sans Limbu");
152 m_hardcodedFallbackFonts[QChar::Script_LinearA] = QStringLiteral("Noto Sans Linear A");
153 m_hardcodedFallbackFonts[QChar::Script_LinearB] = QStringLiteral("Noto Sans Linear B");
154 m_hardcodedFallbackFonts[QChar::Script_Lisu] = QStringLiteral("Noto Sans Lisu");
155 m_hardcodedFallbackFonts[QChar::Script_Lycian] = QStringLiteral("Noto Sans Lycian");
156 m_hardcodedFallbackFonts[QChar::Script_Lydian] = QStringLiteral("Noto Sans Lydian");
157 m_hardcodedFallbackFonts[QChar::Script_Mahajani] = QStringLiteral("Noto Sans Mahajani");
158 m_hardcodedFallbackFonts[QChar::Script_Mandaic] = QStringLiteral("Noto Sans Mandaic");
159 m_hardcodedFallbackFonts[QChar::Script_Manichaean] = QStringLiteral("Noto Sans Manichaean");
160 m_hardcodedFallbackFonts[QChar::Script_Marchen] = QStringLiteral("Noto Sans Marchen");
161 m_hardcodedFallbackFonts[QChar::Script_MendeKikakui] = QStringLiteral("Noto Sans Mende Kikakui");
162 m_hardcodedFallbackFonts[QChar::Script_MeroiticCursive] = QStringLiteral("Noto Sans Meroitic");
163 m_hardcodedFallbackFonts[QChar::Script_MeroiticHieroglyphs] = QStringLiteral("Noto Sans Meroitic");
164 m_hardcodedFallbackFonts[QChar::Script_Miao] = QStringLiteral("Noto Sans Miao");
165 m_hardcodedFallbackFonts[QChar::Script_Modi] = QStringLiteral("Noto Sans Modi");
166 m_hardcodedFallbackFonts[QChar::Script_Mongolian] = QStringLiteral("Noto Sans Mongolian");
167 m_hardcodedFallbackFonts[QChar::Script_Mro] = QStringLiteral("Noto Sans Mro");
168 m_hardcodedFallbackFonts[QChar::Script_MeeteiMayek] = QStringLiteral("Noto Sans Meetei Mayek");
169 m_hardcodedFallbackFonts[QChar::Script_Multani] = QStringLiteral("Noto Sans Multani");
170 m_hardcodedFallbackFonts[QChar::Script_Nabataean] = QStringLiteral("Noto Sans Nabataean");
171 m_hardcodedFallbackFonts[QChar::Script_Newa] = QStringLiteral("Noto Sans Newa");
172 m_hardcodedFallbackFonts[QChar::Script_NewTaiLue] = QStringLiteral("Noto Sans New Tai Lue");
173 m_hardcodedFallbackFonts[QChar::Script_Nko] = QStringLiteral("Noto Sans Nko");
174 m_hardcodedFallbackFonts[QChar::Script_OlChiki] = QStringLiteral("Noto Sans Ol Chiki");
175 m_hardcodedFallbackFonts[QChar::Script_OldHungarian] = QStringLiteral("Noto Sans Old Hungarian");
176 m_hardcodedFallbackFonts[QChar::Script_OldItalic] = QStringLiteral("Noto Sans Old Italic");
177 m_hardcodedFallbackFonts[QChar::Script_OldNorthArabian] = QStringLiteral("Noto Sans Old North Arabian");
178 m_hardcodedFallbackFonts[QChar::Script_OldPermic] = QStringLiteral("Noto Sans Old Permic");
179 m_hardcodedFallbackFonts[QChar::Script_OldPersian] = QStringLiteral("Noto Sans Old Persian");
180 m_hardcodedFallbackFonts[QChar::Script_OldSouthArabian] = QStringLiteral("Noto Sans Old South Arabian");
181 m_hardcodedFallbackFonts[QChar::Script_OldTurkic] = QStringLiteral("Noto Sans Old Turkic");
182 m_hardcodedFallbackFonts[QChar::Script_Osage] = QStringLiteral("Noto Sans Osage");
183 m_hardcodedFallbackFonts[QChar::Script_Osmanya] = QStringLiteral("Noto Sans Osmanya");
184 m_hardcodedFallbackFonts[QChar::Script_PahawhHmong] = QStringLiteral("Noto Sans Pahawh Hmong");
185 m_hardcodedFallbackFonts[QChar::Script_Palmyrene] = QStringLiteral("Noto Sans Palmyrene");
186 m_hardcodedFallbackFonts[QChar::Script_PauCinHau] = QStringLiteral("Noto Sans Pau Cin Hau");
187 m_hardcodedFallbackFonts[QChar::Script_PhagsPa] = QStringLiteral("Noto Sans PhagsPa");
188 m_hardcodedFallbackFonts[QChar::Script_Phoenician] = QStringLiteral("Noto Sans Phoenician");
189 m_hardcodedFallbackFonts[QChar::Script_PsalterPahlavi] = QStringLiteral("Noto Sans Psalter Pahlavi");
190 m_hardcodedFallbackFonts[QChar::Script_Rejang] = QStringLiteral("Noto Sans Rejang");
191 m_hardcodedFallbackFonts[QChar::Script_Samaritan] = QStringLiteral("Noto Sans Samaritan");
192 m_hardcodedFallbackFonts[QChar::Script_Saurashtra] = QStringLiteral("Noto Sans Saurashtra");
193 m_hardcodedFallbackFonts[QChar::Script_Sharada] = QStringLiteral("Noto Sans Sharada");
194 m_hardcodedFallbackFonts[QChar::Script_Siddham] = QStringLiteral("Noto Sans Siddham");
195 m_hardcodedFallbackFonts[QChar::Script_SoraSompeng] = QStringLiteral("Noto Sans Sora Sompeng");
196 m_hardcodedFallbackFonts[QChar::Script_Sundanese] = QStringLiteral("Noto Sans Sundanese");
197 m_hardcodedFallbackFonts[QChar::Script_SylotiNagri] = QStringLiteral("Noto Sans Syloti Nagri");
198 m_hardcodedFallbackFonts[QChar::Script_Tagalog] = QStringLiteral("Noto Sans Tagalog");
199 m_hardcodedFallbackFonts[QChar::Script_Tagbanwa] = QStringLiteral("Noto Sans Tagbanwa");
200 m_hardcodedFallbackFonts[QChar::Script_Takri] = QStringLiteral("Noto Sans Takri");
201 m_hardcodedFallbackFonts[QChar::Script_TaiLe] = QStringLiteral("Noto Sans Tai Le");
202 m_hardcodedFallbackFonts[QChar::Script_TaiTham] = QStringLiteral("Noto Sans Tai Tham");
203 m_hardcodedFallbackFonts[QChar::Script_TaiViet] = QStringLiteral("Noto Sans Tai Viet");
204 m_hardcodedFallbackFonts[QChar::Script_Thaana] = QStringLiteral("Noto Sans Thaana");
205 m_hardcodedFallbackFonts[QChar::Script_Tifinagh] = QStringLiteral("Noto Sans Tifinagh");
206 m_hardcodedFallbackFonts[QChar::Script_Tirhuta] = QStringLiteral("Noto Sans Tirhuta");
207 m_hardcodedFallbackFonts[QChar::Script_Ugaritic] = QStringLiteral("Noto Sans Ugaritic");
208 m_hardcodedFallbackFonts[QChar::Script_Vai] = QStringLiteral("Noto Sans Vai");
209 m_hardcodedFallbackFonts[QChar::Script_WarangCiti] = QStringLiteral("Noto Sans Warang Citi");
210 m_hardcodedFallbackFonts[QChar::Script_Wancho] = QStringLiteral("Noto Sans Wancho");
211 m_hardcodedFallbackFonts[QChar::Script_Yi] = QStringLiteral("Noto Sans Yi");
212 }
213
214 qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms";
215
216 populateThemeFonts();
217
218 for (auto familyName : m_systemFontDescriptors.keys()) {
219 for (auto fontDescriptor : m_systemFontDescriptors.value(familyName))
220 populateFromDescriptor(fontDescriptor, familyName);
221 }
222
223 // The font database now has a reference to the original descriptors
224 m_systemFontDescriptors.clear();
225
226 qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms";
227
228 Q_ASSERT(!m_hasPopulatedAliases);
229}
230
232{
233#if defined(Q_OS_MACOS)
234 if (isFamilyPopulated(missingFamily)) {
235 // We got here because one of the other properties of the font mismatched,
236 // for example the style, so there's no point in populating font aliases.
237 return false;
238 }
239
240 if (m_hasPopulatedAliases)
241 return false;
242
243 // There's no API to go from a localized family name to its non-localized
244 // name, so we have to resort to enumerating all the available fonts and
245 // doing a reverse lookup.
246
247 qCDebug(lcQpaFonts) << "Populating family aliases...";
249 elapsed.start();
250
251 QString nonLocalizedMatch;
252 QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
253 NSFontManager *fontManager = NSFontManager.sharedFontManager;
254 for (NSString *familyName in familyNames.as<const NSArray *>()) {
255 NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil];
256 if (![localizedFamilyName isEqual:familyName]) {
257 QString nonLocalizedFamily = QString::fromNSString(familyName);
258 QString localizedFamily = QString::fromNSString(localizedFamilyName);
259 QPlatformFontDatabase::registerAliasToFontFamily(nonLocalizedFamily, localizedFamily);
260 if (localizedFamily == missingFamily)
261 nonLocalizedMatch = nonLocalizedFamily;
262 }
263 }
264 m_hasPopulatedAliases = true;
265
266 if (lcQpaFonts().isWarningEnabled()) {
267 QString warningMessage;
268 QDebug msg(&warningMessage);
269
270 msg << "Populating font family aliases took" << elapsed.restart() << "ms.";
271 if (!nonLocalizedMatch.isNull())
272 msg << "Replace uses of" << missingFamily << "with its non-localized name" << nonLocalizedMatch;
273 else
274 msg << "Replace uses of missing font family" << missingFamily << "with one that exists";
275 msg << "to avoid this cost.";
276
277 qCWarning(lcQpaFonts) << qPrintable(warningMessage);
278 }
279
280 return true;
281#else
282 Q_UNUSED(missingFamily);
283 return false;
284#endif
285}
286
287CTFontDescriptorRef descriptorForFamily(const char *familyName)
288{
289 return descriptorForFamily(QString::fromLatin1(familyName));
290}
291
293{
294 qCDebug(lcQpaFonts) << "Populating family" << familyName;
295
296 // A single family might match several different fonts with different styles.
297 // We need to add them all so that the font database has the full picture,
298 // as once a family has been populated we will not populate it again.
299 QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(familyName);
300 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
301 if (!matchingFonts) {
302 qCWarning(lcQpaFonts) << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
303 return;
304 }
305
306 const int numFonts = CFArrayGetCount(matchingFonts);
307 for (int i = 0; i < numFonts; ++i)
308 populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)), familyName);
309}
310
312{
313 qCDebug(lcQpaFonts) << "Invalidating font database";
314 m_hasPopulatedAliases = false;
315
316 qDeleteAll(m_themeFonts);
317 m_themeFonts.clear();
318 QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
319}
320
332
333#ifndef QT_NO_DEBUG_STREAM
335{
336 QDebugStateSaver saver(debug);
337 return debug.nospace() << "FontDescription("
338 << "familyName=" << QString(fd.familyName)
339 << ", styleName=" << QString(fd.styleName)
340 << ", foundry=" << fd.foundryName
341 << ", weight=" << fd.weight
342 << ", style=" << fd.style
343 << ", stretch=" << fd.stretch
344 << ", pointSize=" << fd.pointSize
345 << ", fixedPitch=" << fd.fixedPitch
346 << ", writingSystems=" << fd.writingSystems
347 << ")";
348}
349#endif
350
351static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
352{
353 QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
354
355 fd->foundryName = QStringLiteral("CoreText");
356 fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
357 fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
358 fd->weight = QFont::Normal;
359 fd->style = QFont::StyleNormal;
360 fd->stretch = QFont::Unstretched;
361 fd->fixedPitch = false;
362
363 if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
364 uint tag = QFont::Tag("OS/2").value();
365 CTFontRef tempFontRef = tempFont;
366 void *userData = reinterpret_cast<void *>(&tempFontRef);
367 uint length = 128;
368 QVarLengthArray<uchar, 128> os2Table(length);
369 if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) {
370 if (length > uint(os2Table.length())) {
371 os2Table.resize(length);
372 if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length))
373 Q_UNREACHABLE();
374 Q_ASSERT(length >= 86);
375 }
376 fd->writingSystems = QPlatformFontDatabase::writingSystemsFromOS2Table(reinterpret_cast<const char *>(os2Table.data()), length);
377 }
378 }
379
380 if (styles) {
381 if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
382 double normalizedWeight;
383 if (CFNumberGetValue(weightValue, kCFNumberFloat64Type, &normalizedWeight))
384 fd->weight = QCoreTextFontEngine::qtWeightFromCFWeight(float(normalizedWeight));
385 }
386 if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
387 double d;
388 if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
389 if (d > 0.0)
390 fd->style = QFont::StyleItalic;
391 }
392 }
393 if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
394 int d;
395 if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
396 if (d & kCTFontMonoSpaceTrait)
397 fd->fixedPitch = true;
398 if (d & kCTFontExpandedTrait)
399 fd->stretch = QFont::Expanded;
400 else if (d & kCTFontCondensedTrait)
401 fd->stretch = QFont::Condensed;
402 }
403 }
404 }
405
406 if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
407 if (CFNumberIsFloatType(size)) {
408 double d;
409 CFNumberGetValue(size, kCFNumberDoubleType, &d);
410 fd->pointSize = d;
411 } else {
412 int i;
413 CFNumberGetValue(size, kCFNumberIntType, &i);
414 fd->pointSize = i;
415 }
416 }
417
418 if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
419 CFIndex length = CFArrayGetCount(languages);
420 for (int i = 1; i < LanguageCount; ++i) {
422 continue;
423 QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
424 if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
425 fd->writingSystems.setSupported(QFontDatabase::WritingSystem(i));
426 }
427 }
428}
429
430void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName, QFontDatabasePrivate::ApplicationFont *applicationFont)
431{
434
435 // Note: The familyName we are registering, and the family name of the font descriptor, may not
436 // match, as CTFontDescriptorCreateMatchingFontDescriptors will return descriptors for replacement
437 // fonts if a font family does not have any fonts available on the system.
438 QString family = !familyName.isNull() ? familyName : static_cast<QString>(fd.familyName);
439
440 if (applicationFont != nullptr) {
442 properties.familyName = family;
443 properties.styleName = fd.styleName;
444 properties.weight = fd.weight;
445 properties.stretch = fd.stretch;
446 properties.style = fd.style;
447
448 applicationFont->properties.append(properties);
449 }
450
451 CFRetain(font);
452 QPlatformFontDatabase::registerFont(family, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
453 true /* antialiased */, true /* scalable */, 0 /* pixelSize, ignored as font is scalable */,
454 fd.fixedPitch, fd.writingSystems, (void *)font);
455}
456
457static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute";
458
459template <typename T>
460T *descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name)
461{
462 return [static_cast<T *>(CTFontDescriptorCopyAttribute(descriptor, name)) autorelease];
463}
464
466{
467 CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(handle);
468 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) {
469 QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue);
470 delete fontData;
471 }
472 CFRelease(descriptor);
473}
474
475extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
476
477template <>
479{
480 QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet(
481 static_cast<CTFontDescriptorRef>(usrPtr));
482
483 // Since we do not pass in the destination DPI to CoreText when making
484 // the font, we need to pass in a point size which is scaled to include
485 // the DPI. The default DPI for the screen is 72, thus the scale factor
486 // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi,
487 // the pixelSize is actually the scaled point size for the destination
488 // DPI, and we can use that directly.
489 qreal scaledPointSize = fontDef.pixelSize;
490
491 CGAffineTransform matrix = qt_transform_from_fontdef(fontDef);
492
493 if (!fontDef.variableAxisValues.isEmpty()) {
494 QCFType<CFMutableDictionaryRef> variations = CFDictionaryCreateMutable(nullptr,
495 fontDef.variableAxisValues.size(),
496 &kCFTypeDictionaryKeyCallBacks,
497 &kCFTypeDictionaryValueCallBacks);
498 for (auto it = fontDef.variableAxisValues.constBegin();
499 it != fontDef.variableAxisValues.constEnd();
500 ++it) {
501 const quint32 tag = it.key().value();
502 const float value = it.value();
503 QCFType<CFNumberRef> tagRef = CFNumberCreate(nullptr, kCFNumberIntType, &tag);
504 QCFType<CFNumberRef> valueRef = CFNumberCreate(nullptr, kCFNumberFloatType, &value);
505
506 CFDictionarySetValue(variations, tagRef, valueRef);
507 }
508 QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(nullptr,
509 (const void **) &kCTFontVariationAttribute,
510 (const void **) &variations,
511 1,
512 &kCFTypeDictionaryKeyCallBacks,
513 &kCFTypeDictionaryValueCallBacks);
514 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes);
515 }
516
517 if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix))
518 return new QCoreTextFontEngine(font, fontDef);
519
520 return nullptr;
521}
522
523#ifndef QT_NO_FREETYPE
524template <>
526{
527 CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
528
529 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) {
530 QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue);
532 static_cast<QFont::HintingPreference>(fontDef.hintingPreference), fontDef.variableAxisValues);
533 } else if (NSURL *url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) {
534 QFontEngine::FaceId faceId;
535
536 Q_ASSERT(url.fileURL);
537 QString faceFileName{QString::fromNSString(url.path)};
538 faceId.filename = faceFileName.toUtf8();
539
540 QString styleName = QCFString(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute));
541 faceId.index = QFreetypeFace::getFaceIndexByStyleName(faceFileName, styleName);
542
543 faceId.variableAxes = fontDef.variableAxisValues;
544
545 return QFontEngineFT::create(fontDef, faceId);
546 }
547 // We end up here with a descriptor does not contain Qt font data or kCTFontURLAttribute.
548 // Since the FT engine can't deal with a descriptor with just a NSFontNameAttribute,
549 // we should return nullptr.
550 return nullptr;
551}
552#endif
553
554template <class T>
556{
557 return T::create(fontData, pixelSize, hintingPreference, {});
558}
559
560// Explicitly instantiate so that we don't need the plugin to involve FreeType
561template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
562#ifndef QT_NO_FREETYPE
563template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
564#endif
565
566CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
567{
568 QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr);
569 if (!font) {
570 qCWarning(lcQpaFonts) << "Failed to create fallback font for" << descriptor;
571 return nullptr;
572 }
573
574 CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font,
575 (CFArrayRef)NSLocale.preferredLanguages));
576
577 if (!cascadeList) {
578 qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << descriptor;
579 return nullptr;
580 }
581
582 return cascadeList;
583}
584
586{
587 if (family.isEmpty())
588 return nullptr;
589
590 QCFType<CTFontDescriptorRef> fontDescriptor = descriptorForFamily(family);
591 if (!fontDescriptor) {
592 qCWarning(lcQpaFonts) << "Failed to create fallback font descriptor for" << family;
593 return nullptr;
594 }
595
596 // If the font is not available we want to fall back to the style hint.
597 // By creating a matching font descriptor we can verify whether the font
598 // is available or not, and avoid CTFontCreateWithFontDescriptor picking
599 // a default font for us based on incomplete information.
600 fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0);
601 if (!fontDescriptor)
602 return nullptr;
603
604 return fallbacksForDescriptor(fontDescriptor);
605}
606
607CTFontDescriptorRef descriptorForFontType(CTFontUIFontType uiType)
608{
609 static const CGFloat kDefaultSizeForRequestedUIType = 0.0;
610 QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(
611 uiType, kDefaultSizeForRequestedUIType, nullptr);
612 return CTFontCopyFontDescriptor(ctFont);
613}
614
615CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint)
616{
617 switch (styleHint) {
618 case QFont::SansSerif: return descriptorForFamily("Helvetica");
619 case QFont::Serif: return descriptorForFamily("Times New Roman");
620 case QFont::Monospace: return descriptorForFamily("Menlo");
621#ifdef Q_OS_MACOS
622 case QFont::Cursive: return descriptorForFamily("Apple Chancery");
623#endif
624 case QFont::Fantasy: return descriptorForFamily("Zapfino");
625 case QFont::TypeWriter: return descriptorForFamily("American Typewriter");
627 case QFont::System: return descriptorForFontType(kCTFontUIFontSystem);
628 default: return nullptr; // No matching font on this platform
629 }
630}
631
632QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
633{
634 Q_UNUSED(style);
635
636 qCDebug(lcQpaFonts).nospace() << "Resolving fallbacks families for"
637 << (!family.isEmpty() ? qPrintable(" family '%1' with"_L1.arg(family)) : "")
638 << " style hint " << styleHint;
639
641
642 QStringList fallbackList;
643
644 QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family);
645 if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
646 // We were not able to find a fallback for the specific family,
647 // or the family was empty, so we fall back to the style hint.
648 if (!family.isEmpty())
649 qCDebug(lcQpaFonts) << "No fallbacks found. Using style hint instead";
650
651 if (QCFType<CTFontDescriptorRef> styleDescriptor = descriptorForStyle(styleHint)) {
652 CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
653 CFArrayAppendValue(tmp, styleDescriptor);
654 QCFType<CFArrayRef> styleFallbacks = fallbacksForDescriptor(styleDescriptor);
655 CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks)));
656 fallbackFonts = tmp;
657 }
658 }
659
660 if (!fallbackFonts)
661 return fallbackList;
662
663 const int numberOfFallbacks = CFArrayGetCount(fallbackFonts);
664 for (int i = 0; i < numberOfFallbacks; ++i) {
665 auto fallbackDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fallbackFonts, i));
666 auto fallbackFamilyName = QCFString(CTFontDescriptorCopyAttribute(fallbackDescriptor, kCTFontFamilyNameAttribute));
667
668 if (!isFamilyPopulated(fallbackFamilyName)) {
669 // We need to populate, or at least register the fallback fonts,
670 // otherwise the Qt font database may not know they exist.
671 if (isPrivateFontFamily(fallbackFamilyName))
672 const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(fallbackDescriptor);
673 else
674 registerFontFamily(fallbackFamilyName);
675 }
676
677 fallbackList.append(fallbackFamilyName);
678 }
679
680 // Some fallback fonts will have have an order in the list returned
681 // by Core Text that would indicate they should be preferred for e.g.
682 // Arabic, or Emoji, while in reality only supporting a tiny subset
683 // of the required glyphs, or representing them by question marks.
684 // Move these to the end, so that the proper fonts are preferred.
685 for (const char *family : { ".Apple Symbols Fallback", ".Noto Sans Universal" }) {
686 int index = fallbackList.indexOf(QLatin1StringView(family));
687 if (index >= 0)
688 fallbackList.move(index, fallbackList.size() - 1);
689 }
690
691#if defined(Q_OS_MACOS)
692 // Since we are only returning a list of default fonts for the current language, we do not
693 // cover all Unicode completely. This was especially an issue for some of the common script
694 // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
695 // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
696 // of Unicode 2.1.
697 if (!fallbackList.contains(QStringLiteral("Arial Unicode MS")))
698 fallbackList.append(QStringLiteral("Arial Unicode MS"));
699 // Since some symbols (specifically Braille) are not in Arial Unicode MS, we
700 // add Apple Symbols to cover those too.
701 if (!fallbackList.contains(QStringLiteral("Apple Symbols")))
702 fallbackList.append(QStringLiteral("Apple Symbols"));
703 // Some Noto* fonts are not automatically enumerated by system, despite being the main
704 // fonts for their writing system.
705 QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
706 if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
707 if (!isFamilyPopulated(hardcodedFont)) {
708 if (!m_privateFamilies.contains(hardcodedFont)) {
709 QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
710 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
711 if (matchingFonts) {
712 const int numFonts = CFArrayGetCount(matchingFonts);
713 for (int i = 0; i < numFonts; ++i)
714 const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
715 hardcodedFont);
716
717 fallbackList.append(hardcodedFont);
718 }
719
720 // Register as private family even if the font is not found, in order to avoid
721 // redoing the check later. In later calls, the font will then just be ignored.
722 m_privateFamilies.insert(hardcodedFont);
723 }
724 } else {
725 fallbackList.append(hardcodedFont);
726 }
727 }
728#endif
729
730 extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
731 fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
732
733 qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList;
734
735 return fallbackList;
736}
737
739{
740 QCFType<CFArrayRef> fonts;
741
742 if (!fontData.isEmpty()) {
743 QCFType<CFDataRef> fontDataReference = fontData.toRawCFData();
744 if (QCFType<CFArrayRef> descriptors = CTFontManagerCreateFontDescriptorsFromData(fontDataReference)) {
745 CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
746 const int count = CFArrayGetCount(descriptors);
747
748 for (int i = 0; i < count; ++i) {
749 CTFontDescriptorRef descriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(descriptors, i));
750
751 // There's no way to get the data back out of a font descriptor created with
752 // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually.
753 NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] };
754 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
755 CFArrayAppendValue(array, descriptor);
756 }
757
758 fonts = array;
759 }
760 } else {
761 QCFType<CFURLRef> fontURL = QUrl::fromLocalFile(fileName).toCFURL();
762 fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
763 }
764
765 if (!fonts)
766 return QStringList();
767
768 QStringList families;
769 const int numFonts = CFArrayGetCount(fonts);
770 for (int i = 0; i < numFonts; ++i) {
771 CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i));
772 populateFromDescriptor(fontDescriptor, QString(), applicationFont);
773 QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute));
774 families.append(QString::fromCFString(familyName));
775 }
776
777 // Note: We don't do font matching via CoreText for application fonts, so we don't
778 // need to enable font matching for them via CTFontManagerEnableFontDescriptors.
779
780 return families;
781}
782
784{
785 if (family.startsWith(u'.') || family == "LastResort"_L1 || m_privateFamilies.contains(family))
786 return true;
787
789}
790
792{
793 switch (f) {
795 return kCTFontUIFontSystem;
796
800 return kCTFontUIFontMenuItem;
801
803 return kCTFontUIFontEmphasizedSystem;
804
806 return kCTFontUIFontSystem;
807
809 return kCTFontUIFontToolTip;
810
812 return kCTFontUIFontSystem;
813
815 return kCTFontUIFontWindowTitle;
816
818 return kCTFontUIFontSystem;
819
821 return kCTFontUIFontSmallSystem;
822
824 return kCTFontUIFontPushButton;
825
828 return kCTFontUIFontSystem;
829
831 return kCTFontUIFontSmallToolbar;
832
834 return kCTFontUIFontSystem;
835
837 return kCTFontUIFontViews;
838
840 return kCTFontUIFontSmallSystem;
841
843 return kCTFontUIFontViews;
844
846 return kCTFontUIFontSystem;
847
849 return kCTFontUIFontViews;
850
852 return kCTFontUIFontSmallSystem;
853
855 return kCTFontUIFontMiniSystem;
856
858 return kCTFontUIFontUserFixedPitch;
859
860 default:
861 return kCTFontUIFontSystem;
862 }
863}
864
866{
867#if defined(QT_PLATFORM_UIKIT)
868 // Use Dynamic Type to resolve theme fonts if possible, to get
869 // correct font sizes and style based on user configuration.
870 NSString *textStyle = 0;
871 switch (f) {
874 textStyle = UIFontTextStyleHeadline;
875 break;
877 textStyle = UIFontTextStyleSubheadline;
878 break;
881 textStyle = UIFontTextStyleFootnote;
882 break;
884 textStyle = UIFontTextStyleCaption2;
885 break;
887 // Fall back to regular code path, as iOS doesn't provide
888 // an appropriate text style for this theme font.
889 break;
890 default:
891 textStyle = UIFontTextStyleBody;
892 break;
893 }
894
895 if (textStyle) {
896 UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
897 return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc));
898 }
899#endif // QT_PLATFORM_UIKIT
900
901 // macOS default case and iOS fallback case
903}
904
905void QCoreTextFontDatabase::populateThemeFonts()
906{
908
909 if (!m_themeFonts.isEmpty())
910 return;
911
913 if (lcQpaFonts().isDebugEnabled())
914 elapsed.start();
915
916 qCDebug(lcQpaFonts) << "Populating theme fonts...";
917
919 QPlatformTheme::Font themeFont = static_cast<QPlatformTheme::Font>(f);
920 QCFType<CTFontDescriptorRef> fontDescriptor = fontDescriptorFromTheme(themeFont);
922 getFontDescription(fontDescriptor, &fd);
923
924 // We might get here from QFontDatabase::systemFont() or QPlatformTheme::font(),
925 // before the font database has initialized itself and populated all available
926 // families. As a result, we can't populate the descriptor at this time, as that
927 // would result in the font database having > 0 families, which would result in
928 // skipping the initialization and population of all other font families. Instead
929 // we store the descriptors for later and populate them during populateFontDatabase().
930
931 bool haveRegisteredFamily = m_systemFontDescriptors.contains(fd.familyName);
932 qCDebug(lcQpaFonts) << "Got" << (haveRegisteredFamily ? "already registered" : "unseen")
933 << "family" << fd.familyName << "for" << themeFont;
934
935 if (!haveRegisteredFamily) {
936 // We need to register all weights and variants of the theme font,
937 // as the user might tweak the returned QFont before use.
938 QList<QCFType<CTFontDescriptorRef>> themeFontVariants;
939
940 auto addFontVariants = [&](CTFontDescriptorRef descriptor) {
941 QCFType<CFArrayRef> matchingDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, nullptr);
942 const int matchingDescriptorsCount = matchingDescriptors ? CFArrayGetCount(matchingDescriptors) : 0;
943 qCDebug(lcQpaFonts) << "Enumerating font variants based on" << id(descriptor)
944 << "resulted in" << matchingDescriptorsCount << "matching descriptors"
945 << matchingDescriptors.as<NSArray*>();
946
947 for (int i = 0; i < matchingDescriptorsCount; ++i) {
948 auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors, i));
949 themeFontVariants.append(QCFType<CTFontDescriptorRef>::constructFromGet(matchingDescriptor));
950 }
951 };
952
953 // Try populating the font variants based on its UI design trait, if available
954 if (@available(macos 10.15, ios 13.0, *)) {
955 auto fontTraits = QCFType<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute));
956 static const NSString *kUIFontDesignTrait = @"NSCTFontUIFontDesignTrait";
957 if (id uiFontDesignTrait = fontTraits.as<NSDictionary*>()[kUIFontDesignTrait]) {
958 QCFType<CTFontDescriptorRef> designTraitDescriptor = CTFontDescriptorCreateWithAttributes(
959 CFDictionaryRef(@{ (id)kCTFontTraitsAttribute: @{ kUIFontDesignTrait: uiFontDesignTrait }
960 }));
961 addFontVariants(designTraitDescriptor);
962 }
963 }
964
965 if (themeFontVariants.isEmpty()) {
966 // Fall back to populating variants based on the family name alone
967 QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(fd.familyName);
968 addFontVariants(familyDescriptor);
969 }
970
971 if (themeFontVariants.isEmpty()) {
972 qCDebug(lcQpaFonts) << "No theme font variants found, falling back to single variant descriptor";
973 themeFontVariants.append(fontDescriptor);
974 }
975
976 m_systemFontDescriptors.insert(fd.familyName, themeFontVariants);
977 }
978
979 QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic);
980 m_themeFonts.insert(themeFont, font);
981 }
982
983 qCDebug(lcQpaFonts) << "Populating theme fonts took" << elapsed.restart() << "ms";
984}
985
987{
988 // The code paths via QFontDatabase::systemFont() or QPlatformTheme::font()
989 // do not ensure that the font database has been populated, so we need to
990 // manually populate the theme fonts lazily here just in case.
991 const_cast<QCoreTextFontDatabase*>(this)->populateThemeFonts();
992
993 return m_themeFonts.value(f, nullptr);
994}
995
1000
1002{
1003 return true;
1004}
1005
1007{
1008 QList<int> ret;
1009 static const unsigned short standard[] =
1010 { 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288, 0 };
1011 ret.reserve(int(sizeof(standard) / sizeof(standard[0])));
1012 const unsigned short *sizes = standard;
1013 while (*sizes) ret << *sizes++;
1014 return ret;
1015}
1016
1018{
1019 return true;
1020}
1021
1023
static bool isEqual(const aiUVTransform &a, const aiUVTransform &b)
\inmodule QtCore
Definition qbytearray.h:57
static QCFType constructFromGet(const T &t)
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 invalidate() override
This function is called whenever the font database is invalidated.
bool isPrivateFontFamily(const QString &family) const override
Returns true if the font family is private.
bool supportsVariableApplicationFonts() const override
Returns true if this font database supports loading named instances from variable application fonts.
bool fontsAlwaysScalable() const override
Return true if all fonts are considered scalable when using this font database.
QList< int > standardSizes() const override
Return list of standard font sizes when using this font database.
void releaseHandle(void *handle) override
Releases the specified font handle.
void populateFamily(const QString &familyName) override
This function is called whenever a lazily populated family, populated through registerFontFamily(),...
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...
void populateFontDatabase() override
This function is called once at startup by Qt's internal font database.
QFont defaultFont() const override
Returns the default system font.
QFont * themeFont(QPlatformTheme::Font) const
bool populateFamilyAliases(const QString &missingFamily) override
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...
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
static QFont::Weight qtWeightFromCFWeight(float value)
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
WritingSystem
\value Any \value Latin \value Greek \value Cyrillic \value Armenian \value Hebrew \value Arabic \val...
static QFontEngineFT * create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData=QByteArray())
\reentrant
Definition qfont.h:22
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:25
@ AnyStyle
Definition qfont.h:31
@ Monospace
Definition qfont.h:33
@ System
Definition qfont.h:30
@ Serif
Definition qfont.h:27
@ Cursive
Definition qfont.h:32
@ Fantasy
Definition qfont.h:34
@ TypeWriter
Definition qfont.h:28
@ SansSerif
Definition qfont.h:26
HintingPreference
Definition qfont.h:55
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:83
@ Expanded
Definition qfont.h:91
@ Unstretched
Definition qfont.h:89
@ Condensed
Definition qfont.h:87
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:63
@ Normal
Definition qfont.h:67
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
static int getFaceIndexByStyleName(const QString &faceFileName, const QString &styleName)
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1086
T value(const Key &key) const noexcept
Definition qhash.h:1054
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:951
void reserve(qsizetype size)
Definition qlist.h:753
bool isEmpty() const
Definition qmap.h:269
const_iterator constBegin() const
Definition qmap.h:600
size_type size() const
Definition qmap.h:267
const_iterator constEnd() const
Definition qmap.h:604
static Q_CORE_EXPORT QOperatingSystemVersionBase current()
static constexpr QOperatingSystemVersionBase MacOSCatalina
\variable QOperatingSystemVersion::MacOSCatalina
static void repopulateFontDatabase()
Requests that the platform font database should be repopulated.
static QSupportedWritingSystems writingSystemsFromOS2Table(const char *os2Table, size_t length)
Helper function that determines the writing system support based on the contents of the OS/2 table in...
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.
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
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1369
The QSupportedWritingSystems class is used when registering fonts with the internal Qt fontdatabase.
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2468
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
float CGFloat
#define Q_FALLTHROUGH()
#define Q_DECL_UNUSED
QList< QString > QStringList
Constructs a string list that contains the given string, str.
AudioChannelLayoutTag tag
CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
static Q_DECL_UNUSED QDebug operator<<(QDebug debug, const FontDescription &fd)
CTFontDescriptorRef descriptorForFamily(const QString &familyName)
static const char languageForWritingSystem[][8]
static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
CTFontDescriptorRef descriptorForFontType(CTFontUIFontType uiType)
static NSString *const kQtFontDataAttribute
T * descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name)
CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint)
static const QCssKnownValue properties[NumProperties - 1]
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families)
static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
#define qCWarning(category,...)
#define qCDebug(category,...)
return ret
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLuint GLenum GLsizei length
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLenum face
GLfloat GLfloat f
GLuint64 GLenum GLint fd
GLuint name
GLenum GLsizeiptr const void * fontData
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLenum array
GLuint GLenum matrix
GLuint in
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
static double elapsed(qint64 after, qint64 before)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
QUrl url("example.com")
[constructor-url-reference]
QSupportedWritingSystems writingSystems
uint hintingPreference
Definition qfont_p.h:67
qreal pixelSize
Definition qfont_p.h:61
QMap< QFont::Tag, float > variableAxisValues
Definition qfont_p.h:58
QMap< QFont::Tag, float > variableAxes
The QFont::Tag type provides access to advanced font features.
Definition qfont.h:215
constexpr quint32 value() const noexcept
Returns the numerical value of this tag.
Definition qfont.h:227