summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm')
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm211
1 files changed, 71 insertions, 140 deletions
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