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

Reply via email to