From 7db64cdbb26e0026d02cc541afab2b3df03a4baa Mon Sep 17 00:00:00 2001 From: John Levon Date: Wed, 11 Dec 2002 00:22:37 +0000 Subject: [PATCH] widthcache ting git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@5802 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt2/ChangeLog | 7 +++ src/frontends/qt2/qfont_loader.C | 31 ++++++++++---- src/frontends/qt2/qfont_loader.h | 17 ++++++-- src/frontends/qt2/qfont_metrics.C | 71 ++++++++++++++++++++----------- 4 files changed, 90 insertions(+), 36 deletions(-) diff --git a/src/frontends/qt2/ChangeLog b/src/frontends/qt2/ChangeLog index 3f12b63d15..d6dc81d23f 100644 --- a/src/frontends/qt2/ChangeLog +++ b/src/frontends/qt2/ChangeLog @@ -1,3 +1,10 @@ +2002-12-11 John Levon + + * qfont_loader.h: + * qfont_loader.C: + * qfont_metrics.C: cache per-char widths to avoid slowness + of QFontMetrics::width + 2002-12-10 John Levon * ui/QURLDialog.ui: fix tab order diff --git a/src/frontends/qt2/qfont_loader.C b/src/frontends/qt2/qfont_loader.C index 40d79e3bc0..83f6e168d4 100644 --- a/src/frontends/qt2/qfont_loader.C +++ b/src/frontends/qt2/qfont_loader.C @@ -23,6 +23,7 @@ #include "qt_helpers.h" #include +#include #if QT_VERSION < 300 #include "support/lstrings.h" #endif @@ -225,22 +226,36 @@ qfont_loader::font_info::font_info(LyXFont const & f) } -qfont_loader::font_info const * qfont_loader::getfontinfo(LyXFont const & f) +qfont_loader::font_info * qfont_loader::getfontinfo(LyXFont const & f) { if (!lyxrc.use_gui) { // FIXME } - font_info const * fi = fontinfo_[f.family()][f.series()][f.realShape()][f.size()]; - if (!fi) { - fi = new font_info(f); - fontinfo_[f.family()][f.series()][f.realShape()][f.size()] = fi; - } - - return fi; + font_info * fi = fontinfo_[f.family()][f.series()][f.realShape()][f.size()]; + if (fi) + return fi; + + font_info * fi2 = new font_info(f); + fontinfo_[f.family()][f.series()][f.realShape()][f.size()] = fi2; + return fi2; } +int qfont_loader::charwidth(LyXFont const & f, Uchar val) +{ + font_info * fi = getfontinfo(f); + + font_info::WidthCache::const_iterator cit = fi->widthcache.find(val); + if (cit != fi->widthcache.end()) + return cit->second; + + int const w = fi->metrics.width(QChar(val)); + fi->widthcache[val] = w; + return w; +} + + bool qfont_loader::available(LyXFont const & f) { if (!lyxrc.use_gui) diff --git a/src/frontends/qt2/qfont_loader.h b/src/frontends/qt2/qfont_loader.h index 8c01b202cf..be0a3589f3 100644 --- a/src/frontends/qt2/qfont_loader.h +++ b/src/frontends/qt2/qfont_loader.h @@ -16,11 +16,14 @@ #pragma interface #endif +#include + +#include "encoding.h" #include "lyxfont.h" #include #include - + /** * Qt font loader for LyX. Matches LyXFonts against * actual QFont instances, and also caches metrics. @@ -44,6 +47,10 @@ public: QFontMetrics const & metrics(LyXFont const & f) { return getfontinfo(f)->metrics; } + + /// return pixel width for the given unicode char + int charwidth(LyXFont const & f, Uchar val); + private: /// hold info about a particular font struct font_info { @@ -53,13 +60,17 @@ private: QFont font; /// metrics on the font QFontMetrics metrics; + + typedef std::map WidthCache; + /// cache of char widths + WidthCache widthcache; }; /// get font info (font + metrics) for the given LyX font. Does not fail. - font_info const * getfontinfo(LyXFont const & f); + font_info * getfontinfo(LyXFont const & f); /// BUTT ugly ! - font_info const * fontinfo_[LyXFont::NUM_FAMILIES][2][4][10]; + font_info * fontinfo_[LyXFont::NUM_FAMILIES][2][4][10]; }; extern qfont_loader fontloader; diff --git a/src/frontends/qt2/qfont_metrics.C b/src/frontends/qt2/qfont_metrics.C index 3019577e82..c464ecbadb 100644 --- a/src/frontends/qt2/qfont_metrics.C +++ b/src/frontends/qt2/qfont_metrics.C @@ -24,8 +24,7 @@ #include #include - - + namespace { QFontMetrics const & metrics(LyXFont const & f) @@ -33,6 +32,12 @@ QFontMetrics const & metrics(LyXFont const & f) return fontloader.metrics(f); } + +int charwidth(Uchar val, LyXFont const & f) +{ + return fontloader.charwidth(f, val); +} + } // namespace anon @@ -46,22 +51,22 @@ int maxAscent(LyXFont const & f) 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,45 +86,61 @@ int rbearing(char c, LyXFont const & f) } -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; } + + +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 charwidth(encoding->ucs(s[0]), f); + } + + int w = 0; + + for (size_t i = 0; i < ls; ++i) { + w += charwidth(encoding->ucs(s[i]), f); + } + + return w; +} int signedWidth(string const & s, LyXFont const & f)