summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/fontdatabases
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-04-20 11:19:14 +0200
committerLiang Qi <liang.qi@qt.io>2017-04-20 12:31:27 +0200
commit7950b6b283549c98f1e0f981c84b68071a13b616 (patch)
treecf7281872045ebd57c68e10064ff0f400084aa13 /src/platformsupport/fontdatabases
parent58d2927861d3e57cac4f6db599e209d2bfb17a2c (diff)
parent0794d61c822585530243f638687b8a75f0a15d0c (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts: src/corelib/tools/qbytearray.h src/corelib/tools/qdatetime.h src/corelib/tools/qstring.h src/corelib/tools/qversionnumber.h src/plugins/platforms/android/qandroidplatformintegration.cpp tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp Change-Id: Iefd92a435e687a76cd593099e40d9a9620a1454d
Diffstat (limited to 'src/platformsupport/fontdatabases')
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp8
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm211
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h6
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm37
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp12
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h1
7 files changed, 128 insertions, 149 deletions
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index a997bf0ba1..969a9c17e0 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -901,7 +901,13 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
bool forcedAntialiasSetting = !antialias;
const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
- bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY"));
+ bool useXftConf = false;
+
+ if (services) {
+ const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
+ useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY");
+ }
+
if (useXftConf && !forcedAntialiasSetting) {
void *antialiasResource =
QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index ce9b61ba4c..d89a81be6b 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -199,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) {
@@ -255,6 +251,24 @@ struct FontDescription {
QSupportedWritingSystems writingSystems;
};
+#ifndef QT_NO_DEBUG_STREAM
+Q_DECL_UNUSED static inline QDebug operator<<(QDebug debug, const FontDescription &fd)
+{
+ QDebugStateSaver saver(debug);
+ return debug.nospace() << "FontDescription("
+ << "familyName=" << QString(fd.familyName)
+ << ", styleName=" << QString(fd.styleName)
+ << ", foundry=" << fd.foundryName
+ << ", weight=" << fd.weight
+ << ", style=" << fd.style
+ << ", stretch=" << fd.stretch
+ << ", pixelSize=" << fd.pixelSize
+ << ", fixedPitch=" << fd.fixedPitch
+ << ", writingSystems=" << fd.writingSystems
+ << ")";
+}
+#endif
+
static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
{
QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
@@ -358,9 +372,22 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, con
fd.pixelSize, fd.fixedPitch, fd.writingSystems, (void *) font);
}
+static NSString * const kQtFontDataAttribute = @"QtFontDataAttribute";
+
+template <typename T>
+T *descriptorAttribute(CTFontDescriptorRef descriptor, CFStringRef name)
+{
+ return [static_cast<T *>(CTFontDescriptorCopyAttribute(descriptor, name)) autorelease];
+}
+
void QCoreTextFontDatabase::releaseHandle(void *handle)
{
- CFRelease(CTFontDescriptorRef(handle));
+ CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(handle);
+ if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) {
+ QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue);
+ delete fontData;
+ }
+ CFRelease(descriptor);
}
extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
@@ -395,61 +422,31 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const
{
CTFontDescriptorRef descriptor = static_cast<CTFontDescriptorRef>(usrPtr);
- QByteArray filename;
- if (NSURL *url = [static_cast<NSURL *>(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute)) autorelease]) {
- if ([url.scheme isEqual:@"qrc"])
- filename = ":";
- else if (!url.fileURL)
- qWarning() << "QFontDatabase: Unknown scheme" << url.scheme << "in font descriptor URL";
+ 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);
- filename += QString::fromNSString(url.path).toUtf8();
+ } 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_ASSERT(!filename.isEmpty());
-
- QFontEngine::FaceId faceId;
- faceId.filename = filename;
- return QFontEngineFT::create(fontDef, faceId);
+ Q_UNREACHABLE();
}
#endif
-static void releaseFontData(void* info, const void* data, size_t size)
-{
- Q_UNUSED(data);
- Q_UNUSED(size);
- delete (QByteArray*)info;
-}
-
-template <>
-QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
+template <class T>
+QFontEngine *QCoreTextFontDatabaseEngineFactory<T>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
- 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;
+ 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 <>
-QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
-{
- return QFontEngineFT::create(fontData, pixelSize, hintingPreference);
-}
+template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
#endif
QFont::StyleHint styleHintFromNSString(NSString *style)
@@ -584,90 +581,41 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
return fallbackLists[styleLookupKey.arg(styleHint)];
}
-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);
-
- // 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);
- }
-
- CFArrayAppendValue(array, descriptor);
- return array;
-}
-#endif
-
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, fileName);
- 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;
}
@@ -846,22 +794,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();
-}
-
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 8e5449ac90..9c2a4cf1ca 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -87,13 +87,9 @@ public:
private:
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString());
- virtual CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName) = 0;
mutable QString defaultFontName;
- void removeApplicationFonts();
-
- QVector<QVariant> m_applicationFonts;
mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors;
mutable QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
};
@@ -107,8 +103,6 @@ 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
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index c8ae342f16..49a6049c4b 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -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)
{
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index 0074790e43..2986f0aaec 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -123,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/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;
};