}
+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
#ifndef DIMENSION_H
#define DIMENSION_H
+#include "support/types.h"
namespace lyx {
/// 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;
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
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
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
{
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; }
#include "support/unicode.h"
-using lyx::char_type;
-using lyx::docstring;
-
using std::string;
namespace lyx {
: 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
}
}
-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;
-}
-
-
int GuiFontMetrics::lbearing(char_type c) const
{
return metrics_.leftBearing(ucs4_to_qchar(c));
// casts in reality.
if (ls == 1 && !smallcaps_shape_) {
- QChar const c = ucs4_to_qchar(s[0]);
- return width(c.unicode());
+ return width(s[0]);
}
- QString ucs2;
- ucs4_to_qstring(s, ls, ucs2);
-
- if (smallcaps_shape_)
+ 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;
}
descent = metrics_.descent() + d;
}
-#ifdef USE_LYX_FONTCACHE
-int GuiFontMetrics::width(unsigned short val) const
+#ifndef USE_LYX_FONTCACHE
+
+int GuiFontMetrics::ascent(char_type c) const
{
- if (widthcache_[val] == -1)
- widthcache_[val] = metrics_.width(QChar(val));
- return widthcache_[val];
+ QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
+ return -r.top();
}
-#endif
+
+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
namespace lyx {
namespace frontend {
+struct CharMetrics
+{
+ int width;
+ int ascent;
+ int descent;
+};
+
+
class GuiFontMetrics: public FontMetrics
{
public:
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;
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
};
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;
{
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);
#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_))
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;
{
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;
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")
void MathArray::metrics(MetricsInfo & mi) const
{
- mathed_char_dim(mi.base.font, 'I', dim_);
+ dim_.set(mi.base.font, 'I');
if (empty())
return;
} // 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)
{
return theFontMetrics(font).width(c);
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,
rp.paintChangeBar();
if (rit == rb)
rp.paintFirst();
- rp.paintText();
+ rp.paintText();
if (rit + 1 == re)
rp.paintLast();
}