summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-07-02 13:18:50 +0200
committerGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-08-11 10:46:13 +0200
commit909d3f5c733dde02074a737a5f1dbe3e51dbef32 (patch)
tree9707cd00cd97215df12724df79597f74f3c2ed44 /src/platformsupport
parent3924805d595f18820f127ab33486d076102afec6 (diff)
Font Database: Add support for private, system UI font families
We introduce QPlatformFontDatabase::isPrivateFontFamily() to allow testing for private, system UI font families. Both QFontComboBox and QFontDialog need to filter out those private font families which, by definition, should be hidden from the end user. (The textedit example had to be updated to fix the issue where the default font would be private. In 5.4, we will be adding an equivalent, public API in QFontDatabase, and a better solution for the textedit example and QTexEdit in general). In particular, on OS X and iOS, private fonts are used for the system UI font. Those have their font family name prefixed by a dot. QCoreTextFontDatabase knows about this, and makes sure those are tested positive as private font families. In order to have a cleaner layer separation, we moved the QPA theme font resolution from the platform theme classes into QCoreTextFontDatabase for both Cocoa and iOS QPA plugins. In both cases, we use CoreText's CTFontCreateUIFontForLanguage(), that nicely maps to the HITheme API we were using so far on Mac. That means one HITheme dependency less. We also cache the font descriptors we get for these font for each time QCTFD::populateFamilies() gets called. (While not common, this currently happens in auto-tests, like tst_QFontDatabase, and could happen in actual applications -- specially when adding and removing application fonts.) Change-Id: Ic6f0b60f9f597afee1a43596a669742dc546b97f Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm183
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h11
2 files changed, 170 insertions, 24 deletions
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 4aa4253773..cff90f420b 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -211,6 +211,13 @@ void QCoreTextFontDatabase::populateFontDatabase()
QPlatformFontDatabase::registerAliasToFontFamily(familyName, localizedFamilyName);
#endif
}
+
+ // Force creating the theme fonts to get the descriptors in m_systemFontDescriptors
+ if (m_themeFonts.isEmpty())
+ (void)themeFonts();
+
+ Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors)
+ populateFromDescriptor(fontDesc);
}
void QCoreTextFontDatabase::populateFamily(const QString &familyName)
@@ -231,16 +238,29 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName)
populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)));
}
-void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
+struct FontDescription {
+ QCFString familyName;
+ QCFString styleName;
+ QString foundryName;
+ QFont::Weight weight;
+ QFont::Style style;
+ QFont::Stretch stretch;
+ int pixelSize;
+ bool fixedPitch;
+ QSupportedWritingSystems writingSystems;
+};
+
+static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
{
- QString foundryName = QStringLiteral("CoreText");
- QCFString familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
- QCFString styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
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;
+
+ fd->foundryName = QStringLiteral("CoreText");
+ fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
+ fd->styleName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute);
+ fd->weight = QFont::Normal;
+ fd->style = QFont::StyleNormal;
+ fd->stretch = QFont::Unstretched;
+ fd->fixedPitch = false;
if (styles) {
if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
@@ -248,15 +268,15 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
double normalizedWeight;
if (CFNumberGetValue(weightValue, kCFNumberDoubleType, &normalizedWeight)) {
if (normalizedWeight >= 0.62)
- weight = QFont::Black;
+ fd->weight = QFont::Black;
else if (normalizedWeight >= 0.4)
- weight = QFont::Bold;
+ fd->weight = QFont::Bold;
else if (normalizedWeight >= 0.3)
- weight = QFont::DemiBold;
+ fd->weight = QFont::DemiBold;
else if (normalizedWeight == 0.0)
- weight = QFont::Normal;
+ fd->weight = QFont::Normal;
else if (normalizedWeight <= -0.4)
- weight = QFont::Light;
+ fd->weight = QFont::Light;
}
}
if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
@@ -264,34 +284,32 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
double d;
if (CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
if (d > 0.0)
- style = QFont::StyleItalic;
+ fd->style = QFont::StyleItalic;
}
}
if (CFNumberRef symbolic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSymbolicTrait)) {
int d;
if (CFNumberGetValue(symbolic, kCFNumberSInt32Type, &d)) {
if (d & kCTFontMonoSpaceTrait)
- fixedPitch = true;
+ fd->fixedPitch = true;
if (d & kCTFontExpandedTrait)
- stretch = QFont::Expanded;
+ fd->stretch = QFont::Expanded;
else if (d & kCTFontCondensedTrait)
- stretch = QFont::Condensed;
+ fd->stretch = QFont::Condensed;
}
}
}
- int pixelSize = 0;
if (QCFType<CFNumberRef> size = (CFNumberRef) CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
if (CFNumberIsFloatType(size)) {
double d;
CFNumberGetValue(size, kCFNumberDoubleType, &d);
- pixelSize = d;
+ fd->pixelSize = d;
} else {
- CFNumberGetValue(size, kCFNumberIntType, &pixelSize);
+ CFNumberGetValue(size, kCFNumberIntType, &fd->pixelSize);
}
}
- QSupportedWritingSystems writingSystems;
if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
CFIndex length = CFArrayGetCount(languages);
for (int i = 1; i < LanguageCount; ++i) {
@@ -299,14 +317,24 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
continue;
QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
- writingSystems.setSupported(QFontDatabase::WritingSystem(i));
+ fd->writingSystems.setSupported(QFontDatabase::WritingSystem(i));
}
}
+}
+void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
+{
+ FontDescription fd;
+ getFontDescription(font, &fd);
+ populateFromFontDescription(font, fd);
+}
+
+void QCoreTextFontDatabase::populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd)
+{
CFRetain(font);
- QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch,
+ QPlatformFontDatabase::registerFont(fd.familyName, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
true /* antialiased */, true /* scalable */,
- pixelSize, fixedPitch, writingSystems, (void *) font);
+ fd.pixelSize, fd.fixedPitch, fd.writingSystems, (void *) font);
}
void QCoreTextFontDatabase::releaseHandle(void *handle)
@@ -612,6 +640,113 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
return families;
}
+bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const
+{
+ if (family.startsWith(QLatin1Char('.')))
+ return true;
+
+ return QPlatformFontDatabase::isPrivateFontFamily(family);
+}
+
+static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
+{
+ switch (f) {
+ case QPlatformTheme::SystemFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::MenuFont:
+ case QPlatformTheme::MenuBarFont:
+ case QPlatformTheme::MenuItemFont:
+ return kCTFontMenuItemFontType;
+
+ case QPlatformTheme::MessageBoxFont:
+ return kCTFontEmphasizedSystemFontType;
+
+ case QPlatformTheme::LabelFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::TipLabelFont:
+ return kCTFontToolTipFontType;
+
+ case QPlatformTheme::StatusBarFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::TitleBarFont:
+ return kCTFontWindowTitleFontType;
+
+ case QPlatformTheme::MdiSubWindowTitleFont:
+ case QPlatformTheme::DockWidgetTitleFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::PushButtonFont:
+ return kCTFontPushButtonFontType;
+
+ case QPlatformTheme::CheckBoxFont:
+ case QPlatformTheme::RadioButtonFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::ToolButtonFont:
+ return kCTFontSmallToolbarFontType;
+
+ case QPlatformTheme::ItemViewFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::ListViewFont:
+ return kCTFontViewsFontType;
+
+ case QPlatformTheme::HeaderViewFont:
+ return kCTFontSmallSystemFontType;
+
+ case QPlatformTheme::ListBoxFont:
+ return kCTFontViewsFontType;
+
+ case QPlatformTheme::ComboMenuItemFont:
+ return kCTFontSystemFontType;
+
+ case QPlatformTheme::ComboLineEditFont:
+ return kCTFontViewsFontType;
+
+ case QPlatformTheme::SmallFont:
+ return kCTFontSmallSystemFontType;
+
+ case QPlatformTheme::MiniFont:
+ return kCTFontMiniSystemFontType;
+
+ case QPlatformTheme::FixedFont:
+ return kCTFontUserFixedPitchFontType;
+
+ default:
+ return kCTFontSystemFontType;
+ }
+}
+
+const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const
+{
+ if (m_themeFonts.isEmpty()) {
+ for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
+ QPlatformTheme::Font ft = static_cast<QPlatformTheme::Font>(f);
+ m_themeFonts.insert(ft, themeFont(ft));
+ }
+ }
+
+ return m_themeFonts;
+}
+
+QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
+{
+ CTFontUIFontType fontType = fontTypeFromTheme(f);
+
+ QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL);
+ CTFontDescriptorRef fontDesc = CTFontCopyFontDescriptor(ctFont);
+
+ FontDescription fd;
+ getFontDescription(fontDesc, &fd);
+ m_systemFontDescriptors.insert(fontDesc);
+
+ QFont *font = new QFont(fd.familyName, fd.pixelSize, fd.weight, fd.style == QFont::StyleItalic);
+ return font;
+}
+
QFont QCoreTextFontDatabase::defaultFont() const
{
if (defaultFontName.isEmpty()) {
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index c73f4a32ca..a3da27b28d 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -47,6 +47,7 @@
#define HAVE_ATS QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_5, __IPHONE_NA)
#include <qpa/qplatformfontdatabase.h>
+#include <qpa/qplatformtheme.h>
#include <private/qcore_mac_p.h>
#ifndef Q_OS_IOS
@@ -66,6 +67,8 @@ Q_DECLARE_METATYPE(ATSFontContainerRef);
QT_BEGIN_NAMESPACE
+struct FontDescription;
+
class QCoreTextFontDatabase : public QPlatformFontDatabase
{
public:
@@ -79,17 +82,25 @@ public:
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
void releaseHandle(void *handle);
+ bool isPrivateFontFamily(const QString &family) const;
QFont defaultFont() const;
QList<int> standardSizes() const;
+ // For iOS and OS X platform themes
+ QFont *themeFont(QPlatformTheme::Font) const;
+ const QHash<QPlatformTheme::Font, QFont *> &themeFonts() const;
+
private:
void populateFromDescriptor(CTFontDescriptorRef font);
+ void populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd);
mutable QString defaultFontName;
void removeApplicationFonts();
QVector<QVariant> m_applicationFonts;
+ mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors;
+ mutable QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
};
QT_END_NAMESPACE