Good news for Windows and Mac users, this bug is now fixed:

http://bugzilla.lyx.org/show_bug.cgi?id=2900

Jean-Marc, I think you can backport to 1.4 the ascent() and descent() part of the patch. I am quite confident that this alone will solve most speed problem in 1.4 also.

By the way, around section 6.2 of the UserGuide there are some accent characters which are bigger than 65536. Shall I add an assertion for those cases?

Abdel.


Author: younes
Date: Fri Dec  1 17:12:24 2006
New Revision: 16124

URL: http://www.lyx.org/trac/changeset/16124
Log:
This commit fixes the following bug:
http://bugzilla.lyx.org/show_bug.cgi?id=2900

The only drawback is that it requires about 20Mo extra-memory when loading the UserGuide. If it turns out to be too much, we can switch to a QHash based solution instead of a table.

* dimension.[Ch]:
  - Dimension(LyXFont const, char_typec): new ctor
  - set(LyXFont const & font, char_type c): new method.

* frontends/FontMetrics.h:
  - width(char_type): is now a pure virtual method.

* GuiFontMetrics:
  - CharMetrics: new structure;
- the metrics cache now also cache ascent and descent. This is especially useful for mathed.

* MathSupport.[Ch]:
- mathed_char_dim(): deleted. We now use Dimension::set() directly instead.

* rowpainter.C: fixe empty space.


Modified:
    lyx-devel/trunk/src/dimension.C
    lyx-devel/trunk/src/dimension.h
    lyx-devel/trunk/src/frontends/FontMetrics.h
    lyx-devel/trunk/src/frontends/NoGuiFontMetrics.h
    lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.C
    lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.h
    lyx-devel/trunk/src/mathed/InsetMathBrace.C
    lyx-devel/trunk/src/mathed/InsetMathChar.C
    lyx-devel/trunk/src/mathed/InsetMathDelim.C
    lyx-devel/trunk/src/mathed/InsetMathDots.C
    lyx-devel/trunk/src/mathed/MathData.C
    lyx-devel/trunk/src/mathed/MathSupport.C
    lyx-devel/trunk/src/mathed/MathSupport.h
    lyx-devel/trunk/src/rowpainter.C

Modified: lyx-devel/trunk/src/dimension.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/dimension.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/dimension.C (original)
+++ lyx-devel/trunk/src/dimension.C Fri Dec  1 17:12:24 2006
@@ -36,4 +36,12 @@
 }


+void Dimension::set(LyXFont const & font, char_type c)
+{
+       frontend::FontMetrics const & fm = theFontMetrics(font);
+       des = fm.descent(c);
+       asc = fm.ascent(c);
+       wid = fm.width(c);
+}
+
 } // namespace lyx

Modified: lyx-devel/trunk/src/dimension.h
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/dimension.h?rev=16124
==============================================================================
--- lyx-devel/trunk/src/dimension.h (original)
+++ lyx-devel/trunk/src/dimension.h Fri Dec  1 17:12:24 2006
@@ -12,6 +12,7 @@
 #ifndef DIMENSION_H
 #define DIMENSION_H

