QFont: Fix possible cache misses due to misprepared cache key
Parse the requested family before we're looking/saving into the cache, thus hitting the cached EngineData for: * quoted family names (eg. QFont("'Arial'")) * non-simplified family names (eg. QFont(" Arial ")) * substituted family names (\sa QFont::insertSubstitution()) * explicit fallback list, where possible (eg. QFont("Tahoma, Arial")) This also improves the cache hitting for the font engines in some cases. Change-Id: I18cdc3e8d669cccec961f84e9b27329402e2b7ed Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
This commit is contained in:
parent
270cc073b7
commit
3e5719ae7b
@ -2732,9 +2732,16 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
|
|||||||
if (req.stretch == 0)
|
if (req.stretch == 0)
|
||||||
req.stretch = 100;
|
req.stretch = 100;
|
||||||
|
|
||||||
|
// respect the fallback families that might be passed through the request
|
||||||
|
const QStringList fallBackFamilies = familyList(req);
|
||||||
|
|
||||||
if (!d->engineData) {
|
if (!d->engineData) {
|
||||||
QFontCache *fontCache = QFontCache::instance();
|
QFontCache *fontCache = QFontCache::instance();
|
||||||
// look for the requested font in the engine data cache
|
// look for the requested font in the engine data cache
|
||||||
|
// note: fallBackFamilies are not respected in the EngineData cache key;
|
||||||
|
// join them with the primary selection family to avoid cache misses
|
||||||
|
req.family = fallBackFamilies.join(QLatin1Char(','));
|
||||||
|
|
||||||
d->engineData = fontCache->findEngineData(req);
|
d->engineData = fontCache->findEngineData(req);
|
||||||
if (!d->engineData) {
|
if (!d->engineData) {
|
||||||
// create a new one
|
// create a new one
|
||||||
@ -2748,25 +2755,18 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
|
|||||||
if (d->engineData->engines[script])
|
if (d->engineData->engines[script])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Until we specifically asked not to, try looking for Multi font engine
|
QFontEngine *fe = Q_NULLPTR;
|
||||||
// first, the last '1' indicates that we want Multi font engine instead
|
|
||||||
// of single ones
|
|
||||||
bool multi = !(req.styleStrategy & QFont::NoFontMerging);
|
|
||||||
QFontCache::Key key(req, script, multi ? 1 : 0);
|
|
||||||
|
|
||||||
QFontEngine *fe = QFontCache::instance()->findEngine(key);
|
req.fallBackFamilies = fallBackFamilies;
|
||||||
|
if (!req.fallBackFamilies.isEmpty())
|
||||||
|
req.family = req.fallBackFamilies.takeFirst();
|
||||||
|
|
||||||
// list of families to try
|
// list of families to try
|
||||||
QStringList family_list;
|
QStringList family_list;
|
||||||
|
|
||||||
if (!req.family.isEmpty()) {
|
if (!req.family.isEmpty()) {
|
||||||
QStringList familiesForRequest = familyList(req);
|
|
||||||
|
|
||||||
// Add primary selection
|
// Add primary selection
|
||||||
family_list << familiesForRequest.takeFirst();
|
family_list << req.family;
|
||||||
|
|
||||||
// Fallbacks requested in font request
|
|
||||||
req.fallBackFamilies = familiesForRequest;
|
|
||||||
|
|
||||||
// add the default family
|
// add the default family
|
||||||
QString defaultFamily = QGuiApplication::font().family();
|
QString defaultFamily = QGuiApplication::font().family();
|
||||||
|
@ -48,6 +48,9 @@ public:
|
|||||||
virtual ~tst_QFontCache();
|
virtual ~tst_QFontCache();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void engineData_data();
|
||||||
|
void engineData();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,6 +72,52 @@ tst_QFontCache::~tst_QFontCache()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QFontCache::engineData_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("family");
|
||||||
|
QTest::addColumn<QString>("cacheKey");
|
||||||
|
|
||||||
|
QTest::newRow("unquoted-family-name") << QString("Times New Roman") << QString("Times New Roman");
|
||||||
|
QTest::newRow("quoted-family-name") << QString("'Times New Roman'") << QString("Times New Roman");
|
||||||
|
QTest::newRow("invalid") << QString("invalid") << QString("invalid");
|
||||||
|
QTest::newRow("multiple") << QString("invalid, Times New Roman") << QString("invalid,Times New Roman");
|
||||||
|
QTest::newRow("multiple spaces") << QString("invalid, Times New Roman ") << QString("invalid,Times New Roman");
|
||||||
|
QTest::newRow("multiple spaces quotes") << QString("'invalid', Times New Roman ") << QString("invalid,Times New Roman");
|
||||||
|
QTest::newRow("multiple2") << QString("invalid, Times New Roman , foobar, 'baz'") << QString("invalid,Times New Roman,foobar,baz");
|
||||||
|
QTest::newRow("invalid spaces") << QString("invalid spaces, Times New Roman ") << QString("invalid spaces,Times New Roman");
|
||||||
|
QTest::newRow("invalid spaces quotes") << QString("'invalid spaces', 'Times New Roman' ") << QString("invalid spaces,Times New Roman");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QFontCache::engineData()
|
||||||
|
{
|
||||||
|
QFETCH(QString, family);
|
||||||
|
QFETCH(QString, cacheKey);
|
||||||
|
|
||||||
|
QFont f(family);
|
||||||
|
f.exactMatch(); // loads engine
|
||||||
|
|
||||||
|
QFontPrivate *d = QFontPrivate::get(f);
|
||||||
|
|
||||||
|
QFontDef req = d->request;
|
||||||
|
// copy-pasted from QFontDatabase::load(), to engineer the cache key
|
||||||
|
if (req.pixelSize == -1) {
|
||||||
|
req.pixelSize = std::floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
|
||||||
|
req.pixelSize = qRound(req.pixelSize);
|
||||||
|
}
|
||||||
|
if (req.pointSize < 0)
|
||||||
|
req.pointSize = req.pixelSize*72.0/d->dpi;
|
||||||
|
if (req.weight == 0)
|
||||||
|
req.weight = QFont::Normal;
|
||||||
|
if (req.stretch == 0)
|
||||||
|
req.stretch = 100;
|
||||||
|
|
||||||
|
req.family = cacheKey;
|
||||||
|
|
||||||
|
QFontEngineData *engineData = QFontCache::instance()->findEngineData(req);
|
||||||
|
|
||||||
|
QCOMPARE(engineData, QFontPrivate::get(f)->engineData);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QFontCache::clear()
|
void tst_QFontCache::clear()
|
||||||
{
|
{
|
||||||
#ifdef QT_BUILD_INTERNAL
|
#ifdef QT_BUILD_INTERNAL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user