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.
This commit is contained in:
Jean-Marc Lasgouttes 2015-12-07 10:32:34 +01:00
parent d42bd06594
commit f3cdf74e68
2 changed files with 30 additions and 15 deletions

View File

@ -609,7 +609,7 @@ void RowPainter::paintText()
paintStringAndSel(e); paintStringAndSel(e);
// Paint the spelling marks if enabled. // 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); paintMisspelledMark(orig_x, e);
break; break;
case Row::INSET: { case Row::INSET: {

View File

@ -171,9 +171,19 @@ int GuiFontMetrics::signedWidth(docstring const & s) const
} }
namespace { namespace {
void setTextLayout(QTextLayout & tl, docstring const & s, QFont font,
QTextLayout const & getTextLayout(docstring const & s, QFont font,
bool const rtl, double const wordspacing) bool const rtl, double const wordspacing)
{ {
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)); tl.setText(toqstr(s));
font.setWordSpacing(wordspacing); font.setWordSpacing(wordspacing);
tl.setFont(font); tl.setFont(font);
@ -182,17 +192,23 @@ void setTextLayout(QTextLayout & tl, docstring const & s, QFont font,
tl.beginLayout(); tl.beginLayout();
tl.createLine(); tl.createLine();
tl.endLayout(); 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, int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl,
double const wordspacing) const double const wordspacing) const
{ {
QTextLayout tl;
QFont copy = font_; QFont copy = font_;
copy.setWordSpacing(wordspacing); copy.setWordSpacing(wordspacing);
setTextLayout(tl, s, font_, rtl, wordspacing); QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing);
return static_cast<int>(tl.lineForTextPosition(pos).cursorToX(pos)); return static_cast<int>(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, int GuiFontMetrics::x2pos(docstring const & s, int & x, bool const rtl,
double const wordspacing) const double const wordspacing) const
{ {
QTextLayout tl; QTextLayout const & tl = getTextLayout(s, font_, rtl, wordspacing);
setTextLayout(tl, s, font_, rtl, wordspacing);
int pos = tl.lineForTextPosition(0).xToCursor(x); int pos = tl.lineForTextPosition(0).xToCursor(x);
// correct x value to the actual cursor position. // correct x value to the actual cursor position.
x = static_cast<int>(tl.lineForTextPosition(0).cursorToX(pos)); x = static_cast<int>(tl.lineForTextPosition(0).cursorToX(pos));