summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2016-12-02 12:44:16 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2016-12-08 16:38:01 +0000
commit50cb2687b2864acf66586fab9dd56716ebda4e9d (patch)
tree75dec7142ac92a9873de2ef3d890bbdd9f5c9a13
parent2488f34ecfd68702b5508c50cca3fb8e967ac8ea (diff)
UIKit: Improve handling of private system fonts / fallback fonts
Commit 2bc7a40048 taught the CoreText font database to populate the families lazily, and in the process added a guard to ensure that we didn't populate internal fonts (prefixed with a '.'), as these fonts would then show up in font selection dialogs. Commit 909d3f5c7 then added support for private fonts, by making it possible to filter out any private fonts from font selection daialogs. But the guard was not removed, so we were still not populating these fonts. This guard has been removed, and the filtering function has been updated to include the conditions of the guard. Next, commit e5e93345c5 used [UIFont fontNamesForFamilyName:] to verify that each family that we registered with the font database would also have matching fonts when finally populated. This is not the right approach, as [UIFont fontNamesForFamilyName:] does not handle internal fonts. Instead we trust what CTFontDescriptorCreateMatchingFontDescriptors() gives us, but make sure to register the resulting font descriptors with the original/originating font family, instead of the one we pull out of the font descriptor. Finally, as of iOS 10, we can use CTFontManagerCopyAvailableFontFamilyNames instead of [UIFont familyNames], which gives us all of the internal font families like on macOS, instead of just the user-visible families. For earlier iOS versions we manually add '.PhoneFallback', as we know it will be available even if not listed in [UIFont familyNames]. The end result is that we register and populate families like '.PhoneFallback', which is critical to supporting more esoteric writing systems. The check in tst_QFont that styles for a given family is not empty has been removed, as we can't guarantee that on all platforms, which is also documented for QFontDatabase::styles(). Task-number: QTBUG-45746 Task-number: QTBUG-50624 Change-Id: I04674dcb2bb36b4cdf5646d540c35727ff3daaad Reviewed-by: Jake Petroules <jake.petroules@qt.io>
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm37
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h2
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp1
3 files changed, 19 insertions, 21 deletions
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 78a0c4d0c9..1e29b12ec4 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -189,11 +189,16 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase()
static CFArrayRef availableFamilyNames()
{
-#if defined(Q_OS_OSX)
- return CTFontManagerCopyAvailableFontFamilyNames();
-#elif defined(QT_PLATFORM_UIKIT)
- return (CFArrayRef) [[UIFont familyNames] retain];
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(1060, 100000, 100000, 30000)
+ if (&CTFontManagerCopyAvailableFontFamilyNames)
+ return CTFontManagerCopyAvailableFontFamilyNames();
#endif
+#if defined(QT_PLATFORM_UIKIT)
+ CFMutableArrayRef familyNames = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)[UIFont familyNames]);
+ CFArrayAppendValue(familyNames, CFSTR(".PhoneFallback"));
+ return familyNames;
+#endif
+ Q_UNREACHABLE();
}
void QCoreTextFontDatabase::populateFontDatabase()
@@ -207,17 +212,6 @@ void QCoreTextFontDatabase::populateFontDatabase()
for (int i = 0; i < numberOfFamilies; ++i) {
CFStringRef familyNameRef = (CFStringRef) CFArrayGetValueAtIndex(familyNames, i);
QString familyName = QString::fromCFString(familyNameRef);
-
- // Don't populate internal fonts
- if (familyName.startsWith(QLatin1Char('.')) || familyName == QLatin1String("LastResort"))
- continue;
-
-#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
- // Skip font families with no corresponding fonts
- if (![UIFont fontNamesForFamilyName:(NSString*)familyNameRef].count)
- continue;
-#endif
-
QPlatformFontDatabase::registerFontFamily(familyName);
#if defined(Q_OS_OSX)
@@ -250,7 +244,7 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName)
const int numFonts = CFArrayGetCount(matchingFonts);
for (int i = 0; i < numFonts; ++i)
- populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)));
+ populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)), familyName);
}
struct FontDescription {
@@ -352,13 +346,18 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
}
}
-void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
+void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName)
{
FontDescription fd;
getFontDescription(font, &fd);
+ // Note: The familyName we are registering, and the family name of the font descriptor, may not
+ // match, as CTFontDescriptorCreateMatchingFontDescriptors will return descriptors for replacement
+ // fonts if a font family does not have any fonts available on the system.
+ QString family = !familyName.isNull() ? familyName : static_cast<QString>(fd.familyName);
+
CFRetain(font);
- QPlatformFontDatabase::registerFont(fd.familyName, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
+ QPlatformFontDatabase::registerFont(family, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
true /* antialiased */, true /* scalable */,
fd.pixelSize, fd.fixedPitch, fd.writingSystems, (void *) font);
}
@@ -699,7 +698,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const
{
- if (family.startsWith(QLatin1Char('.')))
+ if (family.startsWith(QLatin1Char('.')) || family == QLatin1String("LastResort"))
return true;
return QPlatformFontDatabase::isPrivateFontFamily(family);
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 1bc3522bda..3b1be2e6a1 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -92,7 +92,7 @@ public:
const QHash<QPlatformTheme::Font, QFont *> &themeFonts() const;
private:
- void populateFromDescriptor(CTFontDescriptorRef font);
+ void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString());
#ifndef QT_NO_FREETYPE
bool m_useFreeType;
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index ca984a26a5..a6d8944656 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -130,7 +130,6 @@ void tst_QFont::italicOblique()
QString family = *f_it;
QStringList styles = fdb.styles(family);
- QVERIFY(!styles.isEmpty());
QStringList::ConstIterator s_it, s_end = styles.end();
for (s_it = styles.begin(); s_it != s_end; ++s_it) {
QString style = *s_it;