summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorMathias Hasselmann <mathias.hasselmann@kdab.com>2014-11-07 22:22:10 +0100
committerAndreas Hartmetz <ahartmetz@gmail.com>2015-08-11 09:40:30 +0000
commitbf013c9e745c63cb112be4d3a37027ff997927dd (patch)
treee692a93ec24e8a2e4b3be81e971dcad3a234dca9 /src/platformsupport
parent55512950281260b85ea40c08239e459c76b696d2 (diff)
OSX: Add initial FreeType support
This permits text rendering consistent with other FreeType enabled platforms, like Windows and Linux. Task-number: QTBUG-42839 Change-Id: I8c99bcaa3fb07c16e935a0c3705af467bc3da584 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri7
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm129
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h7
3 files changed, 137 insertions, 6 deletions
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index f67f00672a..ebb64d15b4 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -1,6 +1,13 @@
HEADERS += $$PWD/qcoretextfontdatabase_p.h $$PWD/qfontengine_coretext_p.h
OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.mm
+contains(QT_CONFIG, freetype) {
+ include($$QT_SOURCE_TREE/src/3rdparty/freetype_dependency.pri)
+ HEADERS += $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft_p.h
+ SOURCES += $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft.cpp
+ CONFIG += opentype
+}
+
ios: \
# On iOS CoreText and CoreGraphics are stand-alone frameworks
LIBS_PRIVATE += -framework CoreText -framework CoreGraphics
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 75c4065d66..a9ca5391e8 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -33,6 +33,8 @@
#include "qglobal.h"
+#include <sys/param.h>
+
#if defined(Q_OS_MACX)
#import <Cocoa/Cocoa.h>
#import <IOKit/graphics/IOGraphicsLib.h>
@@ -45,6 +47,9 @@
#include <QtCore/QSettings>
#include <QtGui/QGuiApplication>
#include <QtCore/QtEndian>
+#ifndef QT_NO_FREETYPE
+#include <QtGui/private/qfontengine_ft_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -102,8 +107,12 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context)
}
#endif
-QCoreTextFontDatabase::QCoreTextFontDatabase()
+QCoreTextFontDatabase::QCoreTextFontDatabase(bool useFreeType)
+#ifndef QT_NO_FREETYPE
+ : m_useFreeType(useFreeType)
+#endif
{
+ Q_UNUSED(useFreeType)
#ifdef Q_OS_MACX
QSettings appleSettings(QLatin1String("apple.com"));
QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
@@ -348,10 +357,48 @@ void QCoreTextFontDatabase::releaseHandle(void *handle)
CFRelease(CTFontDescriptorRef(handle));
}
+#ifndef QT_NO_FREETYPE
+static QByteArray filenameForCFUrl(CFURLRef url)
+{
+ // 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",
+ qPrintable(QString::fromCFString(CFURLGetString(url))));
+ } else {
+ QCFType<CFStringRef> scheme = CFURLCopyScheme(url);
+ if (QString::fromCFString(scheme) == QLatin1String("qrc"))
+ filename = ":";
+
+ filename += reinterpret_cast<char *>(buffer);
+ }
+
+ return filename;
+}
+#endif
+
extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, 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
+
qreal scaledPointSize = f.pixelSize;
// When 96 DPI is forced, the Mac plugin will use DPI 72 for some
@@ -363,7 +410,6 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
if (QGuiApplication::testAttribute(Qt::AA_Use96Dpi))
scaledPointSize = f.pointSize;
- CTFontDescriptorRef descriptor = (CTFontDescriptorRef) usrPtr;
CGAffineTransform matrix = qt_transform_from_fontdef(f);
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix);
if (font) {
@@ -385,6 +431,29 @@ static void releaseFontData(void* info, const void* data, size_t size)
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;
+ }
+
+ 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);
@@ -556,10 +625,36 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
}
#if HAVE_CORETEXT
-static CFArrayRef createDescriptorArrayForFont(CTFontRef font)
+static CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName = QString())
{
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- CFArrayAppendValue(array, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font)));
+ 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 if (!fileName.isEmpty()) {
+ // 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;
}
#endif
@@ -580,7 +675,11 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
if (cgFont) {
if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) {
QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
- fonts = createDescriptorArrayForFont(font);
+ fonts = createDescriptorArrayForFont(font
+#ifndef QT_NO_FREETYPE
+ , m_useFreeType ? fileName : QString()
+#endif
+ );
m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont)));
}
}
@@ -880,5 +979,25 @@ void QCoreTextFontDatabase::removeApplicationFonts()
#endif
}
+#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);
+ const QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8
+ : QFontEngineFT::Format_Mono;
+
+ QScopedPointer<QFontEngineFT> engine(new QFontEngineFT(fontDef));
+ if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) {
+ qWarning() << "QCoreTextFontDatabase::freeTypefontEngine Failed to create engine";
+ return Q_NULLPTR;
+ }
+
+ 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 a423ed5ae2..95af1210b3 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
class QCoreTextFontDatabase : public QPlatformFontDatabase
{
public:
- QCoreTextFontDatabase();
+ QCoreTextFontDatabase(bool useFreeType = false);
~QCoreTextFontDatabase();
void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
@@ -95,6 +95,11 @@ public:
private:
void populateFromDescriptor(CTFontDescriptorRef font);
+#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();