From 8539f756ed20092fc6ea6273e77299963f6cc7b6 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Tue, 25 Jun 2013 08:18:25 +0200 Subject: [PATCH] Implement real string width computation Important features: * widths are cached in a map * old behavior is still used when lyxrc.force_paint_single_char is true. --- 00README_STR_METRICS_BRANCH | 25 +++++++++++++++++-------- src/frontends/qt4/GuiFontMetrics.cpp | 26 +++++++++++++------------- src/frontends/qt4/GuiFontMetrics.h | 6 ++++++ 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index b34ba5befe..53d9fd3ef2 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -5,20 +5,29 @@ for now we intend to keep unchanged behavior for testing purposes. What is done: * Make TextMetrics methods operate on Row objects: breakRow and -setRowHeight instead of rowBreakPoint and rowHeight. + setRowHeight instead of rowBreakPoint and rowHeight. + * change breakRow operation to operate on text strings on which -metrics are computed. Note that for now FontMetrics::width(docstring) -still computes the sum of character widths, so that behavior is -unchanged. + metrics are computed. Note that for now + FontMetrics::width(docstring) still computes the sum of character + widths, so that behavior is unchanged. + +* Implement proper string metrics computation (with cache), when + lyxrc.force_paint_single_char is false. Next steps: + * Make breakRow build a list of elements (string, inset, -separator,...) in the row. This will be reused by other methods + separator,...) in the row. This will be reused by other methods + * get rid of rowWidth (breakRow does compute this) + * re-implement getColumnNearX using row elements -* re-implement x2pos using row elements -* re-implement row painting using row elements -* Finally, implement proper string metrics computation (with cache) + +* re-implement cursorX using row elements + +* re-implement row painting using row elements (can it be done?) + * profile and see how performance can be improved. Difference in behavior diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index e007b4a151..4be0fb2463 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -15,8 +15,9 @@ #include "qt_helpers.h" -#include "Language.h" #include "Dimension.h" +#include "Language.h" +#include "LyXRC.h" #include "insets/Inset.h" @@ -110,21 +111,20 @@ int GuiFontMetrics::rbearing(char_type c) const int GuiFontMetrics::width(docstring const & s) const { - size_t ls = s.size(); int w = 0; - for (unsigned int i = 0; i < ls; ++i) { - //FIXME: we need to detect surrogate pairs and act accordingly - /** - if isSurrogateBase(s[i]) { - docstring c = s[i]; - w += metrics_.width(toqstr(c + s[i + 1])); - ++i; + if (lyxrc.force_paint_single_char) { + size_t const ls = s.size(); + for (size_t i = 0; i < ls; ++i) + w += width(s[i]); + } else { + map::const_iterator it = strwidth_cache_.find(s); + if (it != strwidth_cache_.end()) { + w = it->second; + } else { + w = metrics_.width(toqstr(s)); + strwidth_cache_[s] = w; } - else - */ - w += width(s[i]); } - return w; } diff --git a/src/frontends/qt4/GuiFontMetrics.h b/src/frontends/qt4/GuiFontMetrics.h index be36dbf23f..a2c57ecc8b 100644 --- a/src/frontends/qt4/GuiFontMetrics.h +++ b/src/frontends/qt4/GuiFontMetrics.h @@ -16,6 +16,8 @@ #include "support/docstring.h" +#include + #include #include @@ -59,6 +61,10 @@ private: /// Cache of char widths mutable QHash width_cache_; + /// Cache of string widths + /// FIXME Try to use a QHash (this requires to define qHash(docstring)) + mutable std::map strwidth_cache_; + struct AscendDescend { int ascent; int descent;