From f3cdf74e68bd44074ed985106361552161efde2c Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Mon, 7 Dec 2015 10:32:34 +0100 Subject: [PATCH] Remember the last used QTextLayout object This crude caching mecanism is useful in the particular case of a screen with many misspelling dotted lines. In this case, it is necessary to build a QTextLayout in order to know where to put the start/end of the spell line. Since rows typically contains text snippets longer than a word, we may be in a situation where the same QTextLayout is constructed repeatedly. This commit is useful in this particular use case, and should not be costly in other cases. A better fix would be to remember the QTextLayout associated to each row element. This is a bit more work, so this fix should be sufficient for now. Additionally, do not paint misspelled marks when painting is disabled. Fixes bug #9890. --- src/RowPainter.cpp | 2 +- src/frontends/qt4/GuiFontMetrics.cpp | 43 +++++++++++++++++++--------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp index ec083e9ac5..8c62926889 100644 --- a/src/RowPainter.cpp +++ b/src/RowPainter.cpp @@ -609,7 +609,7 @@ void RowPainter::paintText() paintStringAndSel(e); // Paint the spelling marks if enabled. - if (lyxrc.spellcheck_continuously && pi_.do_spellcheck) + if (lyxrc.spellcheck_continuously && pi_.do_spellcheck && pi_.pain.isDrawingEnabled()) paintMisspelledMark(orig_x, e); break; case Row::INSET: { diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 8d0b026998..7cf841f873 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -171,28 +171,44 @@ int GuiFontMetrics::signedWidth(docstring const & s) const } namespace { -void setTextLayout(QTextLayout & tl, docstring const & s, QFont font, - bool const rtl, double const wordspacing) + +QTextLayout const & getTextLayout(docstring const & s, QFont font, + bool const rtl, double const wordspacing) { - tl.setText(toqstr(s)); - font.setWordSpacing(wordspacing); - tl.setFont(font); - // Note that both setFlags and the enums are undocumented - tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight); - tl.beginLayout(); - tl.createLine(); - tl.endLayout(); + static docstring old_s; + static QFont old_font; + static bool old_rtl = false; + // this invalid value is to make sure that it is reset on first try. + static double old_wordspacing = -1.0; + // This one is our trivial cache + static QTextLayout tl; + if (s != old_s || font != old_font || rtl != old_rtl + || wordspacing != old_wordspacing) { + tl.setText(toqstr(s)); + font.setWordSpacing(wordspacing); + tl.setFont(font); + // Note that both setFlags and the enums are undocumented + tl.setFlags(rtl ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight); + tl.beginLayout(); + tl.createLine(); + tl.endLayout(); + old_s = s; + old_font = font; + old_rtl = rtl; + old_wordspacing = wordspacing; + } + return tl; } + } int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl, double const wordspacing) const { - QTextLayout tl; QFont copy = font_; copy.setWordSpacing(wordspacing); - setTextLayout(tl, s, font_, rtl, wordspacing); + QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing); return static_cast(tl.lineForTextPosition(pos).cursorToX(pos)); } @@ -200,8 +216,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl, int GuiFontMetrics::x2pos(docstring const & s, int & x, bool const rtl, double const wordspacing) const { - QTextLayout tl; - setTextLayout(tl, s, font_, rtl, wordspacing); + QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing); int pos = tl.lineForTextPosition(0).xToCursor(x); // correct x value to the actual cursor position. x = static_cast(tl.lineForTextPosition(0).cursorToX(pos));