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);
}