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);
// 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: {

View File

@ -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<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,
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<int>(tl.lineForTextPosition(0).cursorToX(pos));