+#include "support/types.h"

 namespace lyx {

@@ -25,6 +26,8 @@
        /// initialize data
        Dimension(int w, int a, int d) : wid(w), asc(a), des(d) {}

+       Dimension(LyXFont const & font, char_type c) { set(font, c); }
+
        Dimension & operator=(Dimension const & dim) {
                wid = dim.wid;
                asc = dim.asc;
@@ -35,8 +38,11 @@
        void operator+=(Dimension const & dim);
        /// set to empty box
        void clear() { wid = asc = des = 0; }
-       /// set to empty box suitble for given font
+       /// set to empty box suitble for given font.
        void clear(LyXFont const & font);
+       /// set to a char dimensions for a given font.
+       void set(LyXFont const & font, char_type c);
+
        /// get height
        int height() const { return asc + des; }
        /// get ascent

Modified: lyx-devel/trunk/src/frontends/FontMetrics.h
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/frontends/FontMetrics.h?rev=16124
==============================================================================
--- lyx-devel/trunk/src/frontends/FontMetrics.h (original)
+++ lyx-devel/trunk/src/frontends/FontMetrics.h Fri Dec  1 17:12:24 2006
@@ -58,6 +58,8 @@
        virtual int maxAscent() const = 0;
        /// return the maximum descent of the font
        virtual int maxDescent() const = 0;
+       /// return the width of the char in the font
+       virtual int width(char_type c) const = 0;
        /// return the ascent of the char in the font
        virtual int ascent(char_type c) const = 0;
        /// return the descent of the char in the font
@@ -103,13 +105,6 @@
                return (rbearing(c) - lbearing(c)) / 2;
        }

-       /// return the width of the char in the font
-       inline int width(char_type c) const
-       {
-               char_type tmp[2] = { c, L'\0'};
-               return width(tmp, 1);
-       }
-
        /// return the width of the string in the font
        inline int width(docstring const & s) const
        {

Modified: lyx-devel/trunk/src/frontends/NoGuiFontMetrics.h
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/frontends/NoGuiFontMetrics.h?rev=16124
==============================================================================
--- lyx-devel/trunk/src/frontends/NoGuiFontMetrics.h (original)
+++ lyx-devel/trunk/src/frontends/NoGuiFontMetrics.h Fri Dec 1 17:12:24 2006
@@ -31,6 +31,8 @@

        virtual int maxDescent() const { return 1; }
        
+       virtual int width(char_type) const { return 1; }
+
        virtual int ascent(char_type) const { return 1; }
        
        int descent(char_type) const { return 1; }

Modified: lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.C (original)
+++ lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.C Fri Dec 1 17:12:24 2006
@@ -19,9 +19,6 @@

 #include "support/unicode.h"

-using lyx::char_type;
-using lyx::docstring;
-
 using std::string;

 namespace lyx {
@@ -32,8 +29,11 @@
 : metrics_(font), smallcaps_metrics_(font), smallcaps_shape_(false)
 {
 #ifdef USE_LYX_FONTCACHE
-  for (int i = 0; i != 65536; ++i)
-    widthcache_[i] = -1;
+ for (int i = 0; i != 65536; ++i) {
+        metrics_cache_[i].width = -1000;
+        metrics_cache_[i].ascent = -1000;
+        metrics_cache_[i].descent = -1000;
+ }
 #endif
 }

@@ -55,20 +55,6 @@
        // 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_.descent() + 1;
-}
-
-
-int GuiFontMetrics::ascent(char_type c) const
-{
-       QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
-       return -r.top();
-}
-
-
-int GuiFontMetrics::descent(char_type c) const
-{
-       QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
-       return r.bottom() + 1;
 }


@@ -110,19 +96,18 @@
        // casts in reality.

        if (ls == 1 && !smallcaps_shape_) {
-               QChar const c = ucs4_to_qchar(s[0]);
-               return width(c.unicode());
-       }
-
-       QString ucs2;
-       ucs4_to_qstring(s, ls, ucs2);
-
-       if (smallcaps_shape_)
+               return width(s[0]);
+       }
+
+       if (smallcaps_shape_) {
+               QString ucs2;
+               ucs4_to_qstring(s, ls, ucs2);
                return smallcapsWidth(ucs2);
+       }

        int w = 0;
        for (unsigned int i = 0; i < ls; ++i)
-               w += width(ucs2[i].unicode());
+               w += width(s[i]);

        return w;
 }
@@ -178,14 +163,64 @@
        descent = metrics_.descent() + d;
 }

-#ifdef USE_LYX_FONTCACHE
-int GuiFontMetrics::width(unsigned short val) const
-{
-       if (widthcache_[val] == -1)
-               widthcache_[val] = metrics_.width(QChar(val));
-       return widthcache_[val];
-}
+#ifndef USE_LYX_FONTCACHE
+
+int GuiFontMetrics::ascent(char_type c) const
+{
+       QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
+       return -r.top();
+}
+
+
+int GuiFontMetrics::descent(char_type c) const
+{
+       QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
+       return r.bottom() + 1;
+}
+
+#else
+
+void GuiFontMetrics::fillCache(unsigned short val) const
+{
+       QRect const & r = metrics_.boundingRect(QChar(val));
+       metrics_cache_[val].descent = r.bottom() + 1;
+       metrics_cache_[val].ascent = -r.top();
+       // We could as well compute the width but this is not really
+       // needed for now as it is done directly in width() below.
+       //metrics_cache_[val].width = metrics_.width(QChar(val));
+}
+
+
+int GuiFontMetrics::width(char_type c) const
+{
+       unsigned short val = static_cast<unsigned short>(c);
+       if (metrics_cache_[val].width == -1000)
+               metrics_cache_[val].width = metrics_.width(QChar(val));
+
+       return metrics_cache_[val].width;
+}
+
+
+int GuiFontMetrics::ascent(char_type c) const
+{
+       unsigned short val = static_cast<unsigned short>(c);
+       if (metrics_cache_[val].ascent == -1000)
+               fillCache(val);
+
+       return metrics_cache_[val].ascent;
+}
+
+
+int GuiFontMetrics::descent(char_type c) const
+{
+       unsigned short val = static_cast<unsigned short>(c);
+       if (metrics_cache_[val].descent == -1000)
+               fillCache(val);
+
+       return metrics_cache_[val].descent;
+}
+
 #endif

