10#import <IOKit/graphics/IOGraphicsLib.h>
11#elif defined(QT_PLATFORM_UIKIT)
12#import <UIKit/UIFont.h>
15#include <QtCore/qelapsedtimer.h>
16#include <QtCore/private/qcore_mac_p.h>
20#if QT_CONFIG(settings)
21#include <QtCore/QSettings>
23#include <QtCore/QtEndian>
25#include <QtGui/private/qfontengine_ft_p.h>
28#include <QtGui/qpa/qwindowsysteminterface.h>
78 : m_hasPopulatedAliases(
false)
80#if defined(Q_OS_MACOS)
82 qCDebug(lcQpaFonts) <<
"Fonts have changed";
95 return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
96 (
id)kCTFontFamilyNameAttribute: familyName.toNSString()
101 qCDebug(lcQpaFonts) <<
"Populating font database...";
103 if (lcQpaFonts().isDebugEnabled())
106 QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
107 for (NSString *familyName
in familyNames.as<
const NSArray *>())
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");
214 qCDebug(lcQpaFonts) <<
"Populating available families took" <<
elapsed.restart() <<
"ms";
216 populateThemeFonts();
218 for (
auto familyName : m_systemFontDescriptors.
keys()) {
219 for (
auto fontDescriptor : m_systemFontDescriptors.
value(familyName))
220 populateFromDescriptor(fontDescriptor, familyName);
224 m_systemFontDescriptors.
clear();
226 qCDebug(lcQpaFonts) <<
"Populating system descriptors took" <<
elapsed.restart() <<
"ms";
233#if defined(Q_OS_MACOS)
240 if (m_hasPopulatedAliases)
247 qCDebug(lcQpaFonts) <<
"Populating family aliases...";
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);
260 if (localizedFamily == missingFamily)
261 nonLocalizedMatch = nonLocalizedFamily;
264 m_hasPopulatedAliases =
true;
266 if (lcQpaFonts().isWarningEnabled()) {
268 QDebug msg(&warningMessage);
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;
274 msg <<
"Replace uses of missing font family" << missingFamily <<
"with one that exists";
275 msg <<
"to avoid this cost.";
294 qCDebug(lcQpaFonts) <<
"Populating family" << familyName;
300 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor,
nullptr);
301 if (!matchingFonts) {
302 qCWarning(lcQpaFonts) <<
"QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
306 const int numFonts = CFArrayGetCount(matchingFonts);
307 for (
int i = 0;
i < numFonts; ++
i)
308 populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts,
i)), familyName);
313 qCDebug(lcQpaFonts) <<
"Invalidating font database";
314 m_hasPopulatedAliases =
false;
317 m_themeFonts.
clear();
318 QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
333#ifndef QT_NO_DEBUG_STREAM
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
353 QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(
font, kCTFontTraitsAttribute);
356 fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(
font, kCTFontFamilyNameAttribute);
357 fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(
font, kCTFontStyleNameAttribute);
361 fd->fixedPitch =
false;
363 if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(
font, 0.0, 0)) {
365 CTFontRef tempFontRef = tempFont;
366 void *userData =
reinterpret_cast<void *
>(&tempFontRef);
368 QVarLengthArray<uchar, 128> os2Table(
length);
381 if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
382 double normalizedWeight;
383 if (CFNumberGetValue(weightValue, kCFNumberFloat64Type, &normalizedWeight))
386 if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
388 if (CFNumberGetValue(italic, kCFNumberDoubleType, &
d)) {
393 if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
395 if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &
d)) {
396 if (
d & kCTFontMonoSpaceTrait)
397 fd->fixedPitch =
true;
398 if (
d & kCTFontExpandedTrait)
400 else if (
d & kCTFontCondensedTrait)
406 if (QCFType<CFNumberRef>
size = (CFNumberRef) CTFontDescriptorCopyAttribute(
font, kCTFontSizeAttribute)) {
407 if (CFNumberIsFloatType(
size)) {
409 CFNumberGetValue(
size, kCFNumberDoubleType, &
d);
413 CFNumberGetValue(
size, kCFNumberIntType, &
i);
418 if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(
font, kCTFontLanguagesAttribute)) {
419 CFIndex
length = CFArrayGetCount(languages);
424 if (CFArrayContainsValue(languages, CFRangeMake(0,
length), lang))
440 if (applicationFont !=
nullptr) {
448 applicationFont->properties.append(
properties);
454 fd.fixedPitch,
fd.writingSystems, (
void *)
font);
462 return [
static_cast<T *
>(CTFontDescriptorCopyAttribute(descriptor,
name)) autorelease];
467 CTFontDescriptorRef descriptor =
static_cast<CTFontDescriptorRef
>(
handle);
468 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)
kQtFontDataAttribute)) {
472 CFRelease(descriptor);
481 static_cast<CTFontDescriptorRef
>(usrPtr));
494 QCFType<CFMutableDictionaryRef> variations = CFDictionaryCreateMutable(
nullptr,
496 &kCFTypeDictionaryKeyCallBacks,
497 &kCFTypeDictionaryValueCallBacks);
502 const float value =
it.value();
503 QCFType<CFNumberRef> tagRef = CFNumberCreate(
nullptr, kCFNumberIntType, &
tag);
504 QCFType<CFNumberRef> valueRef = CFNumberCreate(
nullptr, kCFNumberFloatType, &
value);
506 CFDictionarySetValue(variations, tagRef, valueRef);
508 QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(
nullptr,
509 (
const void **) &kCTFontVariationAttribute,
510 (
const void **) &variations,
512 &kCFTypeDictionaryKeyCallBacks,
513 &kCFTypeDictionaryValueCallBacks);
514 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes);
517 if (QCFType<CTFontRef>
font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &
matrix))
523#ifndef QT_NO_FREETYPE
527 CTFontDescriptorRef descriptor =
static_cast<CTFontDescriptorRef
>(usrPtr);
529 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)
kQtFontDataAttribute)) {
533 }
else if (NSURL *
url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) {
538 faceId.
filename = faceFileName.toUtf8();
540 QString styleName =
QCFString(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute));
557 return T::create(
fontData, pixelSize, hintingPreference, {});
561template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
562#ifndef QT_NO_FREETYPE
563template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
568 QCFType<CTFontRef>
font = CTFontCreateWithFontDescriptor(descriptor, 0.0,
nullptr);
570 qCWarning(lcQpaFonts) <<
"Failed to create fallback font for" << descriptor;
574 CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(
font,
575 (CFArrayRef)NSLocale.preferredLanguages));
578 qCWarning(lcQpaFonts) <<
"Failed to create fallback cascade list for" << descriptor;
591 if (!fontDescriptor) {
592 qCWarning(lcQpaFonts) <<
"Failed to create fallback font descriptor for" << family;
600 fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0);
609 static const CGFloat kDefaultSizeForRequestedUIType = 0.0;
610 QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(
611 uiType, kDefaultSizeForRequestedUIType,
nullptr);
612 return CTFontCopyFontDescriptor(ctFont);
628 default:
return nullptr;
636 qCDebug(lcQpaFonts).nospace() <<
"Resolving fallbacks families for"
638 <<
" style hint " << styleHint;
645 if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
649 qCDebug(lcQpaFonts) <<
"No fallbacks found. Using style hint instead";
652 CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
653 CFArrayAppendValue(tmp, styleDescriptor);
655 CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks)));
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));
668 if (!isFamilyPopulated(fallbackFamilyName)) {
671 if (isPrivateFontFamily(fallbackFamilyName))
674 registerFontFamily(fallbackFamilyName);
677 fallbackList.append(fallbackFamilyName);
685 for (
const char *family : {
".Apple Symbols Fallback",
".Noto Sans Universal" }) {
688 fallbackList.move(
index, fallbackList.size() - 1);
691#if defined(Q_OS_MACOS)
705 QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
706 if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
707 if (!isFamilyPopulated(hardcodedFont)) {
708 if (!m_privateFamilies.contains(hardcodedFont)) {
710 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor,
nullptr);
712 const int numFonts = CFArrayGetCount(matchingFonts);
713 for (
int i = 0;
i < numFonts; ++
i)
714 const_cast<QCoreTextFontDatabase *
>(
this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts,
i)),
717 fallbackList.append(hardcodedFont);
722 m_privateFamilies.insert(hardcodedFont);
725 fallbackList.append(hardcodedFont);
733 qCDebug(lcQpaFonts).nospace() <<
"Fallback families ordered by script " << script <<
": " << fallbackList;
740 QCFType<CFArrayRef> fonts;
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);
749 CTFontDescriptorRef descriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(descriptors,
i));
754 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
755 CFArrayAppendValue(
array, descriptor);
762 fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
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));
785 if (family.
startsWith(u
'.') || family ==
"LastResort"_L1 || m_privateFamilies.
contains(family))
795 return kCTFontUIFontSystem;
800 return kCTFontUIFontMenuItem;
803 return kCTFontUIFontEmphasizedSystem;
806 return kCTFontUIFontSystem;
809 return kCTFontUIFontToolTip;
812 return kCTFontUIFontSystem;
815 return kCTFontUIFontWindowTitle;
818 return kCTFontUIFontSystem;
821 return kCTFontUIFontSmallSystem;
824 return kCTFontUIFontPushButton;
828 return kCTFontUIFontSystem;
831 return kCTFontUIFontSmallToolbar;
834 return kCTFontUIFontSystem;
837 return kCTFontUIFontViews;
840 return kCTFontUIFontSmallSystem;
843 return kCTFontUIFontViews;
846 return kCTFontUIFontSystem;
849 return kCTFontUIFontViews;
852 return kCTFontUIFontSmallSystem;
855 return kCTFontUIFontMiniSystem;
858 return kCTFontUIFontUserFixedPitch;
861 return kCTFontUIFontSystem;
867#if defined(QT_PLATFORM_UIKIT)
870 NSString *textStyle = 0;
874 textStyle = UIFontTextStyleHeadline;
877 textStyle = UIFontTextStyleSubheadline;
881 textStyle = UIFontTextStyleFootnote;
884 textStyle = UIFontTextStyleCaption2;
891 textStyle = UIFontTextStyleBody;
896 UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
897 return static_cast<CTFontDescriptorRef
>(CFBridgingRetain(desc));
905void QCoreTextFontDatabase::populateThemeFonts()
909 if (!m_themeFonts.isEmpty())
913 if (lcQpaFonts().isDebugEnabled())
916 qCDebug(lcQpaFonts) <<
"Populating theme fonts...";
931 bool haveRegisteredFamily = m_systemFontDescriptors.contains(
fd.familyName);
932 qCDebug(lcQpaFonts) <<
"Got" << (haveRegisteredFamily ?
"already registered" :
"unseen")
933 <<
"family" <<
fd.familyName <<
"for" << themeFont;
935 if (!haveRegisteredFamily) {
938 QList<QCFType<CTFontDescriptorRef>> themeFontVariants;
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*>();
947 for (
int i = 0;
i < matchingDescriptorsCount; ++
i) {
948 auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors,
i));
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 }
961 addFontVariants(designTraitDescriptor);
965 if (themeFontVariants.isEmpty()) {
968 addFontVariants(familyDescriptor);
971 if (themeFontVariants.isEmpty()) {
972 qCDebug(lcQpaFonts) <<
"No theme font variants found, falling back to single variant descriptor";
973 themeFontVariants.append(fontDescriptor);
976 m_systemFontDescriptors.insert(
fd.familyName, themeFontVariants);
980 m_themeFonts.insert(themeFont,
font);
983 qCDebug(lcQpaFonts) <<
"Populating theme fonts took" <<
elapsed.restart() <<
"ms";
993 return m_themeFonts.value(
f,
nullptr);
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;
static bool isEqual(const aiUVTransform &a, const aiUVTransform &b)
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)
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())
StyleHint
Style hints are used by the \l{QFont}{font matching} algorithm to find an appropriate default family ...
Stretch
Predefined stretch values that follow the CSS naming convention.
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Style
This enum describes the different styles of glyphs that are used to display text.
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.
T value(const Key &key) const noexcept
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
void reserve(qsizetype size)
const_iterator constBegin() const
const_iterator constEnd() const
static Q_CORE_EXPORT QOperatingSystemVersionBase current()
static constexpr QOperatingSystemVersionBase MacOSCatalina
\variable QOperatingSystemVersion::MacOSCatalina
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
bool isNull() const
Returns true if this string is null; otherwise returns false.
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
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.
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
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,...)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLsizeiptr const void * fontData
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
#define qPrintable(string)
#define QStringLiteral(str)
static double elapsed(qint64 after, qint64 before)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QUrl url("example.com")
[constructor-url-reference]
QSupportedWritingSystems writingSystems
QMap< QFont::Tag, float > variableAxisValues
QMap< QFont::Tag, float > variableAxes
The QFont::Tag type provides access to advanced font features.
constexpr quint32 value() const noexcept
Returns the numerical value of this tag.