diff options
author | Tor Arne Vestbø <tor.arne.vestbo@digia.com> | 2014-03-06 14:58:18 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-11 03:39:39 +0100 |
commit | c466f2ed464a06ac6427df6135d3e905011aa50e (patch) | |
tree | 8422f7d8fd71667fda85380d86c586dc0e5569ec /src/platformsupport/fontdatabases | |
parent | 800232e1d3ebfbac28d07014a3c646ea00fcf6ad (diff) |
Remove need to populate font database on OS X to get fallback families
Populating the whole database takes a while, and it's very easy to trigger
the fallback family code path through eg. matching or getting the default
font family from QFont.
Instead of relying on populate to resolve family name to a PostScript name
(which was required when using CTFontCreateWithName), we instead use the
CTFontDescriptorCreateWithAttributes() function to create a descriptor
based on the family name, and then use CTFontCreateWithFontDescriptor().
The other way around, we use CTFontDescriptorCreateWithNameAndSize, and
then pull out the family name from the descriptor. The need for creating
a CTFont for private fonts (eg '.Apple Symbols Fallback') does not seem
necessary anymore, as tested on 10.7-10.9.
The disadvantage of creating font descriptors instead of re-using the
data computed by population is that we're doing the same work twice,
but the end result is making the font database more lazy, and the 80%
use-case is assumed to be that you're only interested in the fallback
of a small number of fonts, which means you don't want to populate all
of the fonts in the system (taking about 1100ms on the test system).
Looking up the fallback of a single family or style now takes about
15-25ms.
Task-number: QTBUG-37165
Change-Id: I6b904dbe796a3f236919d778d0168fdef9a20e69
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/platformsupport/fontdatabases')
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 56 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h | 3 |
2 files changed, 14 insertions, 45 deletions
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index f37e7a1db2..102109e33c 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -199,12 +199,6 @@ void QCoreTextFontDatabase::populateFontDatabase() [pool release]; } -void QCoreTextFontDatabase::invalidate() -{ - psNameToFamily.clear(); - familyNameToPsName.clear(); -} - void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) { QString foundryName = QStringLiteral("CoreText"); @@ -271,12 +265,6 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, true /* antialiased */, true /* scalable */, pixelSize, fixedPitch, writingSystems, (void *) font); - - // We need to map back and forth between PostScript-names and family-names for fallback list construction - CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute); - psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName; - familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName); - CFRelease(psName); } void QCoreTextFontDatabase::releaseHandle(void *handle) @@ -356,25 +344,15 @@ QFont::StyleHint styleHintFromNSString(NSString *style) return QFont::AnyStyle; } -static QString familyNameFromPostScriptName(QHash<QString, QString> &psNameToFamily, - NSString *psName) +static QString familyNameFromPostScriptName(NSString *psName) { - QString name = QCFString::toQString(psName); - if (psNameToFamily.contains(name)) - return psNameToFamily[name]; - else { - // Some of the font name in DefaultFontFallbacks.plist are hidden fonts like AquaHiraKaku, - // their family name begins with a dot, like ".AquaHiraKaku" or ".Apple Symbols Fallback", - // the only way (I've found) to get it are actually creating a CTFont with them. We only - // need to do it once though. - QCFType<CTFontRef> font = CTFontCreateWithName((CFStringRef) psName, 12.0, NULL); - if (font) { - QCFString family = CTFontCopyFamilyName(font); - psNameToFamily[name] = family; - return family; - } - return name; - } + QCFType<CTFontDescriptorRef> fontDescriptor = (CTFontDescriptorRef) CTFontDescriptorCreateWithNameAndSize((CFStringRef)psName, 12.0); + QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(fontDescriptor, kCTFontFamilyNameAttribute, 0); + QString name = QCFString::toQString(familyName); + if (name.isEmpty()) + qWarning() << "QCoreTextFontDatabase: Failed to resolve family name for PostScript name " << QCFString::toQString((CFStringRef)psName); + + return name; } QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const @@ -395,12 +373,10 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo if (fallbackLists.contains(family)) return fallbackLists.value(family); - if (familyNameToPsName.isEmpty()) - const_cast<QCoreTextFontDatabase*>(this)->populateFontDatabase(); - - if (familyNameToPsName.contains(family)) { - QCFType<CTFontRef> font = CTFontCreateWithName(QCFString(familyNameToPsName[family]), 12.0, NULL); - if (font) { + QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(family)); + if (QCFType<CTFontDescriptorRef> fontDescriptor = CTFontDescriptorCreateWithAttributes(attributes)) { + if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(fontDescriptor, 12.0, 0)) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"]; @@ -432,10 +408,6 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo static bool didPopulateStyleFallbacks = false; if (!didPopulateStyleFallbacks) { #if defined(Q_OS_MACX) - // Ensure we have the psNameToFamily mapping set up - if (psNameToFamily.isEmpty()) - const_cast<QCoreTextFontDatabase*>(this)->populateFontDatabase(); - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"]; @@ -451,10 +423,10 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort context: languages]; for (NSArray *map in langs) - fallbackList.append(familyNameFromPostScriptName(psNameToFamily, [map objectAtIndex: 1])); + fallbackList.append(familyNameFromPostScriptName([map objectAtIndex: 1])); } else if ([item isKindOfClass: [NSString class]]) - fallbackList.append(familyNameFromPostScriptName(psNameToFamily, item)); + fallbackList.append(familyNameFromPostScriptName(item)); } if (QCoreTextFontEngine::supportsColorGlyphs()) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 5b2fc2ed7e..c6fc791503 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -72,7 +72,6 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase(); - void invalidate() Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); @@ -86,8 +85,6 @@ private: void populateFromDescriptor(CTFontDescriptorRef font); mutable QString defaultFontName; - mutable QHash<QString, QString> psNameToFamily; - mutable QHash<QString, QString> familyNameToPsName; void removeApplicationFonts(); |