-}
-}
+} // frontend
+} // lyx

Modified: lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.h
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.h?rev=16124
==============================================================================
--- lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.h (original)
+++ lyx-devel/trunk/src/frontends/qt4/GuiFontMetrics.h Fri Dec 1 17:12:24 2006
@@ -27,6 +27,14 @@
 namespace lyx {
 namespace frontend {

+struct CharMetrics
+{
+       int width;
+       int ascent;
+       int descent;
+};
+
+
 class GuiFontMetrics: public FontMetrics
 {
 public:
@@ -38,17 +46,24 @@

        virtual int maxAscent() const;
        virtual int maxDescent() const;
-       virtual int ascent(lyx::char_type c) const;
-       int descent(lyx::char_type c) const;
-       virtual int lbearing(lyx::char_type c) const;
-       virtual int rbearing(lyx::char_type c) const;
-       virtual int width(lyx::char_type const * s, size_t n) const;
-       virtual int signedWidth(lyx::docstring const & s) const;
-       virtual void rectText(lyx::docstring const & str,
+#ifndef USE_LYX_FONTCACHE
+       virtual int width(char_type c) const {
+               return metrics_.width(QChar(static_cast<short int>(c)));
+       }
+#else
+       virtual int width(char_type c) const;
+#endif
+       virtual int ascent(char_type c) const;
+       virtual int descent(char_type c) const;
+       virtual int lbearing(char_type c) const;
+       virtual int rbearing(char_type c) const;
+       virtual int width(char_type const * s, size_t n) const;
+       virtual int signedWidth(docstring const & s) const;
+       virtual void rectText(docstring const & str,
                int & width,
                int & ascent,
                int & descent) const;
-       virtual void buttonText(lyx::docstring const & str,
+       virtual void buttonText(docstring const & str,
                int & width,
                int & ascent,
                int & descent) const;
@@ -64,16 +79,16 @@

        bool smallcaps_shape_;

-#ifndef USE_LYX_FONTCACHE
-       /// Return pixel width for the given unicode char
-       int width(unsigned short val) const { return 
metrics_.width(QChar(val)); }
-
-#else
-       /// Return pixel width for the given unicode char
-       int width(unsigned short val) const;
-
+#ifdef USE_LYX_FONTCACHE
+       /// fill in \c metrics_cache_ at specified value.
+       void fillCache(unsigned short val) const;
        /// Cache of char widths
-       mutable int widthcache_[65536];
+       /** This cache adds 20Mo of memory to the LyX executable when
+       * loading UserGuide.lyx which contains a good number of fonts. If
+       * this turns out to be too much, we can switch to a \c QHash based
+       * solution.
+       **/
+       mutable CharMetrics metrics_cache_[65536];
 #endif // USE_LYX_FONTCACHE
 };


Modified: lyx-devel/trunk/src/mathed/InsetMathBrace.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/InsetMathBrace.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/InsetMathBrace.C (original)
+++ lyx-devel/trunk/src/mathed/InsetMathBrace.C Fri Dec  1 17:12:24 2006
@@ -46,8 +46,7 @@
 bool InsetMathBrace::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        cell(0).metrics(mi);
-       Dimension t;
-       mathed_char_dim(mi.base.font, '{', t);
+       Dimension t(mi.base.font, '{');
        dim.asc = max(cell(0).ascent(), t.asc);
        dim.des = max(cell(0).descent(), t.des);
        dim.wid = cell(0).width() + 2 * t.wid;
@@ -63,8 +62,7 @@
 {
        LyXFont font = pi.base.font;
        font.setColor(LColor::latex);
-       Dimension t;
-       mathed_char_dim(font, '{', t);
+       Dimension t(font, '{');
        pi.pain.text(x, y, '{', font);
        cell(0).draw(pi, x + t.wid, y);
        pi.pain.text(x + t.wid + cell(0).width(), y, '}', font);

Modified: lyx-devel/trunk/src/mathed/InsetMathChar.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/InsetMathChar.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/InsetMathChar.C (original)
+++ lyx-devel/trunk/src/mathed/InsetMathChar.C Fri Dec  1 17:12:24 2006
@@ -62,15 +62,15 @@
 #if 1
        if (char_ == '=' && has_math_fonts) {
                FontSetChanger dummy(mi.base, "cmr");
-               mathed_char_dim(mi.base.font, char_, dim);
+               dim.set(mi.base.font, char_);
        } else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
                FontSetChanger dummy(mi.base, "cmm");
-               mathed_char_dim(mi.base.font, char_, dim);
+               dim.set(mi.base.font, char_);
        } else if (!slanted(char_) && mi.base.fontname == "mathnormal") {
                ShapeChanger dummy(mi.base.font, LyXFont::UP_SHAPE);
-               mathed_char_dim(mi.base.font, char_, dim);
+               dim.set(mi.base.font, char_);
        } else {
-               mathed_char_dim(mi.base.font, char_, dim);
+               dim.set(mi.base.font, char_);
        }
        int const em = mathed_char_width(mi.base.font, 'M');
        if (isBinaryOp(char_))
@@ -79,7 +79,7 @@
                dim.wid += static_cast<int>(0.1667*em+0.5);
 #else
        whichFont(font_, code_, mi);
-       mathed_char_dim(font_, char_, dim);
+       dim.set(font_, char_);
        if (isBinaryOp(char_, code_))
                width_ += 2 * theFontMetrics(font_).width(' ');
        lyxerr << "InsetMathChar::metrics: " << dim << endl;

Modified: lyx-devel/trunk/src/mathed/InsetMathDelim.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/InsetMathDelim.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/InsetMathDelim.C (original)
+++ lyx-devel/trunk/src/mathed/InsetMathDelim.C Fri Dec  1 17:12:24 2006
@@ -75,7 +75,7 @@
 {
        cell(0).metrics(mi);
        Dimension t;
-       mathed_char_dim(mi.base.font, 'I', t);
+       t.set(mi.base.font, 'I');
        int h0 = (t.asc + t.des) / 2;
        int a0 = max(cell(0).ascent(), t.asc)   - h0;
        int d0 = max(cell(0).descent(), t.des)  + h0;

Modified: lyx-devel/trunk/src/mathed/InsetMathDots.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/InsetMathDots.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/InsetMathDots.C (original)
+++ lyx-devel/trunk/src/mathed/InsetMathDots.C Fri Dec  1 17:12:24 2006
@@ -37,7 +37,7 @@

 bool InsetMathDots::metrics(MetricsInfo & mi, Dimension & dim) const
 {
-       mathed_char_dim(mi.base.font, 'M', dim);
+       dim.set(mi.base.font, 'M');
        dh_ = 0;
        if (key_->name == "cdots" || key_->name == "dotsb"
                        || key_->name == "dotsm" || key_->name == "dotsi")

Modified: lyx-devel/trunk/src/mathed/MathData.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/MathData.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/MathData.C (original)
+++ lyx-devel/trunk/src/mathed/MathData.C Fri Dec  1 17:12:24 2006
@@ -241,7 +241,7 @@

 void MathArray::metrics(MetricsInfo & mi) const
 {
-       mathed_char_dim(mi.base.font, 'I', dim_);
+       dim_.set(mi.base.font, 'I');

        if (empty())
                return;

Modified: lyx-devel/trunk/src/mathed/MathSupport.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/MathSupport.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/MathSupport.C (original)
+++ lyx-devel/trunk/src/mathed/MathSupport.C Fri Dec  1 17:12:24 2006
@@ -365,15 +365,6 @@


 } // namespace anon
-
-
-void mathed_char_dim(LyXFont const & font, char_type c, Dimension & dim)
-{
-       frontend::FontMetrics const & fm = theFontMetrics(font);
-       dim.des = fm.descent(c);
-       dim.asc = fm.ascent(c);
-       dim.wid = fm.width(c);
-}


 int mathed_char_width(LyXFont const & font, char_type c)

Modified: lyx-devel/trunk/src/mathed/MathSupport.h
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/mathed/MathSupport.h?rev=16124
==============================================================================
--- lyx-devel/trunk/src/mathed/MathSupport.h (original)
+++ lyx-devel/trunk/src/mathed/MathSupport.h Fri Dec  1 17:12:24 2006
@@ -28,7 +28,6 @@
 class InsetMath;


-void mathed_char_dim(LyXFont const &, char_type c, Dimension & dim);
 int mathed_char_width(LyXFont const &, char_type c);

 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,

Modified: lyx-devel/trunk/src/rowpainter.C
URL: http://www.lyx.org/trac/file/lyx-devel/trunk/src/rowpainter.C?rev=16124
==============================================================================
--- lyx-devel/trunk/src/rowpainter.C (original)
+++ lyx-devel/trunk/src/rowpainter.C Fri Dec  1 17:12:24 2006
@@ -949,7 +949,7 @@
                        rp.paintChangeBar();
                        if (rit == rb)
                                rp.paintFirst();
-                       rp.paintText();
+                       rp.paintText();
                        if (rit + 1 == re)
                                rp.paintLast();
                }



Reply via email to