Fix a performance regression with shouldLoadFontEngineForCharacter.
authorPierre Rossi <pierre.rossi@nokia.com>
Wed, 7 Mar 2012 13:53:57 +0000 (14:53 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 8 Mar 2012 22:52:34 +0000 (23:52 +0100)
Calling FcFontMatch should be avoided as much as possible. We can simply
cache the patterns it returns, which should still save memory compared to
loading all font engines as we did before.

Change-Id: I67208a4f919338a948535f717cfd0139dbea2e5f
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp
src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h

index 7b28b20..2016500 100644 (file)
@@ -42,7 +42,6 @@
 #include "qfontenginemultifontconfig_p.h"
 
 #include <QtGui/private/qfontengine_ft_p.h>
-#include <fontconfig/fontconfig.h>
 #include <QtGui/private/qfontengine_ft_p.h>
 
 QT_BEGIN_NAMESPACE
@@ -53,6 +52,14 @@ QFontEngineMultiFontConfig::QFontEngineMultiFontConfig(QFontEngine *fe, int scri
 {
 }
 
+QFontEngineMultiFontConfig::~QFontEngineMultiFontConfig()
+{
+    Q_FOREACH (FcPattern *pattern, cachedMatchPatterns) {
+        if (pattern)
+            FcPatternDestroy(pattern);
+    }
+}
+
 bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint ucs4) const
 {
     QFontEngineFT *fontEngine = static_cast<QFontEngineFT *>(engines.at(at));
@@ -61,27 +68,37 @@ bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint u
         FcCharSet *charSet = fontEngine->freetype->charset;
         charSetHasChar = FcCharSetHasChar(charSet, ucs4);
     } else {
-        FcPattern *requestPattern = FcPatternCreate();
-
-        FcValue value;
-        value.type = FcTypeString;
-        QByteArray cs = fallbackFamilyAt(at-1).toUtf8();
-        value.u.s = reinterpret_cast<const FcChar8 *>(cs.data());
-        FcPatternAdd(requestPattern, FC_FAMILY, value, true);
-
-        FcResult result;
-        FcPattern *matchPattern = FcFontMatch(0, requestPattern, &result);
+        FcPattern *matchPattern = getMatchPatternForFallback(at - 1);
         if (matchPattern != 0) {
             FcCharSet *charSet;
             FcPatternGetCharSet(matchPattern, FC_CHARSET, 0, &charSet);
             charSetHasChar = FcCharSetHasChar(charSet, ucs4);
-            FcPatternDestroy(matchPattern);
         }
-
-        FcPatternDestroy(requestPattern);
     }
 
     return charSetHasChar;
 }
 
+
+FcPattern * QFontEngineMultiFontConfig::getMatchPatternForFallback(int fallBackIndex) const
+{
+    Q_ASSERT(fallBackIndex < fallbackFamilyCount());
+    if (engines.size() - 1 > cachedMatchPatterns.size())
+        cachedMatchPatterns.resize(engines.size() - 1);
+    FcPattern *ret = cachedMatchPatterns.at(fallBackIndex);
+    if (ret)
+        return ret;
+    FcPattern *requestPattern = FcPatternCreate();
+    FcValue value;
+    value.type = FcTypeString;
+    QByteArray cs = fallbackFamilyAt(fallBackIndex).toUtf8();
+    value.u.s = reinterpret_cast<const FcChar8 *>(cs.data());
+    FcPatternAdd(requestPattern, FC_FAMILY, value, true);
+    FcResult result;
+    ret = FcFontMatch(0, requestPattern, &result);
+    cachedMatchPatterns.insert(fallBackIndex, ret);
+    FcPatternDestroy(requestPattern);
+    return ret;
+}
+
 QT_END_NAMESPACE
index 4323cb7..260a9b5 100644 (file)
@@ -43,6 +43,7 @@
 #define QFONTENGINEMULTIFONTCONFIG_H
 
 #include <QtGui/private/qfontengine_qpa_p.h>
+#include <fontconfig/fontconfig.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -52,7 +53,13 @@ class QFontEngineMultiFontConfig : public QFontEngineMultiQPA
 public:
     explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script, const QStringList &fallbacks);
 
+    ~QFontEngineMultiFontConfig();
+
     bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
+private:
+    FcPattern* getMatchPatternForFallback(int at) const;
+
+    mutable QVector<FcPattern*> cachedMatchPatterns;
 };
 
 QT_END_NAMESPACE