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 <simon.hausmann@qt.io>
bb10
Tor Arne Vestbø 2017-03-30 14:35:26 +02:00
parent cd8d2c1743
commit 2b9ecfe69c
5 changed files with 102 additions and 73 deletions

View File

@ -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<QCoreTextFontEngine>::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
#ifndef QT_NO_FREETYPE
if (m_useFreeType) {
QCFType<CFURLRef> url(static_cast<CFURLRef>(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<QFontEngineFT>::fontEngine(const QFontDef &fontDef, void *usrPtr)
{
CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
QCFType<CFURLRef> url(static_cast<CFURLRef>(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<QCoreTextFontEngine>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
#ifndef QT_NO_FREETYPE
if (m_useFreeType) {
QByteArray *fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
QCFType<CGFontRef> 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<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR));
QCFType<CFURLRef> url(static_cast<CFURLRef>(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<QFontEngineFT>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
QByteArray *fontDataCopy = new QByteArray(fontData);
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy,
fontDataCopy->constData(), fontDataCopy->size(), releaseFontData);
QCFType<CGFontRef> 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<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR));
QCFType<CFURLRef> url(static_cast<CFURLRef>(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<QCoreTextFontEngine>::createDescriptorArrayForFont(CTFontRef font, const QString &fileName)
{
Q_UNUSED(fileName)
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
CFArrayAppendValue(array, descriptor);
return array;
}
#ifndef QT_NO_FREETYPE
template <>
CFArrayRef QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::createDescriptorArrayForFont(CTFontRef font, const QString &fileName)
{
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
Q_UNUSED(fileName)
#ifndef QT_NO_FREETYPE
// 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<CFURLRef> 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

View File

@ -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<QPlatformTheme::Font, QFont *> 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 T>
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

View File

@ -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 &paramList)
: 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 &paramList)
qWarning("Creating multiple Cocoa platform integrations is not supported");
mInstance = this;
#ifndef QT_NO_FREETYPE
if (mOptions.testFlag(UseFreeTypeFontEngine))
mFontDb.reset(new QCoreTextFontDatabaseEngineFactory<QFontEngineFT>);
else
#endif
mFontDb.reset(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>);
QString icStr = QPlatformInputContextFactory::requested();
icStr.isNull() ? mInputContext.reset(new QCocoaInputContext)
: mInputContext.reset(QPlatformInputContextFactory::create(icStr));

View File

@ -69,13 +69,15 @@
QT_BEGIN_NAMESPACE
class QCoreTextFontEngine;
QIOSIntegration *QIOSIntegration::instance()
{
return static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
}
QIOSIntegration::QIOSIntegration()
: m_fontDatabase(new QCoreTextFontDatabase)
: m_fontDatabase(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>)
#if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD)
, m_clipboard(new QIOSClipboard)
#endif

View File

@ -69,6 +69,8 @@
QT_BEGIN_NAMESPACE
class QCoreTextFontEngine;
static const char debugBackingStoreEnvironmentVariable[] = "QT_DEBUG_BACKINGSTORE";
static inline unsigned parseOptions(const QStringList &paramList)
@ -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<QCoreTextFontEngine>;
#else
m_fontDatabase = QPlatformIntegration::fontDatabase();
#endif