diff options
author | Andreas Hartmetz <andreas@ixgreen.de> | 2019-06-10 14:39:04 +0200 |
---|---|---|
committer | Andreas Hartmetz <andreas@ixgreen.de> | 2019-07-06 19:55:02 +0200 |
commit | eea99e1e8f3eb67fda35dd3a656fe9b5a9be84f2 (patch) | |
tree | bd94743a619725bc00c1b76add389baa3005ff30 /src/platformsupport | |
parent | 619b92385ead871d1a220bf4bed5a6d2dd09a4fc (diff) |
Fontconfig font database: Short-circuit matching by filename
If the filename matches, no other matching is necessary. Fontconfig
doesn't have a fast path for that, so implement one here.
Fontconfig is unlikely to add that fast path, see here:
https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/103
With -O1 builds of Qt and KDE stack, 358 fonts installed according
to KDE systemsetting, on a Ryzen 1800X, startup time of kwrite
decreases as following according to perf stat:
msec task-clock: ~480 ms to ~455 ms
cycles: ~1.73e9 to ~1.65e9
Change-Id: I630a80e4bed2647d5bbd95247005aab7d0cb0363
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/platformsupport')
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 7abf295782..e28b40c240 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -927,38 +927,66 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef antialias = antialiasingEnabled - 1; } - QFontEngine::GlyphFormat format; - // try and get the pattern + // try to find a match for fid + const QFontEngine::FaceId fid = engine->faceId(); FcPattern *pattern = FcPatternCreate(); + FcPattern *match = nullptr; + + // try a trivial match by filename - FC_FILE is highest priority, so if it matches, FcFontMatch + // will just find the file (fine) and spend a millisecond or so doing unnecessary work (bad). + if (!fid.filename.isEmpty() && QFile::exists(QString::fromUtf8(fid.filename))) { + FcBlanks *blanks = FcConfigGetBlanks(nullptr); + int count = 0; + FcPattern *fileMatch = FcFreeTypeQuery((const FcChar8 *)fid.filename.data(), fid.index, + blanks, &count); + if (fileMatch) { + // Apply Fontconfig configuration - FcFreeTypeQuery only returns information stored in + // the font file, we also want to respect system and user settings. + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + match = FcFontRenderPrepare(0, pattern, fileMatch); + FcPatternDestroy(fileMatch); + } + } - FcValue value; - value.type = FcTypeString; - QByteArray cs = fontDef.family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern,FC_FAMILY,value,true); + if (!match) { + FcValue value; - QFontEngine::FaceId fid = engine->faceId(); + // Fontconfig rules might process this information for arbitrary purposes, so add it, + // even though we already know that it doesn't match an existing file. + if (!fid.filename.isEmpty()) { + value.type = FcTypeString; + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern, FC_FILE, value, true); - if (!fid.filename.isEmpty()) { - value.u.s = (const FcChar8 *)fid.filename.data(); - FcPatternAdd(pattern,FC_FILE,value,true); + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern, FC_INDEX, value, true); + } - value.type = FcTypeInteger; - value.u.i = fid.index; - FcPatternAdd(pattern,FC_INDEX,value,true); - } + const QByteArray cs = fontDef.family.toUtf8(); + value.type = FcTypeString; + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern, FC_FAMILY, value, true); - if (fontDef.pixelSize > 0.1) - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); + if (fontDef.pixelSize > 0.1) { + value.type = FcTypeDouble; + value.u.d = fontDef.pixelSize; + FcPatternAdd(pattern, FC_PIXEL_SIZE, value, true); + } - FcResult result; + FcResult result; - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); - FcPattern *match = FcFontMatch(0, pattern, &result); + match = FcFontMatch(0, pattern, &result); + } + + QFontEngine::GlyphFormat format; if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); + engine->setDefaultHintStyle(defaultHintStyleFromMatch( + (QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); FcBool fc_autohint; if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) |