From c962c77044901a08d1ec15ffec81d48f87a35b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 3 Oct 2019 16:07:37 +0200 Subject: CoreText: Warn the user when family alias lookup slows down the application If the user specifies a font family in their application that doesn't exist in the system, or one that uses the localized family name, we will end up resolving the family alias for all fonts in the system, which typically adds 600-800ms of startup time. Let the user know when this happens. Change-Id: Id8d6f55028e37f681ec4a686df25d33240b5a30f Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontdatabase.cpp | 2 +- src/gui/text/qplatformfontdatabase.h | 2 +- .../fontdatabases/mac/qcoretextfontdatabase.mm | 50 +++++++++++++++++++--- .../fontdatabases/mac/qcoretextfontdatabase_p.h | 2 +- 4 files changed, 48 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index ce6bb0c347..261e1d831b 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2684,7 +2684,7 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) QtFontDesc desc; QList blackListed; int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed); - if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases()) { + if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) { // We populated familiy aliases (e.g. localized families), so try again index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed); } diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 38ba7f10b2..f79c5db625 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -104,7 +104,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); - virtual bool populateFamilyAliases() { return false; } + virtual bool populateFamilyAliases(const QString &missingFamily) { Q_UNUSED(missingFamily); return false; } virtual void populateFamily(const QString &familyName); virtual void invalidate(); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 201a82864f..4887a501ba 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -48,6 +48,8 @@ #import #endif +#include + #include "qcoretextfontdatabase_p.h" #include "qfontengine_coretext_p.h" #if QT_CONFIG(settings) @@ -113,39 +115,77 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() void QCoreTextFontDatabase::populateFontDatabase() { + qCDebug(lcQpaFonts) << "Populating font database..."; + QElapsedTimer elapsed; + if (lcQpaFonts().isDebugEnabled()) + elapsed.start(); + QCFType familyNames = CTFontManagerCopyAvailableFontFamilyNames(); for (NSString *familyName in familyNames.as()) QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName)); + qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms"; + // Force creating the theme fonts to get the descriptors in m_systemFontDescriptors if (m_themeFonts.isEmpty()) (void)themeFonts(); + qCDebug(lcQpaFonts) << "Resolving theme fonts took" << elapsed.restart() << "ms"; + Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors) populateFromDescriptor(fontDesc); + qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms"; + Q_ASSERT(!m_hasPopulatedAliases); } -bool QCoreTextFontDatabase::populateFamilyAliases() +bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily) { #if defined(Q_OS_MACOS) if (m_hasPopulatedAliases) return false; + // There's no API to go from a localized family name to its non-localized + // name, so we have to resort to enumerating all the available fonts and + // doing a reverse lookup. + + qCDebug(lcQpaFonts) << "Populating family aliases..."; + QElapsedTimer elapsed; + elapsed.start(); + + QString nonLocalizedMatch; QCFType familyNames = CTFontManagerCopyAvailableFontFamilyNames(); + NSFontManager *fontManager = NSFontManager.sharedFontManager; for (NSString *familyName in familyNames.as()) { - NSFontManager *fontManager = [NSFontManager sharedFontManager]; NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil]; if (![localizedFamilyName isEqual:familyName]) { - QPlatformFontDatabase::registerAliasToFontFamily( - QString::fromNSString(familyName), - QString::fromNSString(localizedFamilyName)); + QString nonLocalizedFamily = QString::fromNSString(familyName); + QString localizedFamily = QString::fromNSString(localizedFamilyName); + QPlatformFontDatabase::registerAliasToFontFamily(nonLocalizedFamily, localizedFamily); + if (localizedFamily == missingFamily) + nonLocalizedMatch = nonLocalizedFamily; } } m_hasPopulatedAliases = true; + + if (lcQpaFonts().isWarningEnabled()) { + QString warningMessage; + QDebug msg(&warningMessage); + + msg << "Populating font family aliases took" << elapsed.restart() << "ms."; + if (!nonLocalizedMatch.isNull()) + msg << "Replace uses of" << missingFamily << "with its non-localized name" << nonLocalizedMatch; + else + msg << "Replace uses of missing font family" << missingFamily << "with one that exists"; + msg << "to avoid this cost."; + + qCWarning(lcQpaFonts) << qPrintable(warningMessage); + } + return true; #else + Q_UNUSED(missingFamily); return false; #endif } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 45e74b99be..69ff454d1e 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -71,7 +71,7 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase() override; - bool populateFamilyAliases() override; + bool populateFamilyAliases(const QString &missingFamily) override; void populateFamily(const QString &familyName) override; void invalidate() override; -- cgit v1.2.3