summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qplatformtheme.h1
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase.mm70
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase_p.h5
3 files changed, 63 insertions, 13 deletions
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 398ea2eae1..b29d23de6c 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -192,6 +192,7 @@ public:
EditorFont,
NFonts
};
+ Q_ENUM(Font)
enum StandardPixmap { // Keep in sync with QStyle::StandardPixmap
TitleBarMenuButton,
diff --git a/src/gui/text/coretext/qcoretextfontdatabase.mm b/src/gui/text/coretext/qcoretextfontdatabase.mm
index 47af17b04b..043272b4c2 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase.mm
+++ b/src/gui/text/coretext/qcoretextfontdatabase.mm
@@ -110,9 +110,6 @@ QCoreTextFontDatabase::QCoreTextFontDatabase()
QCoreTextFontDatabase::~QCoreTextFontDatabase()
{
qDeleteAll(m_themeFonts);
-
- for (CTFontDescriptorRef ref : qAsConst(m_systemFontDescriptors))
- CFRelease(ref);
}
void QCoreTextFontDatabase::populateFontDatabase()
@@ -130,8 +127,13 @@ void QCoreTextFontDatabase::populateFontDatabase()
populateThemeFonts();
- for (CTFontDescriptorRef fontDesc : m_systemFontDescriptors)
- populateFromDescriptor(fontDesc);
+ for (auto familyName : m_systemFontDescriptors.keys()) {
+ for (auto fontDescriptor : m_systemFontDescriptors.value(familyName))
+ populateFromDescriptor(fontDescriptor, familyName);
+ }
+
+ // The font database now has a reference to the original descriptors
+ m_systemFontDescriptors.clear();
qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms";
@@ -202,6 +204,8 @@ CTFontDescriptorRef descriptorForFamily(const char *familyName)
void QCoreTextFontDatabase::populateFamily(const QString &familyName)
{
+ qCDebug(lcQpaFonts) << "Populating family" << familyName;
+
// A single family might match several different fonts with different styles.
// We need to add them all so that the font database has the full picture,
// as once a family has been populated we will not populate it again.
@@ -749,6 +753,8 @@ static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
void QCoreTextFontDatabase::populateThemeFonts()
{
+ QMacAutoReleasePool pool;
+
if (!m_themeFonts.isEmpty())
return;
@@ -760,7 +766,7 @@ void QCoreTextFontDatabase::populateThemeFonts()
for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
QPlatformTheme::Font themeFont = static_cast<QPlatformTheme::Font>(f);
- CTFontDescriptorRef fontDescriptor = fontDescriptorFromTheme(themeFont);
+ QCFType<CTFontDescriptorRef> fontDescriptor = fontDescriptorFromTheme(themeFont);
FontDescription fd;
getFontDescription(fontDescriptor, &fd);
@@ -770,10 +776,54 @@ void QCoreTextFontDatabase::populateThemeFonts()
// would result in the font database having > 0 families, which would result in
// skipping the initialization and population of all other font families. Instead
// we store the descriptors for later and populate them during populateFontDatabase().
- if (!m_systemFontDescriptors.contains(fontDescriptor))
- m_systemFontDescriptors.insert(fontDescriptor);
- else
- CFRelease(fontDescriptor);
+
+ bool haveRegisteredFamily = m_systemFontDescriptors.contains(fd.familyName);
+ qCDebug(lcQpaFonts) << "Got" << (haveRegisteredFamily ? "already registered" : "unseen")
+ << "family" << fd.familyName << "for" << themeFont;
+
+ if (!haveRegisteredFamily) {
+ // We need to register all weights and variants of the theme font,
+ // as the user might tweak the returned QFont before use.
+ QList<QCFType<CTFontDescriptorRef>> themeFontVariants;
+
+ auto addFontVariants = [&](CTFontDescriptorRef descriptor) {
+ QCFType<CFArrayRef> matchingDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, nullptr);
+ const int matchingDescriptorsCount = CFArrayGetCount(matchingDescriptors);
+ qCDebug(lcQpaFonts) << "Enumerating font variants based on" << id(descriptor)
+ << "resulted in" << matchingDescriptorsCount << "matching descriptors"
+ << matchingDescriptors.as<NSArray*>();
+
+ for (int i = 0; i < matchingDescriptorsCount; ++i) {
+ auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors, i));
+ themeFontVariants.append(QCFType<CTFontDescriptorRef>::constructFromGet(matchingDescriptor));
+ }
+ };
+
+ // Try populating the font variants based on its UI design trait, if available
+ if (@available(macos 10.15, ios 13.0, *)) {
+ auto fontTraits = QCFType<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute));
+ static const NSString *kUIFontDesignTrait = @"NSCTFontUIFontDesignTrait";
+ if (id uiFontDesignTrait = fontTraits.as<NSDictionary*>()[kUIFontDesignTrait]) {
+ QCFType<CTFontDescriptorRef> designTraitDescriptor = CTFontDescriptorCreateWithAttributes(
+ CFDictionaryRef(@{ (id)kCTFontTraitsAttribute: @{ kUIFontDesignTrait: uiFontDesignTrait }
+ }));
+ addFontVariants(designTraitDescriptor);
+ }
+ }
+
+ if (themeFontVariants.isEmpty()) {
+ // Fall back to populating variants based on the family name alone
+ QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(fd.familyName);
+ addFontVariants(familyDescriptor);
+ }
+
+ if (themeFontVariants.isEmpty()) {
+ qCDebug(lcQpaFonts) << "No theme font variants found, falling back to single variant descriptor";
+ themeFontVariants.append(fontDescriptor);
+ }
+
+ m_systemFontDescriptors.insert(fd.familyName, themeFontVariants);
+ }
QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic);
m_themeFonts.insert(themeFont, font);
diff --git a/src/gui/text/coretext/qcoretextfontdatabase_p.h b/src/gui/text/coretext/qcoretextfontdatabase_p.h
index a6f93dd14a..b8fa87996d 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase_p.h
+++ b/src/gui/text/coretext/qcoretextfontdatabase_p.h
@@ -86,9 +86,6 @@ public:
// For iOS and macOS platform themes
QFont *themeFont(QPlatformTheme::Font) const;
-protected:
- mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors;
-
private:
void populateThemeFonts();
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString(), QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr);
@@ -97,6 +94,8 @@ private:
mutable QString defaultFontName;
QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
+ QHash<QString, QList<QCFType<CTFontDescriptorRef>>> m_systemFontDescriptors;
+
bool m_hasPopulatedAliases;
};