Qt 6.x
The Qt SDK
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
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
89{
90 qDeleteAll(m_themeFonts);
91}
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
331};
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 = MAKE_TAG('O', 'S', '/', '2');
365 CTFontRef tempFontRef = tempFont;
366 void *userData = reinterpret_cast<void *>(&tempFontRef);
367 uint length = 128;
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{
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 if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix))
493 return new QCoreTextFontEngine(font, fontDef);
494
495 return nullptr;
496}
497
498#ifndef QT_NO_FREETYPE
499template <>
501{
502 CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
503
504 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) {
505 QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue);
507 static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
508 } else if (NSURL *url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) {
509 QFontEngine::FaceId faceId;
510
511 Q_ASSERT(url.fileURL);
512 QString faceFileName{QString::fromNSString(url.path)};
513 faceId.filename = faceFileName.toUtf8();
514
515 QString styleName = QCFString(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute));
516 faceId.index = QFreetypeFace::getFaceIndexByStyleName(faceFileName, styleName);
517
518 return QFontEngineFT::create(fontDef, faceId);
519 }
520 // We end up here with a descriptor does not contain Qt font data or kCTFontURLAttribute.
521 // Since the FT engine can't deal with a descriptor with just a NSFontNameAttribute,
522 // we should return nullptr.
523 return nullptr;
524}
525#endif
526
527template <class T>
529{
530 return T::create(fontData, pixelSize, hintingPreference);
531}
532
533// Explicitly instantiate so that we don't need the plugin to involve FreeType
535#ifndef QT_NO_FREETYPE
537#endif
538
539CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
540{
541 QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr);
542 if (!font) {
543 qCWarning(lcQpaFonts) << "Failed to create fallback font for" << descriptor;
544 return nullptr;
545 }
546
547 CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font,
548 (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:@"AppleLanguages"]));
549
550 if (!cascadeList) {
551 qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << descriptor;
552 return nullptr;
553 }
554
555 return cascadeList;
556}
557
559{
560 if (family.isEmpty())
561 return nullptr;
562
563 QCFType<CTFontDescriptorRef> fontDescriptor = descriptorForFamily(family);
564 if (!fontDescriptor) {
565 qCWarning(lcQpaFonts) << "Failed to create fallback font descriptor for" << family;
566 return nullptr;
567 }
568
569 // If the font is not available we want to fall back to the style hint.
570 // By creating a matching font descriptor we can verify whether the font
571 // is available or not, and avoid CTFontCreateWithFontDescriptor picking
572 // a default font for us based on incomplete information.
573 fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0);
574 if (!fontDescriptor)
575 return nullptr;
576
577 return fallbacksForDescriptor(fontDescriptor);
578}
579
580CTFontDescriptorRef descriptorForFontType(CTFontUIFontType uiType)
581{
582 static const CGFloat kDefaultSizeForRequestedUIType = 0.0;
583 QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(
584 uiType, kDefaultSizeForRequestedUIType, nullptr);
585 return CTFontCopyFontDescriptor(ctFont);
586}
587
588CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint)
589{
590 switch (styleHint) {
591 case QFont::SansSerif: return descriptorForFamily("Helvetica");
592 case QFont::Serif: return descriptorForFamily("Times New Roman");
593 case QFont::Monospace: return descriptorForFamily("Menlo");
594#ifdef Q_OS_MACOS
595 case QFont::Cursive: return descriptorForFamily("Apple Chancery");
596#endif
597 case QFont::Fantasy: return descriptorForFamily("Zapfino");
598 case QFont::TypeWriter: return descriptorForFamily("American Typewriter");
600 case QFont::System: return descriptorForFontType(kCTFontUIFontSystem);
601 default: return nullptr; // No matching font on this platform
602 }
603}
604
606{
607 Q_UNUSED(style);
608
609 qCDebug(lcQpaFonts).nospace() << "Resolving fallbacks families for"
610 << (!family.isEmpty() ? qPrintable(" family '%1' with"_L1.arg(family)) : "")
611 << " style hint " << styleHint;
612
614
615 QStringList fallbackList;
616
617 QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family);
618 if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
619 // We were not able to find a fallback for the specific family,
620 // or the family was empty, so we fall back to the style hint.
621 if (!family.isEmpty())
622 qCDebug(lcQpaFonts) << "No fallbacks found. Using style hint instead";
623
624 if (QCFType<CTFontDescriptorRef> styleDescriptor = descriptorForStyle(styleHint)) {
625 CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
626 CFArrayAppendValue(tmp, styleDescriptor);
627 QCFType<CFArrayRef> styleFallbacks = fallbacksForDescriptor(styleDescriptor);
628 CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks)));
629 fallbackFonts = tmp;
630 }
631 }
632
633 if (!fallbackFonts)
634 return fallbackList;
635
636 const int numberOfFallbacks = CFArrayGetCount(fallbackFonts);
637 for (int i = 0; i < numberOfFallbacks; ++i) {
638 auto fallbackDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fallbackFonts, i));
639 auto fallbackFamilyName = QCFString(CTFontDescriptorCopyAttribute(fallbackDescriptor, kCTFontFamilyNameAttribute));
640
641 if (!isFamilyPopulated(fallbackFamilyName)) {
642 // We need to populate, or at least register the fallback fonts,
643 // otherwise the Qt font database may not know they exist.
644 if (isPrivateFontFamily(fallbackFamilyName))
645 const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(fallbackDescriptor);
646 else
647 registerFontFamily(fallbackFamilyName);
648 }
649
650 fallbackList.append(fallbackFamilyName);
651 }
652
653 // Some fallback fonts will have have an order in the list returned
654 // by Core Text that would indicate they should be preferred for e.g.
655 // Arabic, or Emoji, while in reality only supporting a tiny subset
656 // of the required glyphs, or representing them by question marks.
657 // Move these to the end, so that the proper fonts are preferred.
658 for (const char *family : { ".Apple Symbols Fallback", ".Noto Sans Universal" }) {
659 int index = fallbackList.indexOf(QLatin1StringView(family));
660 if (index >= 0)
661 fallbackList.move(index, fallbackList.size() - 1);
662 }
663
664#if defined(Q_OS_MACOS)
665 // Since we are only returning a list of default fonts for the current language, we do not
666 // cover all Unicode completely. This was especially an issue for some of the common script
667 // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
668 // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
669 // of Unicode 2.1.
670 if (!fallbackList.contains(QStringLiteral("Arial Unicode MS")))
671 fallbackList.append(QStringLiteral("Arial Unicode MS"));
672 // Since some symbols (specifically Braille) are not in Arial Unicode MS, we
673 // add Apple Symbols to cover those too.
674 if (!fallbackList.contains(QStringLiteral("Apple Symbols")))
675 fallbackList.append(QStringLiteral("Apple Symbols"));
676 // Some Noto* fonts are not automatically enumerated by system, despite being the main
677 // fonts for their writing system.
678 QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
679 if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
680 if (!isFamilyPopulated(hardcodedFont)) {
681 if (!m_privateFamilies.contains(hardcodedFont)) {
682 QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
683 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
684 if (matchingFonts) {
685 const int numFonts = CFArrayGetCount(matchingFonts);
686 for (int i = 0; i < numFonts; ++i)
687 const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
688 hardcodedFont);
689
690 fallbackList.append(hardcodedFont);
691 }
692
693 // Register as private family even if the font is not found, in order to avoid
694 // redoing the check later. In later calls, the font will then just be ignored.
695 m_privateFamilies.insert(hardcodedFont);
696 }
697 } else {
698 fallbackList.append(hardcodedFont);
699 }
700 }
701#endif
702
704 fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
705
706 qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList;
707
708 return fallbackList;
709}
710
712{
714
715 if (!fontData.isEmpty()) {
716 QCFType<CFDataRef> fontDataReference = fontData.toRawCFData();
717 if (QCFType<CTFontDescriptorRef> descriptor = CTFontManagerCreateFontDescriptorFromData(fontDataReference)) {
718 // There's no way to get the data back out of a font descriptor created with
719 // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually.
720 NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] };
721 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
722 CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
723 CFArrayAppendValue(array, descriptor);
724 fonts = array;
725 }
726 } else {
728 fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
729 }
730
731 if (!fonts)
732 return QStringList();
733
734 QStringList families;
735 const int numFonts = CFArrayGetCount(fonts);
736 for (int i = 0; i < numFonts; ++i) {
737 CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i));
738 populateFromDescriptor(fontDescriptor, QString(), applicationFont);
739 QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute));
740 families.append(QString::fromCFString(familyName));
741 }
742
743 // Note: We don't do font matching via CoreText for application fonts, so we don't
744 // need to enable font matching for them via CTFontManagerEnableFontDescriptors.
745
746 return families;
747}
748
750{
751 if (family.startsWith(u'.') || family == "LastResort"_L1 || m_privateFamilies.contains(family))
752 return true;
753
755}
756
758{
759 switch (f) {
761 return kCTFontUIFontSystem;
762
766 return kCTFontUIFontMenuItem;
767
769 return kCTFontUIFontEmphasizedSystem;
770
772 return kCTFontUIFontSystem;
773
775 return kCTFontUIFontToolTip;
776
778 return kCTFontUIFontSystem;
779
781 return kCTFontUIFontWindowTitle;
782
784 return kCTFontUIFontSystem;
785
787 return kCTFontUIFontSmallSystem;
788
790 return kCTFontUIFontPushButton;
791
794 return kCTFontUIFontSystem;
795
797 return kCTFontUIFontSmallToolbar;
798
800 return kCTFontUIFontSystem;
801
803 return kCTFontUIFontViews;
804
806 return kCTFontUIFontSmallSystem;
807
809 return kCTFontUIFontViews;
810
812 return kCTFontUIFontSystem;
813
815 return kCTFontUIFontViews;
816
818 return kCTFontUIFontSmallSystem;
819
821 return kCTFontUIFontMiniSystem;
822
824 return kCTFontUIFontUserFixedPitch;
825
826 default:
827 return kCTFontUIFontSystem;
828 }
829}
830
832{
833#if defined(QT_PLATFORM_UIKIT)
834 // Use Dynamic Type to resolve theme fonts if possible, to get
835 // correct font sizes and style based on user configuration.
836 NSString *textStyle = 0;
837 switch (f) {
840 textStyle = UIFontTextStyleHeadline;
841 break;
843 textStyle = UIFontTextStyleSubheadline;
844 break;
847 textStyle = UIFontTextStyleFootnote;
848 break;
850 textStyle = UIFontTextStyleCaption2;
851 break;
853 // Fall back to regular code path, as iOS doesn't provide
854 // an appropriate text style for this theme font.
855 break;
856 default:
857 textStyle = UIFontTextStyleBody;
858 break;
859 }
860
861 if (textStyle) {
862 UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
863 return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc));
864 }
865#endif // Q_OS_IOS, Q_OS_TVOS, Q_OS_WATCHOS
866
867 // macOS default case and iOS fallback case
869}
870
871void QCoreTextFontDatabase::populateThemeFonts()
872{
874
875 if (!m_themeFonts.isEmpty())
876 return;
877
879 if (lcQpaFonts().isDebugEnabled())
880 elapsed.start();
881
882 qCDebug(lcQpaFonts) << "Populating theme fonts...";
883
888 getFontDescription(fontDescriptor, &fd);
889
890 // We might get here from QFontDatabase::systemFont() or QPlatformTheme::font(),
891 // before the font database has initialized itself and populated all available
892 // families. As a result, we can't populate the descriptor at this time, as that
893 // would result in the font database having > 0 families, which would result in
894 // skipping the initialization and population of all other font families. Instead
895 // we store the descriptors for later and populate them during populateFontDatabase().
896
897 bool haveRegisteredFamily = m_systemFontDescriptors.contains(fd.familyName);
898 qCDebug(lcQpaFonts) << "Got" << (haveRegisteredFamily ? "already registered" : "unseen")
899 << "family" << fd.familyName << "for" << themeFont;
900
901 if (!haveRegisteredFamily) {
902 // We need to register all weights and variants of the theme font,
903 // as the user might tweak the returned QFont before use.
904 QList<QCFType<CTFontDescriptorRef>> themeFontVariants;
905
906 auto addFontVariants = [&](CTFontDescriptorRef descriptor) {
907 QCFType<CFArrayRef> matchingDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, nullptr);
908 const int matchingDescriptorsCount = matchingDescriptors ? CFArrayGetCount(matchingDescriptors) : 0;
909 qCDebug(lcQpaFonts) << "Enumerating font variants based on" << id(descriptor)
910 << "resulted in" << matchingDescriptorsCount << "matching descriptors"
911 << matchingDescriptors.as<NSArray*>();
912
913 for (int i = 0; i < matchingDescriptorsCount; ++i) {
914 auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors, i));
915 themeFontVariants.append(QCFType<CTFontDescriptorRef>::constructFromGet(matchingDescriptor));
916 }
917 };
918
919 // Try populating the font variants based on its UI design trait, if available
920 if (@available(macos 10.15, ios 13.0, *)) {
921 auto fontTraits = QCFType<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute));
922 static const NSString *kUIFontDesignTrait = @"NSCTFontUIFontDesignTrait";
923 if (id uiFontDesignTrait = fontTraits.as<NSDictionary*>()[kUIFontDesignTrait]) {
924 QCFType<CTFontDescriptorRef> designTraitDescriptor = CTFontDescriptorCreateWithAttributes(
925 CFDictionaryRef(@{ (id)kCTFontTraitsAttribute: @{ kUIFontDesignTrait: uiFontDesignTrait }
926 }));
927 addFontVariants(designTraitDescriptor);
928 }
929 }
930
931 if (themeFontVariants.isEmpty()) {
932 // Fall back to populating variants based on the family name alone
933 QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(fd.familyName);
934 addFontVariants(familyDescriptor);
935 }
936
937 if (themeFontVariants.isEmpty()) {
938 qCDebug(lcQpaFonts) << "No theme font variants found, falling back to single variant descriptor";
939 themeFontVariants.append(fontDescriptor);
940 }
941
942 m_systemFontDescriptors.insert(fd.familyName, themeFontVariants);
943 }
944
945 QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic);
946 m_themeFonts.insert(themeFont, font);
947 }
948
949 qCDebug(lcQpaFonts) << "Populating theme fonts took" << elapsed.restart() << "ms";
950}
951
953{
954 // The code paths via QFontDatabase::systemFont() or QPlatformTheme::font()
955 // do not ensure that the font database has been populated, so we need to
956 // manually populate the theme fonts lazily here just in case.
957 const_cast<QCoreTextFontDatabase*>(this)->populateThemeFonts();
958
959 return m_themeFonts.value(f, nullptr);
960}
961
963{
965}
966
968{
969 return true;
970}
971
973{
975 static const unsigned short standard[] =
976 { 9, 10, 11, 12, 13, 14, 18, 24, 36, 48, 64, 72, 96, 144, 288, 0 };
977 ret.reserve(int(sizeof(standard) / sizeof(standard[0])));
978 const unsigned short *sizes = standard;
979 while (*sizes) ret << *sizes++;
980 return ret;
981}
982
984
static bool isEqual(const aiUVTransform &a, const aiUVTransform &b)
\inmodule QtCore
Definition qbytearray.h:57
static QCFType constructFromGet(const T &t)
X as() const
Script
Definition qchar.h:144
@ Script_Kharoshthi
Definition qchar.h:211
@ Script_OldTurkic
Definition qchar.h:247
@ Script_Balinese
Definition qchar.h:214
@ Script_OldItalic
Definition qchar.h:185
@ Script_OldHungarian
Definition qchar.h:294
@ Script_Newa
Definition qchar.h:301
@ Script_Batak
Definition qchar.h:251
@ Script_PahawhHmong
Definition qchar.h:270
@ Script_Marchen
Definition qchar.h:300
@ Script_MendeKikakui
Definition qchar.h:275
@ Script_Buginese
Definition qchar.h:205
@ Script_Vai
Definition qchar.h:224
@ Script_Mahajani
Definition qchar.h:273
@ Script_Ugaritic
Definition qchar.h:198
@ Script_Siddham
Definition qchar.h:284
@ Script_Nabataean
Definition qchar.h:279
@ Script_Duployan
Definition qchar.h:267
@ Script_HanifiRohingya
Definition qchar.h:314
@ Script_Bhaiksuki
Definition qchar.h:299
@ Script_Samaritan
Definition qchar.h:238
@ Script_Adlam
Definition qchar.h:298
@ Script_Sundanese
Definition qchar.h:221
@ Script_Takri
Definition qchar.h:262
@ Script_Hatran
Definition qchar.h:292
@ Script_Palmyrene
Definition qchar.h:280
@ Script_EgyptianHieroglyphs
Definition qchar.h:237
@ Script_PhagsPa
Definition qchar.h:217
@ Script_Miao
Definition qchar.h:259
@ Script_PsalterPahlavi
Definition qchar.h:283
@ Script_Tirhuta
Definition qchar.h:286
@ Script_Lisu
Definition qchar.h:239
@ Script_Avestan
Definition qchar.h:236
@ Script_Yi
Definition qchar.h:184
@ Script_Carian
Definition qchar.h:229
@ Script_Khudawadi
Definition qchar.h:285
@ Script_Kaithi
Definition qchar.h:248
@ Script_Cham
Definition qchar.h:231
@ Script_InscriptionalParthian
Definition qchar.h:245
@ Script_Lydian
Definition qchar.h:230
@ Script_Phoenician
Definition qchar.h:216
@ Script_InscriptionalPahlavi
Definition qchar.h:246
@ Script_WarangCiti
Definition qchar.h:287
@ Script_Mandaic
Definition qchar.h:253
@ Script_OldSouthArabian
Definition qchar.h:244
@ Script_Wancho
Definition qchar.h:322
@ Script_Osage
Definition qchar.h:302
@ Script_LinearA
Definition qchar.h:272
@ Script_OlChiki
Definition qchar.h:223
@ Script_Mongolian
Definition qchar.h:179
@ Script_Javanese
Definition qchar.h:241
@ Script_Tifinagh
Definition qchar.h:208
@ Script_PauCinHau
Definition qchar.h:281
@ Script_Hanunoo
Definition qchar.h:189
@ Script_ImperialAramaic
Definition qchar.h:243
@ Script_Buhid
Definition qchar.h:190
@ Script_Manichaean
Definition qchar.h:274
@ Script_OldPersian
Definition qchar.h:210
@ Script_MeroiticCursive
Definition qchar.h:257
@ Script_TaiViet
Definition qchar.h:235
@ Script_Cuneiform
Definition qchar.h:215
@ Script_Modi
Definition qchar.h:276
@ Script_Lycian
Definition qchar.h:228
@ Script_OldNorthArabian
Definition qchar.h:278
@ Script_Thaana
Definition qchar.h:156
@ Script_TaiTham
Definition qchar.h:234
@ Script_Saurashtra
Definition qchar.h:225
@ Script_CaucasianAlbanian
Definition qchar.h:265
@ Script_Lepcha
Definition qchar.h:222
@ Script_MeeteiMayek
Definition qchar.h:242
@ Script_OldPermic
Definition qchar.h:282
@ Script_SoraSompeng
Definition qchar.h:261
@ Script_Rejang
Definition qchar.h:227
@ Script_Tagbanwa
Definition qchar.h:191
@ Script_Ahom
Definition qchar.h:290
@ Script_BassaVah
Definition qchar.h:266
@ Script_SylotiNagri
Definition qchar.h:209
@ Script_Brahmi
Definition qchar.h:252
@ Script_Nko
Definition qchar.h:218
@ Script_MeroiticHieroglyphs
Definition qchar.h:258
@ Script_Multani
Definition qchar.h:293
@ Script_KayahLi
Definition qchar.h:226
@ Script_Limbu
Definition qchar.h:195
@ Script_LinearB
Definition qchar.h:197
@ Script_TaiLe
Definition qchar.h:196
@ Script_Coptic
Definition qchar.h:192
@ Script_Gothic
Definition qchar.h:186
@ Script_NewTaiLue
Definition qchar.h:206
@ Script_Glagolitic
Definition qchar.h:207
@ Script_Cypriot
Definition qchar.h:201
@ Script_Tagalog
Definition qchar.h:188
@ Script_Sharada
Definition qchar.h:260
@ Script_Elbasan
Definition qchar.h:268
@ Script_Osmanya
Definition qchar.h:200
@ Script_Khojki
Definition qchar.h:271
@ Script_Chakma
Definition qchar.h:256
@ Script_Mro
Definition qchar.h:277
@ Script_Bamum
Definition qchar.h:240
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 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:20
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Definition qfont.h:23
@ AnyStyle
Definition qfont.h:29
@ Monospace
Definition qfont.h:31
@ System
Definition qfont.h:28
@ Serif
Definition qfont.h:25
@ Cursive
Definition qfont.h:30
@ Fantasy
Definition qfont.h:32
@ TypeWriter
Definition qfont.h:26
@ SansSerif
Definition qfont.h:24
HintingPreference
Definition qfont.h:52
Stretch
Predefined stretch values that follow the CSS naming convention.
Definition qfont.h:80
@ Expanded
Definition qfont.h:88
@ Unstretched
Definition qfont.h:86
@ Condensed
Definition qfont.h:84
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:60
@ Normal
Definition qfont.h:64
Style
This enum describes the different styles of glyphs that are used to display text.
Definition qfont.h:73
@ StyleItalic
Definition qfont.h:75
@ StyleNormal
Definition qfont.h:74
static 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:1076
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
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:949
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:926
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
void append(parameter_type t)
Definition qlist.h:441
static constexpr QOperatingSystemVersionBase MacOSCatalina
\variable QOperatingSystemVersion::MacOSCatalina
static QOperatingSystemVersion current()
[0]
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,...
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
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:3354
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
void resize(qsizetype sz)
qsizetype length() const
T * data() noexcept
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
float CGFloat
#define Q_FALLTHROUGH()
#define Q_DECL_UNUSED
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]
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families)
#define MAKE_TAG(ch1, ch2, ch3, ch4)
#define qCWarning(category,...)
#define qCDebug(category,...)
return ret
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1363
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLuint GLenum GLsizei length
GLenum GLuint id
[7]
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:1391
#define QStringLiteral(str)
static double elapsed(qint64 after, qint64 before)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_UNUSED(x)
@ desc
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
QUrl url("example.com")
[constructor-url-reference]
QSupportedWritingSystems writingSystems
uint hintingPreference
Definition qfont_p.h:66
qreal pixelSize
Definition qfont_p.h:60