Fix a performance regression with shouldLoadFontEngineForCharacter.

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>
This commit is contained in:
Pierre Rossi 2012-03-07 14:53:57 +01:00 committed by Qt by Nokia
parent 4ba895a863
commit 7e53debcf2
2 changed files with 38 additions and 14 deletions

View File

@ -42,7 +42,6 @@
#include "qfontenginemultifontconfig_p.h" #include "qfontenginemultifontconfig_p.h"
#include <QtGui/private/qfontengine_ft_p.h> #include <QtGui/private/qfontengine_ft_p.h>
#include <fontconfig/fontconfig.h>
#include <QtGui/private/qfontengine_ft_p.h> #include <QtGui/private/qfontengine_ft_p.h>
QT_BEGIN_NAMESPACE 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 bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint ucs4) const
{ {
QFontEngineFT *fontEngine = static_cast<QFontEngineFT *>(engines.at(at)); QFontEngineFT *fontEngine = static_cast<QFontEngineFT *>(engines.at(at));
@ -61,27 +68,37 @@ bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint u
FcCharSet *charSet = fontEngine->freetype->charset; FcCharSet *charSet = fontEngine->freetype->charset;
charSetHasChar = FcCharSetHasChar(charSet, ucs4); charSetHasChar = FcCharSetHasChar(charSet, ucs4);
} else { } else {
FcPattern *requestPattern = FcPatternCreate(); FcPattern *matchPattern = getMatchPatternForFallback(at - 1);
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);
if (matchPattern != 0) { if (matchPattern != 0) {
FcCharSet *charSet; FcCharSet *charSet;
FcPatternGetCharSet(matchPattern, FC_CHARSET, 0, &charSet); FcPatternGetCharSet(matchPattern, FC_CHARSET, 0, &charSet);
charSetHasChar = FcCharSetHasChar(charSet, ucs4); charSetHasChar = FcCharSetHasChar(charSet, ucs4);
FcPatternDestroy(matchPattern);
} }
FcPatternDestroy(requestPattern);
} }
return charSetHasChar; 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 QT_END_NAMESPACE

View File

@ -43,6 +43,7 @@
#define QFONTENGINEMULTIFONTCONFIG_H #define QFONTENGINEMULTIFONTCONFIG_H
#include <QtGui/private/qfontengine_qpa_p.h> #include <QtGui/private/qfontengine_qpa_p.h>
#include <fontconfig/fontconfig.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -52,7 +53,13 @@ class QFontEngineMultiFontConfig : public QFontEngineMultiQPA
public: public:
explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script, const QStringList &fallbacks); explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script, const QStringList &fallbacks);
~QFontEngineMultiFontConfig();
bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const; bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
private:
FcPattern* getMatchPatternForFallback(int at) const;
mutable QVector<FcPattern*> cachedMatchPatterns;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE