summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qfontengine.cpp
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2012-02-15 15:06:00 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-17 05:26:34 +0100
commit2801db558c56e98753e297c1aeabd4fd2975e09a (patch)
tree14726483adef27b2e19f67ee0a4a0d2ef1a577a9 /src/gui/text/qfontengine.cpp
parent4212898822f1798dac0167e4f6a147bd8a3b3dcc (diff)
Avoid loading and keeping unused fallback font engines
When we request glyphs from fallback fonts, we would potentially load all fonts on the system into memory. This is especially true for glyphs that are not supported by any font (or by the last in the list) in any "Common" script (which e.g. includes CJK). This would make any application which tried to display unsupported glyphs use huge amounts of memory for keeping unused fonts cached, only limited by the number of fonts on the system. The patch contains two solutions: First, before loading the font, the multi font engine will be asked whether it needs to be tried for the given character. By default, this will always be true, so all fonts will be tried, but with the new font config multi engine in the platform plugin, it will ask FontConfig whether the font contains a glyph for the character. Should the font be loaded and still fail to resolve the character (which could be the case for other platforms), we will simply delete it again immediately instead keeping it cached. Change-Id: I92dfb39289a359f49caa02c2caf8baf66098fb59 Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/gui/text/qfontengine.cpp')
-rw-r--r--src/gui/text/qfontengine.cpp37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 156a4a1e59..a084a3dd8c 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1379,18 +1379,24 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
int glyph_pos = 0;
for (int i = 0; i < len; ++i) {
bool surrogate = (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate());
-
+ uint ucs4 = surrogate ? QChar::surrogateToUcs4(str[i], str[i+1]) : str[i].unicode();
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) {
+ for (int x=1; x < engines.size(); ++x) {
+ if (!shouldLoadFontEngineForCharacter(x, ucs4))
+ continue;
+
QFontEngine *engine = engines.at(x);
+ bool deleteThisEngine = false;
if (!engine) {
const_cast<QFontEngineMulti *>(this)->loadEngine(x);
engine = engines.at(x);
+ deleteThisEngine = true;
}
Q_ASSERT(engine != 0);
if (engine->type() == Box)
continue;
+
glyphs->advances_x[glyph_pos] = glyphs->advances_y[glyph_pos] = 0;
glyphs->offsets[glyph_pos] = QFixedPoint();
int num = 2;
@@ -1401,13 +1407,17 @@ 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<QFontEngineMulti *>(this)->unloadEngine(x);
}
}
+
// ensure we use metrics from the 1st font when we use the fallback image.
if (!glyphs->glyphs[glyph_pos]) {
glyphs->setInstance(glyph_pos, tmp);
}
}
+
if (surrogate)
++i;
++glyph_pos;
@@ -1418,6 +1428,29 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
return true;
}
+bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const
+{
+ Q_UNUSED(at);
+ Q_UNUSED(ucs4);
+ return true;
+}
+
+void QFontEngineMulti::unloadEngine(int at)
+{
+ QFontEngine *fontEngine = engines.at(at);
+ if (fontEngine == 0)
+ return;
+
+ // If there are other references to the engine, keep it around and keep the reference
+ if (fontEngine->ref.load() == 1) {
+ QFontCache::instance()->removeEngine(fontEngine);
+ if (fontEngine->cache_count == 0) {
+ delete fontEngine;
+ engines[at] = 0;
+ }
+ }
+}
+
glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
{
if (glyphs.numGlyphs <= 0)