diff options
Diffstat (limited to 'src/platformsupport/fontdatabases')
27 files changed, 374 insertions, 423 deletions
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 98dce03ae6..969a9c17e0 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -677,6 +677,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; + // FIXME: Unify with logic in QFontEngineFT::create() QFontEngineFT *engine = new QFontEngineFT(f); engine->face_id = fid; @@ -692,7 +693,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontEngineFT *engine = static_cast<QFontEngineFT*>(QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); + QFontEngineFT *engine = static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); if (engine == 0) return 0; @@ -844,7 +845,7 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const { - QString resolved = QBasicFontDatabase::resolveFontFamilyAlias(family); + QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family); if (!resolved.isEmpty() && resolved != family) return resolved; FcPattern *pattern = FcPatternCreate(); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index f7e3172b65..6a3261de30 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -52,13 +52,13 @@ // #include <qpa/qplatformfontdatabase.h> -#include <QtFontDatabaseSupport/private/qbasicfontdatabase_p.h> +#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h> QT_BEGIN_NAMESPACE class QFontEngineFT; -class QFontconfigDatabase : public QBasicFontDatabase +class QFontconfigDatabase : public QFreeTypeFontDatabase { public: void populateFontDatabase() Q_DECL_OVERRIDE; diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro index 9376c3b702..d2726d08a0 100644 --- a/src/platformsupport/fontdatabases/fontdatabases.pro +++ b/src/platformsupport/fontdatabases/fontdatabases.pro @@ -7,11 +7,11 @@ CONFIG += static internal_module DEFINES += QT_NO_CAST_FROM_ASCII PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h -darwin:!if(watchos:CONFIG(simulator, simulator|device)) { +darwin { include($$PWD/mac/coretext.pri) } else { qtConfig(freetype) { - include($$PWD/basic/basic.pri) + include($$PWD/freetype/freetype.pri) } unix { diff --git a/src/platformsupport/fontdatabases/basic/basic.pri b/src/platformsupport/fontdatabases/freetype/freetype.pri index 0617bf74d7..7bda687ef4 100644 --- a/src/platformsupport/fontdatabases/basic/basic.pri +++ b/src/platformsupport/fontdatabases/freetype/freetype.pri @@ -1,9 +1,9 @@ HEADERS += \ - $$PWD/qbasicfontdatabase_p.h \ + $$PWD/qfreetypefontdatabase_p.h \ $$PWD/qfontengine_ft_p.h SOURCES += \ - $$PWD/qbasicfontdatabase.cpp \ + $$PWD/qfreetypefontdatabase.cpp \ $$PWD/qfontengine_ft.cpp QMAKE_USE_PRIVATE += freetype diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index de6da88245..39b6814a57 100644 --- a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -44,6 +44,10 @@ #include "qfontengine_ft_p.h" #include "private/qimage_p.h" #include <private/qstringiterator_p.h> +#include <qguiapplication.h> +#include <qscreen.h> +#include <qpa/qplatformscreen.h> +#include <QtCore/QUuid> #ifndef QT_NO_FREETYPE @@ -61,17 +65,19 @@ #include FT_TRUETYPE_TABLES_H #include FT_TYPE1_TABLES_H #include FT_GLYPH_H +#include FT_MODULE_H #if defined(FT_LCD_FILTER_H) #include FT_LCD_FILTER_H +#define QT_USE_FREETYPE_LCDFILTER #endif #if defined(FT_CONFIG_OPTIONS_H) #include FT_CONFIG_OPTIONS_H #endif -#if defined(FT_LCD_FILTER_H) -#define QT_USE_FREETYPE_LCDFILTER +#if defined(FT_FONT_FORMATS_H) +#include FT_FONT_FORMATS_H #endif #ifdef QT_LINUXBASE @@ -151,6 +157,14 @@ QtFreetypeData *qt_getFreetypeData() QtFreetypeData *&freetypeData = theFreetypeData()->localData(); if (!freetypeData) freetypeData = new QtFreetypeData; + if (!freetypeData->library) { + FT_Init_FreeType(&freetypeData->library); +#if defined(FT_FONT_FORMATS_H) + // Freetype defaults to disabling stem-darkening on CFF, we re-enable it. + FT_Bool no_darkening = false; + FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening); +#endif + } return freetypeData; } #endif @@ -158,8 +172,7 @@ QtFreetypeData *qt_getFreetypeData() FT_Library qt_getFreetype() { QtFreetypeData *freetypeData = qt_getFreetypeData(); - if (!freetypeData->library) - FT_Init_FreeType(&freetypeData->library); + Q_ASSERT(freetypeData->library); return freetypeData->library; } @@ -218,8 +231,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, return 0; QtFreetypeData *freetypeData = qt_getFreetypeData(); - if (!freetypeData->library) - FT_Init_FreeType(&freetypeData->library); QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0); if (freetype) { @@ -659,6 +670,93 @@ static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, } } +static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint() +{ + static int type = -1; + if (type == -1) { + if (QScreen *screen = QGuiApplication::primaryScreen()) + type = screen->handle()->subpixelAntialiasingTypeHint(); + } + return static_cast<QFontEngine::SubpixelAntialiasingType>(type); +} + +QFontEngineFT *QFontEngineFT::create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData) +{ + QScopedPointer<QFontEngineFT> engine(new QFontEngineFT(fontDef)); + + QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; + const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + + if (antialias) { + QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); + if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { + format = QFontEngineFT::Format_A8; + engine->subpixelType = QFontEngine::Subpixel_None; + } else { + format = QFontEngineFT::Format_A32; + engine->subpixelType = subpixelType; + } + } + + if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { + qWarning("QFontEngineFT: Failed to create FreeType font engine"); + return nullptr; + } + + engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); + return engine.take(); +} + +namespace { + class QFontEngineFTRawData: public QFontEngineFT + { + public: + QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) + { + } + + void updateFamilyNameAndStyle() + { + fontDef.family = QString::fromLatin1(freetype->face->family_name); + + if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) + fontDef.style = QFont::StyleItalic; + + if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) + fontDef.weight = QFont::Bold; + } + + bool initFromData(const QByteArray &fontData) + { + FaceId faceId; + faceId.filename = ""; + faceId.index = 0; + faceId.uuid = QUuid::createUuid().toByteArray(); + + return init(faceId, true, Format_None, fontData); + } + }; +} + +QFontEngineFT *QFontEngineFT::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QFontDef fontDef; + fontDef.pixelSize = pixelSize; + fontDef.stretch = QFont::Unstretched; + fontDef.hintingPreference = hintingPreference; + + QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); + if (!fe->initFromData(fontData)) { + delete fe; + return 0; + } + + fe->updateFamilyNameAndStyle(); + fe->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); + + return fe; +} + QFontEngineFT::QFontEngineFT(const QFontDef &fd) : QFontEngine(Freetype) { @@ -687,6 +785,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) cacheEnabled = env.isEmpty() || env.toInt() == 0; m_subPixelPositionCount = 4; forceAutoHint = false; + stemDarkeningDriver = false; } QFontEngineFT::~QFontEngineFT() @@ -798,6 +897,17 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, } } } +#if defined(FT_FONT_FORMATS_H) + const char *fmt = FT_Get_Font_Format(face); + if (fmt && qstrncmp(fmt, "CFF", 4) == 0) { + FT_Bool no_stem_darkening = true; + FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening); + if (err == FT_Err_Ok) + stemDarkeningDriver = !no_stem_darkening; + else + stemDarkeningDriver = false; + } +#endif fontDef.styleName = QString::fromUtf8(face->style_name); @@ -841,6 +951,11 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style) default_hint_style = style; } +bool QFontEngineFT::expectsGammaCorrectedBlending() const +{ + return stemDarkeningDriver; +} + int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const { diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index c5f3b0443e..2993e3b616 100644 --- a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -246,6 +246,7 @@ private: QPoint *offset) Q_DECL_OVERRIDE; bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; } void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE; + bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE; void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE; int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; } @@ -291,6 +292,10 @@ private: bool initFromFontEngine(const QFontEngineFT *fontEngine); HintStyle defaultHintStyle() const { return default_hint_style; } + + static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray()); + static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); + protected: QFreetypeFace *freetype; @@ -305,12 +310,12 @@ protected: bool embeddedbitmap; bool cacheEnabled; bool forceAutoHint; + bool stemDarkeningDriver; private: friend class QFontEngineFTRawFont; friend class QFontconfigDatabase; - friend class QBasicFontDatabase; - friend class QCoreTextFontDatabase; + friend class QFreeTypeFontDatabase; friend class QFontEngineMultiFontConfig; int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp index 8cf572b1af..2caa47658a 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qbasicfontdatabase_p.h" +#include "qfreetypefontdatabase_p.h" #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformscreen.h> @@ -45,7 +45,6 @@ #include <QtCore/QFile> #include <QtCore/QLibraryInfo> #include <QtCore/QDir> -#include <QtCore/QUuid> #include <QtCore/QtEndian> #undef QT_NO_FREETYPE @@ -57,7 +56,7 @@ QT_BEGIN_NAMESPACE -void QBasicFontDatabase::populateFontDatabase() +void QFreeTypeFontDatabase::populateFontDatabase() { QString fontpath = fontDir(); QDir dir(fontpath); @@ -79,100 +78,32 @@ void QBasicFontDatabase::populateFontDatabase() const auto fis = dir.entryInfoList(nameFilters, QDir::Files); for (const QFileInfo &fi : fis) { const QByteArray file = QFile::encodeName(fi.absoluteFilePath()); - QBasicFontDatabase::addTTFile(QByteArray(), file); + QFreeTypeFontDatabase::addTTFile(QByteArray(), file); } } -QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) +QFontEngine *QFreeTypeFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) { - FontFile *fontfile = static_cast<FontFile *> (usrPtr); - QFontEngine::FaceId fid; - fid.filename = QFile::encodeName(fontfile->fileName); - fid.index = fontfile->indexValue; - - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT *engine = new QFontEngineFT(fontDef); - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); - if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { - format = QFontEngineFT::Format_A8; - engine->subpixelType = QFontEngine::Subpixel_None; - } else { - format = QFontEngineFT::Format_A32; - engine->subpixelType = subpixelType; - } - } - - if (!engine->init(fid, antialias, format) || engine->invalid()) { - delete engine; - engine = 0; - } else { - engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); - } - - return engine; -} - -namespace { - - class QFontEngineFTRawData: public QFontEngineFT - { - public: - QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) - { - } - - void updateFamilyNameAndStyle() - { - fontDef.family = QString::fromLatin1(freetype->face->family_name); - - if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) - fontDef.style = QFont::StyleItalic; - - if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) - fontDef.weight = QFont::Bold; - } - - bool initFromData(const QByteArray &fontData) - { - FaceId faceId; - faceId.filename = ""; - faceId.index = 0; - faceId.uuid = QUuid::createUuid().toByteArray(); - - return init(faceId, true, Format_None, fontData); - } - }; + FontFile *fontfile = static_cast<FontFile *>(usrPtr); + QFontEngine::FaceId faceId; + faceId.filename = QFile::encodeName(fontfile->fileName); + faceId.index = fontfile->indexValue; + return QFontEngineFT::create(fontDef, faceId); } -QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, +QFontEngine *QFreeTypeFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.stretch = QFont::Unstretched; - fontDef.hintingPreference = hintingPreference; - - QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); - if (!fe->initFromData(fontData)) { - delete fe; - return 0; - } - - fe->updateFamilyNameAndStyle(); - fe->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); - - return fe; + return QFontEngineFT::create(fontData, pixelSize, hintingPreference); } -QStringList QBasicFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +QStringList QFreeTypeFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { - return QBasicFontDatabase::addTTFile(fontData, fileName.toLocal8Bit()); + return QFreeTypeFontDatabase::addTTFile(fontData, fileName.toLocal8Bit()); } -void QBasicFontDatabase::releaseHandle(void *handle) +void QFreeTypeFontDatabase::releaseHandle(void *handle) { FontFile *file = static_cast<FontFile *>(handle); delete file; @@ -180,7 +111,7 @@ void QBasicFontDatabase::releaseHandle(void *handle) extern FT_Library qt_getFreetype(); -QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) +QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) { FT_Library library = qt_getFreetype(); diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h index 8d8f61973b..6d51361400 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QBASICFONTDATABASE_H -#define QBASICFONTDATABASE_H +#ifndef QFREETYPEFONTDATABASE_H +#define QFREETYPEFONTDATABASE_H // // W A R N I N G @@ -63,7 +63,7 @@ struct FontFile int indexValue; }; -class QBasicFontDatabase : public QPlatformFontDatabase +class QFreeTypeFontDatabase : public QPlatformFontDatabase { public: void populateFontDatabase() Q_DECL_OVERRIDE; @@ -77,4 +77,4 @@ public: QT_END_NAMESPACE -#endif // QBASICFONTDATABASE_H +#endif // QFREETYPEFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h b/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h index 37c667eeb3..ccf5ad6d13 100644 --- a/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h @@ -57,8 +57,8 @@ #include <QtFontDatabaseSupport/private/qfontconfigdatabase_p.h> typedef QFontconfigDatabase QGenericUnixFontDatabase; #else -#include <QtFontDatabaseSupport/private/qbasicfontdatabase_p.h> -typedef QBasicFontDatabase QGenericUnixFontDatabase; +#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h> +typedef QFreeTypeFontDatabase QGenericUnixFontDatabase; #endif //Q_FONTCONFIGDATABASE #endif // QGENERICUNIXFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri index 50dafc3f89..a533234c26 100644 --- a/src/platformsupport/fontdatabases/mac/coretext.pri +++ b/src/platformsupport/fontdatabases/mac/coretext.pri @@ -3,14 +3,29 @@ OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.m qtConfig(freetype) { QMAKE_USE_PRIVATE += freetype - HEADERS += basic/qfontengine_ft_p.h - SOURCES += basic/qfontengine_ft.cpp + HEADERS += freetype/qfontengine_ft_p.h + SOURCES += freetype/qfontengine_ft.cpp } uikit: \ # On iOS/tvOS/watchOS CoreText and CoreGraphics are stand-alone frameworks LIBS_PRIVATE += -framework CoreText -framework CoreGraphics else: \ - # On Mac OS they are part of the ApplicationServices umbrella framework, - # even in 10.8 where they were also made available stand-alone. - LIBS_PRIVATE += -framework ApplicationServices + # On macOS they are re-exported by the AppKit framework + LIBS_PRIVATE += -framework AppKit + +# CoreText is documented to be available on watchOS, but the headers aren't present +# in the watchOS Simulator SDK like they are supposed to be. Work around the problem +# by adding the device SDK's headers to the search path as a fallback. +# rdar://25314492, rdar://27844864 +watchos:simulator { + simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks + device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks + for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) { + QMAKE_CXXFLAGS += \ + -Xarch_$${arch} \ + -F$$simulator_system_frameworks \ + -Xarch_$${arch} \ + -F$$device_system_frameworks + } +} diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 3d94982f60..3b9a456be0 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")); @@ -203,10 +199,6 @@ static CFArrayRef availableFamilyNames() void QCoreTextFontDatabase::populateFontDatabase() { - // The caller (QFontDB) expects the db to be populate only with system fonts, so we need - // to make sure that any previously registered app fonts become invisible. - removeApplicationFonts(); - QCFType<CFArrayRef> familyNames = availableFamilyNames(); const int numberOfFamilies = CFArrayGetCount(familyNames); for (int i = 0; i < numberOfFamilies; ++i) { @@ -362,66 +354,43 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, con fd.pixelSize, fd.fixedPitch, fd.writingSystems, (void *) font); } -void QCoreTextFontDatabase::releaseHandle(void *handle) +static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute"; + +template <typename T> +T *descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name) { - CFRelease(CTFontDescriptorRef(handle)); + return [static_cast<T *>(CTFontDescriptorCopyAttribute(descriptor, name)) autorelease]; } -#ifndef QT_NO_FREETYPE -static QByteArray filenameForCFUrl(CFURLRef url) +void QCoreTextFontDatabase::releaseHandle(void *handle) { - // The on-stack buffer prevents that a QByteArray allocated for the worst case (MAXPATHLEN) - // stays around for the lifetime of the font. Additionally, it helps to move the char - // signedness cast to an acceptable place. - uchar buffer[MAXPATHLEN]; - QByteArray filename; - - if (!CFURLGetFileSystemRepresentation(url, true, buffer, sizeof(buffer))) { - qWarning("QCoreTextFontDatabase::filenameForCFUrl: could not resolve file for URL %s", - url ? qPrintable(QString::fromCFString(CFURLGetString(url))) : "(null)"); - } else { - QCFType<CFStringRef> scheme = CFURLCopyScheme(url); - if (QString::fromCFString(scheme) == QLatin1String("qrc")) - filename = ":"; - - filename += reinterpret_cast<char *>(buffer); + CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(handle); + if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) { + QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue); + delete fontData; } - - return filename; + CFRelease(descriptor); } -#endif 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); CFRelease(font); return engine; } @@ -429,60 +398,39 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) return NULL; } -static void releaseFontData(void* info, const void* data, size_t size) +#ifndef QT_NO_FREETYPE +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const QFontDef &fontDef, void *usrPtr) { - Q_UNUSED(data); - Q_UNUSED(size); - delete (QByteArray*)info; -} + CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr); -QFontEngine *QCoreTextFontDatabase::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; - } + if (NSURL *url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) { + Q_ASSERT(url.fileURL); + QFontEngine::FaceId faceId; + faceId.filename = QString::fromNSString(url.path).toUtf8(); + return QFontEngineFT::create(fontDef, faceId); - 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); + } else if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) { + QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue); + return QFontEngineFT::create(*fontData, fontDef.pixelSize, + static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); } + Q_UNREACHABLE(); +} #endif - Q_UNUSED(hintingPreference); - - QByteArray* fontDataCopy = new QByteArray(fontData); - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy, - fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - - CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider); - - QFontEngine *fontEngine = NULL; - if (cgFont == NULL) { - qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); - } else { - QFontDef def; - def.pixelSize = pixelSize; - def.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontEngine = new QCoreTextFontEngine(cgFont, def); - CFRelease(cgFont); - } - - return fontEngine; +template <class T> +QFontEngine *QCoreTextFontDatabaseEngineFactory<T>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + return T::create(fontData, pixelSize, hintingPreference); } +// Explicitly instantiate so that we don't need the plugin to involve FreeType +template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>; +#ifndef QT_NO_FREETYPE +template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>; +#endif + QFont::StyleHint styleHintFromNSString(NSString *style) { if ([style isEqual: @"sans-serif"]) @@ -615,84 +563,41 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo return fallbackLists[styleLookupKey.arg(styleHint)]; } -static CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName = QString()) -{ - 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 (!fileName.isEmpty()) { - QCFType<CFURLRef> fontURL; - - if (fileName.startsWith(QLatin1String(":/"))) { - // QUrl::fromLocalFile() doesn't accept qrc pseudo-paths like ":/fonts/myfont.ttf". - // Therefore construct from QString with the qrc:// scheme -> "qrc:///fonts/myfont.ttf". - fontURL = QUrl(QStringLiteral("qrc://") + fileName.mid(1)).toCFURL(); - } else { - // At this point we hope that filename is in a format that QUrl can handle. - fontURL = QUrl::fromLocalFile(fileName).toCFURL(); - } - - QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL); - descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes); - } -#endif - - CFArrayAppendValue(array, descriptor); - return array; -} - QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { QCFType<CFArrayRef> fonts; - QStringList families; - CFErrorRef error = 0; if (!fontData.isEmpty()) { - QByteArray* fontDataCopy = new QByteArray(fontData); - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy, - fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - QCFType<CGFontRef> cgFont = CGFontCreateWithDataProvider(dataProvider); - if (cgFont) { - if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) { - QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL); - fonts = createDescriptorArrayForFont(font -#ifndef QT_NO_FREETYPE - , m_useFreeType ? fileName : QString() -#endif - ); - m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont))); - } + QCFType<CFDataRef> fontDataReference = fontData.toRawCFData(); + if (QCFType<CTFontDescriptorRef> descriptor = CTFontManagerCreateFontDescriptorFromData(fontDataReference)) { + // There's no way to get the data back out of a font descriptor created with + // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually. + NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] }; + descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes); + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(array, descriptor); + fonts = array; } } else { - QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false); - if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error)) { - fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL); - m_applicationFonts.append(QVariant::fromValue(QCFType<CFURLRef>::constructFromGet(fontURL))); - } + QCFType<CFURLRef> fontURL = QUrl::fromLocalFile(fileName).toCFURL(); + fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL); } - if (error) { - NSLog(@"Unable to register font: %@", error); - CFRelease(error); - } + if (!fonts) + return QStringList(); - if (fonts) { - const int numFonts = CFArrayGetCount(fonts); - for (int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i)); - populateFromDescriptor(fontDescriptor); - QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute)); - families.append(QCFString(familyName)); - } + QStringList families; + const int numFonts = CFArrayGetCount(fonts); + for (int i = 0; i < numFonts; ++i) { + CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i)); + populateFromDescriptor(fontDescriptor); + QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute)); + families.append(QString::fromCFString(familyName)); } + // Note: We don't do font matching via CoreText for application fonts, so we don't + // need to enable font matching for them via CTFontManagerEnableFontDescriptors. + return families; } @@ -708,71 +613,71 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f) { switch (f) { case QPlatformTheme::SystemFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::MenuFont: case QPlatformTheme::MenuBarFont: case QPlatformTheme::MenuItemFont: - return kCTFontMenuItemFontType; + return kCTFontUIFontMenuItem; case QPlatformTheme::MessageBoxFont: - return kCTFontEmphasizedSystemFontType; + return kCTFontUIFontEmphasizedSystem; case QPlatformTheme::LabelFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::TipLabelFont: return kCTFontToolTipFontType; case QPlatformTheme::StatusBarFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::TitleBarFont: - return kCTFontWindowTitleFontType; + return kCTFontUIFontWindowTitle; case QPlatformTheme::MdiSubWindowTitleFont: case QPlatformTheme::DockWidgetTitleFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::PushButtonFont: - return kCTFontPushButtonFontType; + return kCTFontUIFontPushButton; case QPlatformTheme::CheckBoxFont: case QPlatformTheme::RadioButtonFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::ToolButtonFont: - return kCTFontSmallToolbarFontType; + return kCTFontUIFontSmallToolbar; case QPlatformTheme::ItemViewFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::ListViewFont: - return kCTFontViewsFontType; + return kCTFontUIFontViews; case QPlatformTheme::HeaderViewFont: - return kCTFontSmallSystemFontType; + return kCTFontUIFontSmallSystem; case QPlatformTheme::ListBoxFont: - return kCTFontViewsFontType; + return kCTFontUIFontViews; case QPlatformTheme::ComboMenuItemFont: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; case QPlatformTheme::ComboLineEditFont: - return kCTFontViewsFontType; + return kCTFontUIFontViews; case QPlatformTheme::SmallFont: - return kCTFontSmallSystemFontType; + return kCTFontUIFontSmallSystem; case QPlatformTheme::MiniFont: - return kCTFontMiniSystemFontType; + return kCTFontUIFontMiniSystem; case QPlatformTheme::FixedFont: - return kCTFontUserFixedPitchFontType; + return kCTFontUIFontUserFixedPitch; default: - return kCTFontSystemFontType; + return kCTFontUIFontSystem; } } @@ -848,7 +753,7 @@ QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const QFont QCoreTextFontDatabase::defaultFont() const { if (defaultFontName.isEmpty()) { - QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 12.0, NULL); + QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, 12.0, NULL); defaultFontName = (QString) QCFString(CTFontCopyFullName(font)); } @@ -871,53 +776,5 @@ QList<int> QCoreTextFontDatabase::standardSizes() const return ret; } -void QCoreTextFontDatabase::removeApplicationFonts() -{ - if (m_applicationFonts.isEmpty()) - return; - - for (const QVariant &font : qAsConst(m_applicationFonts)) { - CFErrorRef error; - if (font.canConvert(qMetaTypeId<QCFType<CGFontRef> >())) { - CTFontManagerUnregisterGraphicsFont(font.value<QCFType<CGFontRef> >(), &error); - } else if (font.canConvert(qMetaTypeId<QCFType<CFURLRef> >())) { - CTFontManagerUnregisterFontsForURL(font.value<QCFType<CFURLRef> >(), kCTFontManagerScopeProcess, &error); - } - } - - 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; - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - - QScopedPointer<QFontEngineFT> engine(new QFontEngineFT(fontDef)); - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); - if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { - format = QFontEngineFT::Format_A8; - engine->subpixelType = QFontEngine::Subpixel_None; - } else { - format = QFontEngineFT::Format_A32; - engine->subpixelType = subpixelType; - } - } - - if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { - qWarning("QCoreTextFontDatabase::freeTypefontEngine Failed to create engine"); - return Q_NULLPTR; - } - engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference)); - - return engine.take(); -} -#endif - QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 3b1be2e6a1..a7529b7fb0 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; @@ -94,20 +92,23 @@ public: private: void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString()); -#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(); - - QVector<QVariant> m_applicationFonts; mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors; 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; +}; + QT_END_NAMESPACE #endif // QCORETEXTFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7a06d5f1c9..49a6049c4b 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -141,7 +141,7 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont, { Q_UNUSED(flags); QVarLengthArray<CGSize> advances(len); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len); + CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), len); for (int i = 0; i < len; ++i) { if (glyphs->glyphs[i] & 0xff000000) @@ -177,6 +177,43 @@ CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef) return transform; } +// Keeps font data alive until engine is disposed +class QCoreTextRawFontEngine : public QCoreTextFontEngine +{ +public: + QCoreTextRawFontEngine(CGFontRef font, const QFontDef &def, const QByteArray &fontData) + : QCoreTextFontEngine(font, def) + , m_fontData(fontData) + {} + QByteArray m_fontData; +}; + +QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + Q_UNUSED(hintingPreference); + + QCFType<CFDataRef> fontDataReference = fontData.toRawCFData(); + QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithCFData(fontDataReference); + + // Note: CTFontCreateWithGraphicsFont (which we call from the QCoreTextFontEngine + // constructor) has a bug causing it to retain the CGFontRef but never release it. + // The result is that we are leaking the CGFont, CGDataProvider, and CGData, but + // as the CGData is created from the raw QByteArray data, which we deref in the + // subclass above during destruction, we're at least not leaking the font data, + // (unless CoreText copies it internally). http://stackoverflow.com/questions/40805382/ + QCFType<CGFontRef> cgFont = CGFontCreateWithDataProvider(dataProvider); + + if (!cgFont) { + qWarning("QCoreTextFontEngine::create: CGFontCreateWithDataProvider failed"); + return nullptr; + } + + QFontDef def; + def.pixelSize = pixelSize; + def.pointSize = pixelSize * 72.0 / qt_defaultDpi(); + return new QCoreTextRawFontEngine(cgFont, def, fontData); +} + QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) : QFontEngine(Mac) { @@ -320,7 +357,7 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout * return true; QVarLengthArray<CGSize> advances(glyph_pos); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), glyph_pos); + CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), glyph_pos); for (int i = 0; i < glyph_pos; ++i) { if (glyphs->glyphs[i] & 0xff000000) @@ -351,7 +388,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) { glyph_metrics_t ret; CGGlyph g = glyph; - CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1); + CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, 0, 1); if (synthesisFlags & QFontEngine::SynthesizedItalic) { rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW; } @@ -360,7 +397,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) ret.x = QFixed::fromReal(rect.origin.x); ret.y = -QFixed::fromReal(rect.origin.y) - ret.height; CGSize advances[1]; - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1); + CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, &g, advances, 1); ret.xoff = QFixed::fromReal(advances[0].width); ret.yoff = QFixed::fromReal(advances[0].height); @@ -602,6 +639,11 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s return br; } +bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const +{ + // Only works well when font-smoothing is enabled + return (glyphFormat == Format_A32) && !(fontDef.styleStrategy & (QFont::NoAntialias | QFont::NoSubpixelAntialias)); +} QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix) { diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index d9ffbb5697..2986f0aaec 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -110,6 +110,7 @@ public: void doKerning(QGlyphLayout *g, ShaperFlags flags) const Q_DECL_OVERRIDE; bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; + bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE; QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; Qt::HANDLE handle() const Q_DECL_OVERRIDE; @@ -122,6 +123,8 @@ public: static int antialiasingThreshold; static QFontEngine::GlyphFormat defaultGlyphFormat; + + static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); private: void init(); QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool colorful, const QTransform &m); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index c457246354..d3e4daa341 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -591,12 +591,7 @@ namespace { */ QWindowsFontEngineData::QWindowsFontEngineData() - : clearTypeEnabled(false) - , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma()) -#if !defined(QT_NO_DIRECTWRITE) - , directWriteFactory(0) - , directWriteGdiInterop(0) -#endif + : fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma()) { // from qapplication_win.cpp UINT result = 0; @@ -1221,8 +1216,6 @@ QWindowsFontEngineDataPtr sharedFontData() } #endif // QT_NO_THREAD -extern Q_GUI_EXPORT bool qt_needs_a8_gamma_correction; - QWindowsFontDatabase::QWindowsFontDatabase() { // Properties accessed by QWin32PrintEngine (Qt Print Support) @@ -1236,7 +1229,6 @@ QWindowsFontDatabase::QWindowsFontDatabase() qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: " << data->clearTypeEnabled << "gamma: " << data->fontSmoothingGamma; } - qt_needs_a8_gamma_correction = true; } QWindowsFontDatabase::~QWindowsFontDatabase() diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index 65947ab7da..3f03b30f10 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -393,14 +393,14 @@ void QWindowsFontDatabaseFT::populateFontDatabase() QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle) { - QFontEngine *fe = QBasicFontDatabase::fontEngine(fontDef, handle); + QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontDef, handle); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.family << fe << handle; return fe; } QFontEngine *QWindowsFontDatabaseFT::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontEngine *fe = QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference); + QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fe; return fe; } @@ -410,7 +410,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF QStringList result; result.append(QWindowsFontDatabase::familyForStyleHint(styleHint)); result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h index 3a432842e5..2df81274ad 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h @@ -51,13 +51,13 @@ // We mean it. // -#include <QtFontDatabaseSupport/private/qbasicfontdatabase_p.h> +#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h> #include <QtCore/QSharedPointer> #include <QtCore/qt_windows.h> QT_BEGIN_NAMESPACE -class QWindowsFontDatabaseFT : public QBasicFontDatabase +class QWindowsFontDatabaseFT : public QFreeTypeFontDatabase { public: void populateFontDatabase() Q_DECL_OVERRIDE; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index 325f522335..15172c09da 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -74,12 +74,12 @@ public: uint pow_gamma[256]; - bool clearTypeEnabled; + bool clearTypeEnabled = false; qreal fontSmoothingGamma; - HDC hdc; + HDC hdc = 0; #if !defined(QT_NO_DIRECTWRITE) - IDWriteFactory *directWriteFactory; - IDWriteGdiInterop *directWriteGdiInterop; + IDWriteFactory *directWriteFactory = nullptr; + IDWriteGdiInterop *directWriteGdiInterop = nullptr; #endif }; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp index 5af73a6f2b..6e95fb5a05 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp @@ -239,21 +239,9 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name, : QFontEngine(Win), m_fontEngineData(fontEngineData), _name(name), - hfont(0), m_logfont(lf), ttf(0), - hasOutline(0), - cmap(0), - cmapSize(0), - lbearing(SHRT_MIN), - rbearing(SHRT_MIN), - x_height(-1), - synthesized_flags(-1), - lineWidth(-1), - widthCache(0), - widthCacheSize(0), - designAdvances(0), - designAdvancesSize(0) + hasOutline(0) { qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight; hfont = CreateFontIndirect(&m_logfont); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h index 709de7d11d..5119adc0eb 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h @@ -145,29 +145,29 @@ private: const QString _name; QString uniqueFamilyName; - HFONT hfont; + HFONT hfont = 0; const LOGFONT m_logfont; uint ttf : 1; uint hasOutline : 1; uint hasUnreliableOutline : 1; uint cffTable : 1; TEXTMETRIC tm; - const unsigned char *cmap; - int cmapSize; + const unsigned char *cmap = nullptr; + int cmapSize = 0; QByteArray cmapTable; - mutable qreal lbearing; - mutable qreal rbearing; + mutable qreal lbearing = SHRT_MIN; + mutable qreal rbearing = SHRT_MIN; QFixed designToDevice; - int unitsPerEm; - QFixed x_height; + int unitsPerEm = 0; + QFixed x_height = -1; FaceId _faceId; - mutable int synthesized_flags; - mutable QFixed lineWidth; - mutable unsigned char *widthCache; - mutable uint widthCacheSize; - mutable QFixed *designAdvances; - mutable int designAdvancesSize; + mutable int synthesized_flags = -1; + mutable QFixed lineWidth = -1; + mutable unsigned char *widthCache = nullptr; + mutable uint widthCacheSize = 0; + mutable QFixed *designAdvances = nullptr; + mutable int designAdvancesSize = 0; }; class QWindowsMultiFontEngine : public QFontEngineMulti diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index 683b7f65ad..f07e711048 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -355,6 +355,13 @@ void QWindowsFontEngineDirectWrite::collectMetrics() m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile)); fontFile->Release(); } + + QByteArray table = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); + const int advanceWidthMaxLocation = 10; + if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) { + quint16 advanceWidthMax = qFromBigEndian<quint16>(table.constData() + advanceWidthMaxLocation); + m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax); + } } QFixed QWindowsFontEngineDirectWrite::underlinePosition() const @@ -607,8 +614,9 @@ QFixed QWindowsFontEngineDirectWrite::xHeight() const qreal QWindowsFontEngineDirectWrite::maxCharWidth() const { - // ### - return 0; + return fontDef.styleStrategy & QFont::ForceIntegerMetrics + ? m_maxAdvanceWidth.round().toReal() + : m_maxAdvanceWidth.toReal(); } QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h index 65b16b9ba7..db4e79e44f 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h @@ -143,6 +143,7 @@ private: QFixed m_descent; QFixed m_xHeight; QFixed m_lineGap; + QFixed m_maxAdvanceWidth; FaceId m_faceId; QString m_uniqueFamilyName; }; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp index 7022615511..f8fcff952a 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp @@ -110,9 +110,7 @@ static inline HBITMAP createDIB(HDC hdc, int width, int height, QWindowsNativeImage::QWindowsNativeImage(int width, int height, QImage::Format format) : - m_hdc(createDC()), - m_bitmap(0), - m_null_bitmap(0) + m_hdc(createDC()) { if (width != 0 && height != 0) { uchar *bits; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h index c27c0d1e98..6c47a527d2 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h @@ -80,8 +80,8 @@ private: const HDC m_hdc; QImage m_image; - HBITMAP m_bitmap; - HBITMAP m_null_bitmap; + HBITMAP m_bitmap = 0; + HBITMAP m_null_bitmap = 0; }; QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri index 4ca0080ad9..0e64084cf1 100644 --- a/src/platformsupport/fontdatabases/windows/windows.pri +++ b/src/platformsupport/fontdatabases/windows/windows.pri @@ -26,3 +26,4 @@ qtConfig(directwrite) { } LIBS += -lole32 -lgdi32 -luser32 -ladvapi32 +mingw: LIBS += -luuid diff --git a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp index eb5a38855e..2a95ca26a9 100644 --- a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp @@ -144,7 +144,7 @@ QWinRTFontDatabase::~QWinRTFontDatabase() QString QWinRTFontDatabase::fontDir() const { qCDebug(lcQpaFonts) << __FUNCTION__; - QString fontDirectory = QBasicFontDatabase::fontDir(); + QString fontDirectory = QFreeTypeFontDatabase::fontDir(); if (!QFile::exists(fontDirectory)) { // Fall back to app directory + fonts, and just app directory after that const QString applicationDirPath = QCoreApplication::applicationDirPath(); @@ -176,7 +176,7 @@ void QWinRTFontDatabase::populateFontDatabase() HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); if (FAILED(hr)) { qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); return; } @@ -184,7 +184,7 @@ void QWinRTFontDatabase::populateFontDatabase() hr = factory->GetSystemFontCollection(&fontCollection); if (FAILED(hr)) { qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); return; } @@ -222,7 +222,7 @@ void QWinRTFontDatabase::populateFontDatabase() registerFontFamily(familyName); } - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); } void QWinRTFontDatabase::populateFamily(const QString &familyName) @@ -399,7 +399,7 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle); if (!m_fonts.contains(fontFile)) - return QBasicFontDatabase::fontEngine(fontDef, handle); + return QFreeTypeFontDatabase::fontEngine(fontDef, handle); const void *referenceKey; quint32 referenceKeySize; @@ -444,15 +444,8 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl const FontDescription description = m_fonts.value(fontFile); faceId.uuid = description.uuid; faceId.index = description.index; - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; - QFontEngineFT *engine = new QFontEngineFT(fontDef); - if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { - delete engine; - return 0; - } - return engine; + return QFontEngineFT::create(fontDef, faceId, fontData); } QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, @@ -468,7 +461,7 @@ QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont: QStringList result; if (family == QLatin1String("Helvetica")) result.append(QStringLiteral("Arial")); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; } @@ -486,7 +479,7 @@ void QWinRTFontDatabase::releaseHandle(void *handle) return; } - QBasicFontDatabase::releaseHandle(handle); + QFreeTypeFontDatabase::releaseHandle(handle); } QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h index 3b803d7613..9a2bf00fab 100644 --- a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <QtFontDatabaseSupport/private/qbasicfontdatabase_p.h> +#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h> #include <QtCore/QLoggingCategory> struct IDWriteFontFile; @@ -67,7 +67,7 @@ struct FontDescription QByteArray uuid; }; -class QWinRTFontDatabase : public QBasicFontDatabase +class QWinRTFontDatabase : public QFreeTypeFontDatabase { public: ~QWinRTFontDatabase(); |