diff options
-rw-r--r-- | src/gui/kernel/qplatformtheme.h | 1 | ||||
-rw-r--r-- | src/gui/text/coretext/qcoretextfontdatabase.mm | 70 | ||||
-rw-r--r-- | src/gui/text/coretext/qcoretextfontdatabase_p.h | 5 |
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; }; |