From 9f13a7d020749e936dfe0b4c0a1d46f4dbee810f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 2 Mar 2012 16:20:55 +0100 Subject: Make cache of opentype tables in Harfbuzz face lazy The mechanism in fontconfig which determines if a certain character is available (FcCharSetHasChar()) may give false positives, in which case we would load and unload those fonts per every char for which FC gave us a false positive. This was a major performance regression. Specifically the false positives happened when looking at e.g. italic variants of certain multilingual fonts, since we only check the charset of the font family as a whole and not of the specific variant, which may only support a subset of the chars. To optimize this, we remove the deletion of the font engines after loading them, but also wait with loading the opentype tables until they are actually needed. This means that for the false positives, we will load the font, but the cached data for each unused font will be much smaller. Change-Id: Idfc794401a2080da5946bf65204eb947aeb635ed Reviewed-by: Lars Knoll --- src/gui/text/qfontengine.cpp | 15 ++++++++++----- src/gui/text/qfontengine_p.h | 1 + src/gui/text/qtextengine.cpp | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src/gui') diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 4bceb28ef7..142d627100 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -227,6 +227,15 @@ HB_Face QFontEngine::harfbuzzFace() const return hbFace; } +HB_Face QFontEngine::initializedHarfbuzzFace() const +{ + HB_Face face = harfbuzzFace(); + if (face != 0 && face->font_for_init != 0) + face = qHBLoadFace(face); + + return face; +} + glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix) { glyph_metrics_t metrics = boundingBox(glyph); @@ -1364,15 +1373,13 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) { QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); for (int x=1; x < engines.size(); ++x) { - if (!shouldLoadFontEngineForCharacter(x, ucs4)) + if (engines.at(x) == 0 && !shouldLoadFontEngineForCharacter(x, ucs4)) continue; QFontEngine *engine = engines.at(x); - bool deleteThisEngine = false; if (!engine) { const_cast(this)->loadEngine(x); engine = engines.at(x); - deleteThisEngine = true; } Q_ASSERT(engine != 0); if (engine->type() == Box) @@ -1388,8 +1395,6 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, // set the high byte to indicate which engine the glyph came from glyphs->glyphs[glyph_pos] |= (x << 24); break; - } else if (deleteThisEngine) { - const_cast(this)->unloadEngine(x); } } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 44464ee788..660e3be459 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -235,6 +235,7 @@ public: HB_Font harfbuzzFont() const; HB_Face harfbuzzFace() const; + HB_Face initializedHarfbuzzFace() const; virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 0460db14d5..dae02def07 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1112,7 +1112,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const si.leading = qMax(actualFontEngine->leading(), si.leading); shaper_item.font = actualFontEngine->harfbuzzFont(); - shaper_item.face = actualFontEngine->harfbuzzFace(); + shaper_item.face = actualFontEngine->initializedHarfbuzzFace(); shaper_item.glyphIndicesPresent = true; -- cgit v1.2.3