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())
107 for (NSString *familyName
in familyNames.
as<
const NSArray *>())
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...";
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
356 fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(
font, kCTFontFamilyNameAttribute);
357 fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(
font, kCTFontStyleNameAttribute);
361 fd->fixedPitch =
false;
365 CTFontRef tempFontRef = tempFont;
366 void *userData =
reinterpret_cast<void *
>(&tempFontRef);
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)
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) {
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));
498#ifndef QT_NO_FREETYPE
502 CTFontDescriptorRef descriptor =
static_cast<CTFontDescriptorRef
>(usrPtr);
504 if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)
kQtFontDataAttribute)) {
508 }
else if (NSURL *
url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) {
513 faceId.
filename = faceFileName.toUtf8();
515 QString styleName =
QCFString(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute));
530 return T::create(
fontData, pixelSize, hintingPreference);
535#ifndef QT_NO_FREETYPE
543 qCWarning(lcQpaFonts) <<
"Failed to create fallback font for" << descriptor;
547 CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(
font,
548 (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:
@"AppleLanguages"]));
551 qCWarning(lcQpaFonts) <<
"Failed to create fallback cascade list for" << descriptor;
564 if (!fontDescriptor) {
565 qCWarning(lcQpaFonts) <<
"Failed to create fallback font descriptor for" << family;
573 fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0);
582 static const CGFloat kDefaultSizeForRequestedUIType = 0.0;
584 uiType, kDefaultSizeForRequestedUIType,
nullptr);
585 return CTFontCopyFontDescriptor(ctFont);
601 default:
return nullptr;
609 qCDebug(lcQpaFonts).nospace() <<
"Resolving fallbacks families for"
611 <<
" style hint " << styleHint;
618 if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
622 qCDebug(lcQpaFonts) <<
"No fallbacks found. Using style hint instead";
625 CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
626 CFArrayAppendValue(tmp, styleDescriptor);
628 CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks)));
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));
650 fallbackList.append(fallbackFamilyName);
658 for (
const char *family : {
".Apple Symbols Fallback",
".Noto Sans Universal" }) {
661 fallbackList.move(
index, fallbackList.size() - 1);
664#if defined(Q_OS_MACOS)
678 QString hardcodedFont = m_hardcodedFallbackFonts.
value(script);
679 if (!hardcodedFont.
isEmpty() && !fallbackList.contains(hardcodedFont)) {
681 if (!m_privateFamilies.
contains(hardcodedFont)) {
683 QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor,
nullptr);
685 const int numFonts = CFArrayGetCount(matchingFonts);
686 for (
int i = 0;
i < numFonts; ++
i)
687 const_cast<QCoreTextFontDatabase *
>(
this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts,
i)),
690 fallbackList.append(hardcodedFont);
695 m_privateFamilies.
insert(hardcodedFont);
698 fallbackList.append(hardcodedFont);
706 qCDebug(lcQpaFonts).nospace() <<
"Fallback families ordered by script " << script <<
": " << fallbackList;
721 descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
722 CFMutableArrayRef
array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
723 CFArrayAppendValue(
array, descriptor);
728 fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL);
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));
751 if (family.
startsWith(u
'.') || family ==
"LastResort"_L1 || m_privateFamilies.
contains(family))
761 return kCTFontUIFontSystem;
766 return kCTFontUIFontMenuItem;
769 return kCTFontUIFontEmphasizedSystem;
772 return kCTFontUIFontSystem;
775 return kCTFontUIFontToolTip;
778 return kCTFontUIFontSystem;
781 return kCTFontUIFontWindowTitle;
784 return kCTFontUIFontSystem;
787 return kCTFontUIFontSmallSystem;
790 return kCTFontUIFontPushButton;
794 return kCTFontUIFontSystem;
797 return kCTFontUIFontSmallToolbar;
800 return kCTFontUIFontSystem;
803 return kCTFontUIFontViews;
806 return kCTFontUIFontSmallSystem;
809 return kCTFontUIFontViews;
812 return kCTFontUIFontSystem;
815 return kCTFontUIFontViews;
818 return kCTFontUIFontSmallSystem;
821 return kCTFontUIFontMiniSystem;
824 return kCTFontUIFontUserFixedPitch;
827 return kCTFontUIFontSystem;
833#if defined(QT_PLATFORM_UIKIT)
836 NSString *textStyle = 0;
840 textStyle = UIFontTextStyleHeadline;
843 textStyle = UIFontTextStyleSubheadline;
847 textStyle = UIFontTextStyleFootnote;
850 textStyle = UIFontTextStyleCaption2;
857 textStyle = UIFontTextStyleBody;
862 UIFontDescriptor *
desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
863 return static_cast<CTFontDescriptorRef
>(CFBridgingRetain(
desc));
871void QCoreTextFontDatabase::populateThemeFonts()
879 if (lcQpaFonts().isDebugEnabled())
882 qCDebug(lcQpaFonts) <<
"Populating theme fonts...";
897 bool haveRegisteredFamily = m_systemFontDescriptors.
contains(
fd.familyName);
898 qCDebug(lcQpaFonts) <<
"Got" << (haveRegisteredFamily ?
"already registered" :
"unseen")
899 <<
"family" <<
fd.familyName <<
"for" <<
themeFont;
901 if (!haveRegisteredFamily) {
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*>();
913 for (
int i = 0;
i < matchingDescriptorsCount; ++
i) {
914 auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors,
i));
920 if (@available(macos 10.15, ios 13.0, *)) {
922 static const NSString *kUIFontDesignTrait =
@"NSCTFontUIFontDesignTrait";
923 if (
id uiFontDesignTrait = fontTraits.as<NSDictionary*>()[kUIFontDesignTrait]) {
925 CFDictionaryRef(@{ (
id)kCTFontTraitsAttribute: @{ kUIFontDesignTrait: uiFontDesignTrait }
927 addFontVariants(designTraitDescriptor);
931 if (themeFontVariants.
isEmpty()) {
934 addFontVariants(familyDescriptor);
937 if (themeFontVariants.
isEmpty()) {
938 qCDebug(lcQpaFonts) <<
"No theme font variants found, falling back to single variant descriptor";
939 themeFontVariants.
append(fontDescriptor);
942 m_systemFontDescriptors.
insert(
fd.familyName, themeFontVariants);
949 qCDebug(lcQpaFonts) <<
"Populating theme fonts took" <<
elapsed.restart() <<
"ms";
959 return m_themeFonts.
value(
f,
nullptr);
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;
static bool isEqual(const aiUVTransform &a, const aiUVTransform &b)
static QCFType constructFromGet(const T &t)
@ Script_EgyptianHieroglyphs
@ Script_InscriptionalParthian
@ Script_InscriptionalPahlavi
@ Script_CaucasianAlbanian
@ Script_MeroiticHieroglyphs
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)
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.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
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.
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
bool isEmpty() const noexcept
void append(parameter_type t)
static constexpr QOperatingSystemVersionBase MacOSCatalina
\variable QOperatingSystemVersion::MacOSCatalina
static QOperatingSystemVersion current()
[0]
bool contains(const T &value) const
iterator insert(const T &value)
\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 isNull() const
Returns true if this string is null; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
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.
void resize(qsizetype sz)
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
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,...)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
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
QList< Properties > properties