summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-07-17 14:53:27 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-07-31 07:54:01 +0200
commit3745b0ca126f46eadfeeb7e3d1d53360dbf800cd (patch)
treeb86417f1571ffd3f1313100cb3be969daaeee0e0 /src/platformsupport
parentc6ccd278188cb460276ea4d942519b760576a202 (diff)
Fix application font population on OS X
This patch fixes two issues that prevented the application font related tests of tst_QFontDatabase from passing: * The code for creating the font descriptor after the registration of an app font with file name using CTFontDescriptorCreateWithAttributes must create a dictionary with kCTFontURLAttribute as key and the CFURLRef pointing to the on-disk file as value. Unfortunately the code mixed up keys and values in the dictionary. * Registration of app fonts within QFontDatabase itself on Windows and Fontconfig platforms works by QFontDatabase calling addApplicationFont on the platform db after calling populateFontDatabase(). It assumes that addApplicationFont on the platform db is capable of registering the font right away. This part was also missing from the Mac implementation and this patch implements it by moving the common registration code from a CTFontDescriptorRef out into a separate method, called from populateFontDatabase() as well as addApplicationFont(). Task-number: QTBUG-23062 Change-Id: Ide5e6bf277d99f3cab50ee0d4631cc3fba6d0d45 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm173
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h20
2 files changed, 127 insertions, 66 deletions
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 1e15a9e62c..5139f11d23 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -176,6 +176,10 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase()
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();
+
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0);
@@ -186,82 +190,87 @@ void QCoreTextFontDatabase::populateFontDatabase()
if (! fonts)
return;
- QString foundryName = QLatin1String("CoreText");
const int numFonts = CFArrayGetCount(fonts);
for (int i = 0; i < numFonts; ++i) {
CTFontDescriptorRef font = (CTFontDescriptorRef) CFArrayGetValueAtIndex(fonts, i);
- QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL);
- QCFString styleName = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL);
- QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
- QFont::Weight weight = QFont::Normal;
- QFont::Style style = QFont::StyleNormal;
- QFont::Stretch stretch = QFont::Unstretched;
- bool fixedPitch = false;
-
- if (styles) {
- if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
- Q_ASSERT(CFNumberIsFloatType(weightValue));
- double d;
- if (CFNumberGetValue(weightValue, kCFNumberDoubleType, &d))
- weight = (d > 0.0) ? QFont::Bold : QFont::Normal;
- }
- if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
- Q_ASSERT(CFNumberIsFloatType(italic));
- double d;
- if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
- if (d > 0.0)
- style = QFont::StyleItalic;
- }
- }
- if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
- int d;
- if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
- if (d & kCTFontMonoSpaceTrait)
- fixedPitch = true;
- if (d & kCTFontExpandedTrait)
- stretch = QFont::Expanded;
- else if (d & kCTFontCondensedTrait)
- stretch = QFont::Condensed;
- }
- }
- }
+ populateFromDescriptor(font);
+ }
- int pixelSize = 0;
- if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
- if (CFNumberIsFloatType(size)) {
- double d;
- CFNumberGetValue(size, kCFNumberDoubleType, &d);
- pixelSize = d;
- } else {
- CFNumberGetValue(size, kCFNumberIntType, &pixelSize);
+ [pool release];
+}
+
+void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
+{
+ QString foundryName = QStringLiteral("CoreText");
+ QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL);
+ QCFString styleName = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL);
+ QCFType<CFDictionaryRef> styles = (CFDictionaryRef) CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
+ QFont::Weight weight = QFont::Normal;
+ QFont::Style style = QFont::StyleNormal;
+ QFont::Stretch stretch = QFont::Unstretched;
+ bool fixedPitch = false;
+
+ if (styles) {
+ if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
+ Q_ASSERT(CFNumberIsFloatType(weightValue));
+ double d;
+ if (CFNumberGetValue(weightValue, kCFNumberDoubleType, &d))
+ weight = (d > 0.0) ? QFont::Bold : QFont::Normal;
+ }
+ if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
+ Q_ASSERT(CFNumberIsFloatType(italic));
+ double d;
+ if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
+ if (d > 0.0)
+ style = QFont::StyleItalic;
}
}
-
- QSupportedWritingSystems writingSystems;
- if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
- CFIndex length = CFArrayGetCount(languages);
- for (int i = 1; i < LanguageCount; ++i) {
- if (!languageForWritingSystem[i])
- continue;
- QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
- if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
- writingSystems.setSupported(QFontDatabase::WritingSystem(i));
+ if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
+ int d;
+ if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
+ if (d & kCTFontMonoSpaceTrait)
+ fixedPitch = true;
+ if (d & kCTFontExpandedTrait)
+ stretch = QFont::Expanded;
+ else if (d & kCTFontCondensedTrait)
+ stretch = QFont::Condensed;
}
}
+ }
- CFRetain(font);
- QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
- true /* antialiased */, true /* scalable */,
- pixelSize, fixedPitch, writingSystems, (void *) font);
+ int pixelSize = 0;
+ if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
+ if (CFNumberIsFloatType(size)) {
+ double d;
+ CFNumberGetValue(size, kCFNumberDoubleType, &d);
+ pixelSize = d;
+ } else {
+ CFNumberGetValue(size, kCFNumberIntType, &pixelSize);
+ }
+ }
- // We need to map back and forth between PostScript-names and family-names for fallback list construction
- CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute);
- psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName;
- familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName);
- CFRelease(psName);
+ QSupportedWritingSystems writingSystems;
+ if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
+ CFIndex length = CFArrayGetCount(languages);
+ for (int i = 1; i < LanguageCount; ++i) {
+ if (!languageForWritingSystem[i])
+ continue;
+ QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
+ if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
+ writingSystems.setSupported(QFontDatabase::WritingSystem(i));
+ }
}
- [pool release];
+ CFRetain(font);
+ QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
+ true /* antialiased */, true /* scalable */,
+ pixelSize, fixedPitch, writingSystems, (void *) font);
+
+ // We need to map back and forth between PostScript-names and family-names for fallback list construction
+ CFStringRef psName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute);
+ psNameToFamily[QCFString::toQString((NSString *) psName)] = familyName;
+ familyNameToPsName[familyName] = QCFString::toQString((NSString *) psName);
+ CFRelease(psName);
}
void QCoreTextFontDatabase::releaseHandle(void *handle)
@@ -473,6 +482,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
bool success = CTFontManagerRegisterGraphicsFont(cgFont, &error);
if (success) {
font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL);
+ m_applicationGraphicsFonts.append(QCFType<CGFontRef>::constructFromGet(cgFont));
} else {
NSLog(@"Unable to register font: %@", error);
CFRelease(error);
@@ -484,12 +494,13 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false);
bool success = CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error);
if (success) {
- const void *keys[] = { fontURL };
- const void *values[] = { kCTFontURLAttribute };
+ const void *keys[] = { kCTFontURLAttribute };
+ const void *values[] = { fontURL };
QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(NULL, keys, values, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes);
font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL);
+ m_applicationURLFonts.append(QCFType<CFURLRef>::constructFromGet(fontURL));
} else {
NSLog(@"Unable to register font: %@", error);
CFRelease(error);
@@ -499,6 +510,10 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
if (font) {
QStringList families;
families.append(QCFString(CTFontCopyFamilyName(font)));
+
+ QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
+ populateFromDescriptor(descriptor);
+
CFRelease(font);
return families;
}
@@ -534,9 +549,12 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
QStringList families;
for (int i = 0; i < containedFonts.size(); ++i) {
QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL);
+ QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font);
+ populateFromDescriptor(descriptor);
families.append(QCFString(CTFontCopyFamilyName(font)));
}
+ m_applicationFonts.append(fontContainer);
return families;
}
#endif
@@ -569,5 +587,28 @@ QList<int> QCoreTextFontDatabase::standardSizes() const
return ret;
}
+void QCoreTextFontDatabase::removeApplicationFonts()
+{
+#ifdef Q_OS_MACX
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) {
+ CFErrorRef error;
+ for (int i = 0; i < m_applicationGraphicsFonts.count(); ++i)
+ CTFontManagerUnregisterGraphicsFont(m_applicationGraphicsFonts[i], &error);
+ m_applicationGraphicsFonts.clear();
+
+ for (int i = 0; i < m_applicationURLFonts.count(); ++i)
+ CTFontManagerUnregisterFontsForURL(m_applicationURLFonts[i], kCTFontManagerScopeProcess, &error);
+ m_applicationURLFonts.clear();
+ }
+#else
+ for (int i = 0; i < m_applicationFonts.count(); ++i)
+ ATSFontDeactivate(m_applicationFonts[i], 0, kATSOptionFlagsDoNotNotify);
+ m_applicationFonts.clear();
+ ATSFontNotify(kATSFontNotifyActionFontsChanged, 0);
+#endif
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 8536ad9123..c3bb4d428a 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -43,6 +43,14 @@
#define QCORETEXTFONTDATABASE_H
#include <qpa/qplatformfontdatabase.h>
+#include <private/qcore_mac_p.h>
+
+#ifndef Q_OS_IOS
+#include <ApplicationServices/ApplicationServices.h>
+#else
+#include <CoreText/CoreText.h>
+#include <CoreGraphics/CoreGraphics.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -63,9 +71,21 @@ public:
QList<int> standardSizes() const;
private:
+ void populateFromDescriptor(CTFontDescriptorRef font);
+
mutable QString defaultFontName;
mutable QHash<QString, QString> psNameToFamily;
mutable QHash<QString, QString> familyNameToPsName;
+
+ void removeApplicationFonts();
+#ifdef Q_OS_MACX
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+ QVector<QCFType<CGFontRef> > m_applicationGraphicsFonts;
+ QVector<QCFType<CFURLRef> > m_applicationURLFonts;
+#else
+ QVector<ATSFontContainerRef> m_applicationFonts;
+#endif
+#endif
};
QT_END_NAMESPACE