Well I'm out of ideas so here's a dumb patch that caches single widths. Qt :
moz src 335 ./lyx lyxdoc/UserGuide.lyx resize took 1.64121 seconds resize took 1.18429 seconds resize took 1.3532 seconds resize took 1.16759 seconds resize took 1.1749 seconds xforms : resize took 1.10012 seconds resize took 0.828689 seconds resize took 0.831414 seconds resize took 0.762123 seconds resize took 0.769867 seconds So it's quite a bit less than twice as slow. I still need to hook this into the font-invalidate stuff, but it's complete-ish otherwise. Comments ? regards john Index: qfont_metrics.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/qfont_metrics.C,v retrieving revision 1.17 diff -u -r1.17 qfont_metrics.C --- qfont_metrics.C 21 Oct 2002 15:51:06 -0000 1.17 +++ qfont_metrics.C 10 Dec 2002 00:33:40 -0000 @@ -25,6 +25,12 @@ #include <qfontmetrics.h> #include <qfont.h> +#include <list> + +using std::pair; +using std::map; +using std::make_pair; +using std::list; namespace { @@ -46,22 +52,22 @@ int maxDescent(LyXFont const & f) { - return metrics(f).descent()+1; // We add 1 as the value returned by QT is different than X // See http://doc.trolltech.com/2.3/qfontmetrics.html#200b74 + return metrics(f).descent() + 1; } int ascent(char c, LyXFont const & f) { - QRect r = metrics(f).boundingRect(c); + QRect const & r = metrics(f).boundingRect(c); return -r.top(); } int descent(char c, LyXFont const & f) { - QRect r = metrics(f).boundingRect(c); + QRect const & r = metrics(f).boundingRect(c); return r.bottom()+1; } @@ -81,44 +87,95 @@ } -int width(char const * s, size_t ls, LyXFont const & f) +Encoding const * fontencoding(LyXFont const & f) { Encoding const * encoding = f.language()->encoding(); if (f.isSymbolFont()) encoding = encodings.symbol_encoding(); + return encoding; +} + - QString str; -#if QT_VERSION >= 300 - str.setLength(ls); - for (size_t i = 0; i < ls; ++i) - str[i] = QChar(encoding->ucs(s[i])); -#else - for (size_t i = 0; i < ls; ++i) - str += QChar(encoding->ucs(s[i])); -#endif - - if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) { - return metrics(f).width(str); - } - +int smallcapswidth(char const * s, size_t ls, LyXFont const & f) +{ // handle small caps ourselves ... LyXFont smallfont(f); smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE); - QFontMetrics qm = fontloader.metrics(f); - QFontMetrics qsmallm = fontloader.metrics(smallfont); + QFontMetrics const & qm = fontloader.metrics(f); + QFontMetrics const & qsmallm = fontloader.metrics(smallfont); + Encoding const * encoding(fontencoding(f)); + int w = 0; for (size_t i = 0; i < ls; ++i) { - QChar const c = str[i].upper(); - if (c != str[i]) - w += qsmallm.width(c); + QChar const c = QChar(encoding->ucs(s[i])); + QChar const uc = c.upper(); + if (c != uc) + w += qsmallm.width(uc); else w += qm.width(c); } return w; +} + + + +typedef pair<LyXFont, int> MetricPair; +typedef vector<MetricPair> MetricList; +typedef map<Uchar, MetricList> CharMetrics; +CharMetrics char_metrics; + +int singlewidth(Uchar val, LyXFont const & f) +{ + CharMetrics::iterator it(char_metrics.find(val)); + if (it != char_metrics.end()) { + MetricList::const_iterator lit(it->second.begin()); + MetricList::const_iterator lend(it->second.end()); + for (; lit < lend; ++lit) { + if (lit->first == f) + return lit->second; + } + + int const w = metrics(f).width(QChar(val)); + MetricList & list(it->second); + list.push_back(make_pair(f, w)); + return w; + } + + int const w = metrics(f).width(QChar(val)); + MetricList list; + list.push_back(make_pair(f, w)); + char_metrics[val] = list; + return w; +} + + +int width(char const * s, size_t ls, LyXFont const & f) +{ + if (f.realShape() == LyXFont::SMALLCAPS_SHAPE) { + return smallcapswidth(s, ls, f); + } + + Encoding const * encoding(fontencoding(f)); + + if (ls == 1) { + return singlewidth(encoding->ucs(s[0]), f); + } + + QString str; +#if QT_VERSION >= 300 + str.setLength(ls); + for (size_t i = 0; i < ls; ++i) + str[i] = QChar(encoding->ucs(s[i])); +#else + for (size_t i = 0; i < ls; ++i) + str += QChar(encoding->ucs(s[i])); +#endif + + return metrics(f).width(str, ls); }