From 2b9ecfe69c01085fbafb6c3c83b7ca4a5f564f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Mar 2017 14:35:26 +0200 Subject: macOS: Split out font engine creation from QCoreTextFontDatabase The Core Text font database can produce both Core Text and FreeType font engines. Refactor the code a bit so that the actual factory methods that differ between the two stand out, and do not require a granular runtime check in each method. Change-Id: Ib70f76f4a9001a8108d87c1101a50699a6ea8f55 Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 129 +++++++++++---------- .../fontdatabases/mac/qcoretextfontdatabase_p.h | 24 ++-- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 +- src/plugins/platforms/ios/qiosintegration.mm | 4 +- .../platforms/minimal/qminimalintegration.cpp | 4 +- 5 files changed, 101 insertions(+), 72 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index b8097702ed..fcc94c40b3 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -112,12 +112,8 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context) } #endif -QCoreTextFontDatabase::QCoreTextFontDatabase(bool useFreeType) -#ifndef QT_NO_FREETYPE - : m_useFreeType(useFreeType) -#endif +QCoreTextFontDatabase::QCoreTextFontDatabase() { - Q_UNUSED(useFreeType) #ifdef Q_OS_MACX QSettings appleSettings(QLatin1String("apple.com")); QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold")); @@ -393,35 +389,24 @@ static QByteArray filenameForCFUrl(CFURLRef url) extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); -QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) { CTFontDescriptorRef descriptor = static_cast(usrPtr); -#ifndef QT_NO_FREETYPE - if (m_useFreeType) { - QCFType url(static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))); - - QByteArray filename; - if (url) - filename = filenameForCFUrl(url); - - return freeTypeFontEngine(f, filename); - } -#endif - // Since we do not pass in the destination DPI to CoreText when making // the font, we need to pass in a point size which is scaled to include // the DPI. The default DPI for the screen is 72, thus the scale factor // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi, // the pixelSize is actually the scaled point size for the destination // DPI, and we can use that directly. - qreal scaledPointSize = f.pixelSize; + qreal scaledPointSize = fontDef.pixelSize; - CGAffineTransform matrix = qt_transform_from_fontdef(f); + CGAffineTransform matrix = qt_transform_from_fontdef(fontDef); CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); if (font) { - QFontEngine *engine = new QCoreTextFontEngine(font, f); - engine->fontDef = f; + QFontEngine *engine = new QCoreTextFontEngine(font, fontDef); + engine->fontDef = fontDef; CFRelease(font); return engine; } @@ -429,6 +414,24 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) return NULL; } +#ifndef QT_NO_FREETYPE +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) +{ + CTFontDescriptorRef descriptor = static_cast(usrPtr); + + QCFType url(static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))); + + QByteArray filename; + if (url) + filename = filenameForCFUrl(url); + + QFontEngine::FaceId faceId; + faceId.filename = filename; + return QFontEngineFT::create(fontDef, faceId); +} +#endif + static void releaseFontData(void* info, const void* data, size_t size) { Q_UNUSED(data); @@ -436,31 +439,9 @@ static void releaseFontData(void* info, const void* data, size_t size) delete (QByteArray*)info; } -QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { -#ifndef QT_NO_FREETYPE - if (m_useFreeType) { - QByteArray *fontDataCopy = new QByteArray(fontData); - QCFType dataProvider = CGDataProviderCreateWithData(fontDataCopy, - fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - QCFType cgFont(CGFontCreateWithDataProvider(dataProvider)); - - if (!cgFont) { - qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); - return Q_NULLPTR; - } - - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontDef.hintingPreference = hintingPreference; - CGAffineTransform transform = qt_transform_from_fontdef(fontDef); - QCFType ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR)); - QCFType url(static_cast(CTFontCopyAttribute(ctFont, kCTFontURLAttribute))); - return freeTypeFontEngine(fontDef, filenameForCFUrl(url), fontData); - } -#endif - Q_UNUSED(hintingPreference); QByteArray* fontDataCopy = new QByteArray(fontData); @@ -483,6 +464,34 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal return fontEngine; } +#ifndef QT_NO_FREETYPE +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QByteArray *fontDataCopy = new QByteArray(fontData); + QCFType dataProvider = CGDataProviderCreateWithData(fontDataCopy, + fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); + QCFType cgFont(CGFontCreateWithDataProvider(dataProvider)); + + if (!cgFont) { + qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); + return Q_NULLPTR; + } + + QFontDef fontDef; + fontDef.pixelSize = pixelSize; + fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); + fontDef.hintingPreference = hintingPreference; + CGAffineTransform transform = qt_transform_from_fontdef(fontDef); + QCFType ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR)); + QCFType url(static_cast(CTFontCopyAttribute(ctFont, kCTFontURLAttribute))); + + QFontEngine::FaceId faceId; + faceId.filename = filenameForCFUrl(url); + return QFontEngineFT::create(fontDef, faceId, fontData); +} +#endif + QFont::StyleHint styleHintFromNSString(NSString *style) { if ([style isEqual: @"sans-serif"]) @@ -615,17 +624,27 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo return fallbackLists[styleLookupKey.arg(styleHint)]; } -CFArrayRef QCoreTextFontDatabase::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) +template <> +CFArrayRef QCoreTextFontDatabaseEngineFactory::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) { + Q_UNUSED(fileName) CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); QCFType descriptor = CTFontCopyFontDescriptor(font); + CFArrayAppendValue(array, descriptor); + return array; +} - Q_UNUSED(fileName) #ifndef QT_NO_FREETYPE +template <> +CFArrayRef QCoreTextFontDatabaseEngineFactory::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) +{ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + QCFType descriptor = CTFontCopyFontDescriptor(font); + // The physical font source URL (usually a local file or Qt resource) is only required for // FreeType, when using non-system fonts, and needs some hackery to attach in a format // agreeable to OSX. - if (m_useFreeType && !fileName.isEmpty()) { + if (!fileName.isEmpty()) { QCFType fontURL; if (fileName.startsWith(QLatin1String(":/"))) { @@ -642,11 +661,11 @@ CFArrayRef QCoreTextFontDatabase::createDescriptorArrayForFont(CTFontRef font, c CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL); descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes); } -#endif CFArrayAppendValue(array, descriptor); return array; } +#endif QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { @@ -884,15 +903,5 @@ void QCoreTextFontDatabase::removeApplicationFonts() m_applicationFonts.clear(); } -#ifndef QT_NO_FREETYPE -QFontEngine *QCoreTextFontDatabase::freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename, - const QByteArray &fontData) -{ - QFontEngine::FaceId faceId; - faceId.filename = filename; - return QFontEngineFT::create(fontDef, faceId, fontData); -} -#endif - QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index c093d903af..8edf60b5fa 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -72,13 +72,11 @@ QT_BEGIN_NAMESPACE class QCoreTextFontDatabase : public QPlatformFontDatabase { public: - QCoreTextFontDatabase(bool useFreeType = false); + QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_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; void releaseHandle(void *handle) Q_DECL_OVERRIDE; @@ -93,13 +91,8 @@ public: private: void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString()); - CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName); + virtual CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName) = 0; -#ifndef QT_NO_FREETYPE - bool m_useFreeType; - QFontEngine *freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename, - const QByteArray &fontData = QByteArray()); -#endif mutable QString defaultFontName; void removeApplicationFonts(); @@ -109,6 +102,19 @@ private: mutable QHash m_themeFonts; }; +// Split out into separate template class so that the compiler doesn't have +// to generate code for each override in QCoreTextFontDatabase for each T. + +template +class QCoreTextFontDatabaseEngineFactory : public QCoreTextFontDatabase +{ +public: + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override; +protected: + CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName) override; +}; + QT_END_NAMESPACE #endif // QCORETEXTFONTDATABASE_H diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 9dfcb82151..d48ec8c6f7 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -69,6 +69,9 @@ static void initResources() QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; +class QFontEngineFT; + QCocoaScreen::QCocoaScreen(int screenIndex) : QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0) { @@ -302,7 +305,7 @@ QCocoaIntegration *QCocoaIntegration::mInstance = 0; QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) : mOptions(parseOptions(paramList)) - , mFontDb(new QCoreTextFontDatabase(mOptions.testFlag(UseFreeTypeFontEngine))) + , mFontDb(0) #ifndef QT_NO_ACCESSIBILITY , mAccessibility(new QCocoaAccessibility) #endif @@ -318,6 +321,13 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) qWarning("Creating multiple Cocoa platform integrations is not supported"); mInstance = this; +#ifndef QT_NO_FREETYPE + if (mOptions.testFlag(UseFreeTypeFontEngine)) + mFontDb.reset(new QCoreTextFontDatabaseEngineFactory); + else +#endif + mFontDb.reset(new QCoreTextFontDatabaseEngineFactory); + QString icStr = QPlatformInputContextFactory::requested(); icStr.isNull() ? mInputContext.reset(new QCocoaInputContext) : mInputContext.reset(QPlatformInputContextFactory::create(icStr)); diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index fbf167b514..5c42828885 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -69,13 +69,15 @@ QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; + QIOSIntegration *QIOSIntegration::instance() { return static_cast(QGuiApplicationPrivate::platformIntegration()); } QIOSIntegration::QIOSIntegration() - : m_fontDatabase(new QCoreTextFontDatabase) + : m_fontDatabase(new QCoreTextFontDatabaseEngineFactory) #if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD) , m_clipboard(new QIOSClipboard) #endif diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 820c4891ca..ca33689cd7 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -69,6 +69,8 @@ QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; + static const char debugBackingStoreEnvironmentVariable[] = "QT_DEBUG_BACKINGSTORE"; static inline unsigned parseOptions(const QStringList ¶mList) @@ -140,7 +142,7 @@ QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const m_fontDatabase = new QWindowsFontDatabase; } #elif defined(Q_OS_DARWIN) - m_fontDatabase = new QCoreTextFontDatabase; + m_fontDatabase = new QCoreTextFontDatabaseEngineFactory; #else m_fontDatabase = QPlatformIntegration::fontDatabase(); #endif -- cgit v1.2.3