CoreText: Order fallback fonts based on writing system support

After we stopped sanitizing the fallback font list (with change
6ca48a847a), we now need to make
sure it is ordered so that the fonts that support the writing
system in question are always tested first, otherwise we can end up
loading a lot of fonts that will never be used.

Task-number: QTBUG-65605
Change-Id: Id2a65bbff3e64e6d6e6b4f72500778ee3e811e84
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2018-01-08 13:29:38 +01:00
parent fcbaa8ec38
commit 12687ccfd5
3 changed files with 73 additions and 0 deletions

View File

@ -2837,6 +2837,41 @@ QString QFontDatabase::resolveFontFamilyAlias(const QString &family)
return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->resolveFontFamilyAlias(family);
}
Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families)
{
size_t writingSystem = std::find(scriptForWritingSystem,
scriptForWritingSystem + QFontDatabase::WritingSystemsCount,
script) - scriptForWritingSystem;
if (writingSystem == QFontDatabase::Any
|| writingSystem >= QFontDatabase::WritingSystemsCount) {
return families;
}
QFontDatabasePrivate *db = privateDb();
QMultiMap<uint, QString> supported;
for (int i = 0; i < families.size(); ++i) {
const QString &family = families.at(i);
QtFontFamily *testFamily = nullptr;
for (int x = 0; x < db->count; ++x) {
if (Q_UNLIKELY(matchFamilyName(family, db->families[x]))) {
testFamily = db->families[x];
testFamily->ensurePopulated();
break;
}
}
uint order = i;
if (testFamily == nullptr
|| (testFamily->writingSystems[writingSystem] & QtFontFamily::Supported) == 0) {
order |= 1 << 31;
}
supported.insert(order, family);
}
return supported.values();
}
QT_END_NAMESPACE

View File

@ -544,6 +544,9 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
fallbackList.append(QStringLiteral("Arial Unicode MS"));
#endif
extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
return fallbackList;
}
}

View File

@ -90,6 +90,9 @@ private slots:
void rawFontFromInvalidData();
void kernedAdvances();
void fallbackFontsOrder();
private:
QString testFont;
QString testFontBoldItalic;
@ -1009,6 +1012,38 @@ void tst_QRawFont::kernedAdvances()
QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin));
}
void tst_QRawFont::fallbackFontsOrder()
{
QFontDatabase fontDatabase;
int id = fontDatabase.addApplicationFont(testFont);
QFont font("QtBidiTestFont");
font.setPixelSize(12.0);
QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic);
// If this fails, then the writing system sample has changed and we need to create
// a new text containing both a space and Arabic characters.
QVERIFY(arabicText.contains(QLatin1Char(' ')));
QTextLayout layout;
layout.setFont(font);
layout.setText(arabicText);
layout.setCacheEnabled(true);
layout.beginLayout();
layout.createLine();
layout.endLayout();
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
// Since QtBidiTestFont does not support Arabic nor the space, both should map to
// the same font. If this fails, it is an indication that the list of fallbacks fonts
// is not sorted by writing system support.
QCOMPARE(glyphRuns.size(), 1);
fontDatabase.removeApplicationFont(id);
}
#endif // QT_NO_RAWFONT
QTEST_MAIN(tst_QRawFont)