Use a QCache for string metrics

This is better because it implements a LRU cache. Indeed, while editing in particular, width of many different strings has to be computed. This is different from the previous situation where only width of single characters was computed and cached.
This commit is contained in:
Jean-Marc Lasgouttes 2015-11-09 10:11:57 +01:00
parent 735c10d039
commit b26b90ae0e
3 changed files with 27 additions and 17 deletions

View File

@ -259,8 +259,9 @@ FontLoader::~FontLoader()
/////////////////////////////////////////////////
namespace {
static QString makeFontName(QString const & family, QString const & foundry)
QString makeFontName(QString const & family, QString const & foundry)
{
QString res = family;
if (!foundry.isEmpty())
@ -269,9 +270,9 @@ static QString makeFontName(QString const & family, QString const & foundry)
}
GuiFontInfo::GuiFontInfo(FontInfo const & f)
: metrics(QFont())
QFont makeQFont(FontInfo const & f)
{
QFont font;
QString const pat = symbolFamily(f.family());
if (!pat.isEmpty()) {
bool ok;
@ -347,9 +348,16 @@ GuiFontInfo::GuiFontInfo(FontInfo const & f)
LYXERR(Debug::FONT, "The font has size: " << font.pointSizeF());
metrics = GuiFontMetrics(font);
return font;
}
} // anon namespace
GuiFontInfo::GuiFontInfo(FontInfo const & f)
: font(makeQFont(f)), metrics(font)
{}
bool FontLoader::available(FontInfo const & f)
{

View File

@ -53,7 +53,10 @@ inline QChar const ucs4_to_qchar(char_type const ucs4)
} // anon namespace
GuiFontMetrics::GuiFontMetrics(QFont const & font) : font_(font), metrics_(font, 0)
// Limit strwidth_cache_ size to 512kB of string data
GuiFontMetrics::GuiFontMetrics(QFont const & font)
: font_(font), metrics_(font, 0),
strwidth_cache_(1 << 19)
{
}
@ -138,14 +141,14 @@ int GuiFontMetrics::rbearing(char_type c) const
int GuiFontMetrics::width(docstring const & s) const
{
int w = 0;
map<docstring, int>::const_iterator it = strwidth_cache_.find(s);
if (it != strwidth_cache_.end()) {
w = it->second;
} else {
w = metrics_.width(toqstr(s));
strwidth_cache_[s] = w;
}
QByteArray qba =
QByteArray(reinterpret_cast<char const *>(s.data()),
s.size() * sizeof(docstring::value_type));
int * pw = strwidth_cache_[qba];
if (pw)
return *pw;
int w = metrics_.width(toqstr(s));
strwidth_cache_.insert(qba, new int(w), qba.size());
return w;
}

View File

@ -16,8 +16,8 @@
#include "support/docstring.h"
#include <map>
#include <QByteArray>
#include <QCache>
#include <QFont>
#include <QFontMetrics>
#include <QHash>
@ -73,8 +73,7 @@ private:
mutable QHash<char_type, int> width_cache_;
/// Cache of string widths
/// FIXME Try to use a QHash (this requires to define qHash(docstring))
mutable std::map<docstring, int> strwidth_cache_;
mutable QCache<QByteArray, int> strwidth_cache_;
struct AscendDescend {
int ascent;