macOS: Defer population of localized font family aliases until needed

Getting the localized family name of a font involves quite a bit of work
internally in CoreText, e.g. creating and sorting font descriptors.

By deferring population of family aliases until a font match misses
we shave off ~1 second of startup time for applications that use non-
localized font families (most applications).

Change-Id: I021952c311c0d70d7769ccf764dbf997ebf30a4b
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Tor Arne Vestbø 2017-04-07 14:56:22 +02:00
parent 414c751c7d
commit 84b3f12310
4 changed files with 41 additions and 12 deletions

View File

@ -2678,6 +2678,10 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
QtFontDesc desc;
QList<int> blackListed;
int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases()) {
// 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);
}
if (index >= 0) {
engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
if (engine)

View File

@ -104,6 +104,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase
public:
virtual ~QPlatformFontDatabase();
virtual void populateFontDatabase();
virtual bool populateFamilyAliases() { return false; }
virtual void populateFamily(const QString &familyName);
virtual void invalidate();

View File

@ -113,6 +113,7 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context)
#endif
QCoreTextFontDatabase::QCoreTextFontDatabase()
: m_hasPopulatedAliases(false)
{
#ifdef Q_OS_MACX
QSettings appleSettings(QLatin1String("apple.com"));
@ -200,18 +201,8 @@ static CFArrayRef availableFamilyNames()
void QCoreTextFontDatabase::populateFontDatabase()
{
QCFType<CFArrayRef> familyNames = availableFamilyNames();
const int numberOfFamilies = CFArrayGetCount(familyNames);
for (int i = 0; i < numberOfFamilies; ++i) {
CFStringRef familyNameRef = (CFStringRef) CFArrayGetValueAtIndex(familyNames, i);
QString familyName = QString::fromCFString(familyNameRef);
QPlatformFontDatabase::registerFontFamily(familyName);
#if defined(Q_OS_OSX)
QString localizedFamilyName = QString::fromNSString([[NSFontManager sharedFontManager] localizedNameForFamily:(NSString*)familyNameRef face:nil]);
if (familyName != localizedFamilyName)
QPlatformFontDatabase::registerAliasToFontFamily(familyName, localizedFamilyName);
#endif
}
for (NSString *familyName in familyNames.as<const NSArray *>())
QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
// Force creating the theme fonts to get the descriptors in m_systemFontDescriptors
if (m_themeFonts.isEmpty())
@ -219,6 +210,31 @@ void QCoreTextFontDatabase::populateFontDatabase()
Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors)
populateFromDescriptor(fontDesc);
Q_ASSERT(!m_hasPopulatedAliases);
}
bool QCoreTextFontDatabase::populateFamilyAliases()
{
#if defined(Q_OS_MACOS)
if (m_hasPopulatedAliases)
return false;
QCFType<CFArrayRef> familyNames = availableFamilyNames();
for (NSString *familyName in familyNames.as<const NSArray *>()) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil];
if (![localizedFamilyName isEqual:familyName]) {
QPlatformFontDatabase::registerAliasToFontFamily(
QString::fromNSString(familyName),
QString::fromNSString(localizedFamilyName));
}
}
m_hasPopulatedAliases = true;
return true;
#else
return false;
#endif
}
void QCoreTextFontDatabase::populateFamily(const QString &familyName)
@ -239,6 +255,11 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName)
populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)), familyName);
}
void QCoreTextFontDatabase::invalidate()
{
m_hasPopulatedAliases = false;
}
struct FontDescription {
QCFString familyName;
QCFString styleName;

View File

@ -75,7 +75,9 @@ public:
QCoreTextFontDatabase();
~QCoreTextFontDatabase();
void populateFontDatabase() Q_DECL_OVERRIDE;
bool populateFamilyAliases() override;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
void invalidate() override;
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE;
@ -96,6 +98,7 @@ private:
mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors;
mutable QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
bool m_hasPopulatedAliases;
};
// Split out into separate template class so that the compiler doesn't have