Make the non-drawing cases faster in TextMetrics::drawParagraph

There are two main cases:
* when drawing is disabled from the start, use a simplified code that only paints insets (in order to cache positions).
* when the row is not visible, do the same.

The goal of this optimization is to be able to always run a no-drawing draw after the metrics have been computed.
This commit is contained in:
Jean-Marc Lasgouttes 2016-02-29 16:07:35 +01:00
parent 96fee0ed7a
commit fc73ebc16c

View File

@ -1864,15 +1864,31 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) const
void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const x, int y) const void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const x, int y) const
{ {
BufferParams const & bparams = bv_->buffer().params();
ParagraphMetrics const & pm = par_metrics_[pit]; ParagraphMetrics const & pm = par_metrics_[pit];
if (pm.rows().empty()) if (pm.rows().empty())
return; return;
bool const original_drawing_state = pi.pain.isDrawingEnabled();
int const ww = bv_->workHeight();
size_t const nrows = pm.rows().size(); size_t const nrows = pm.rows().size();
// Use fast lane when drawing is disabled.
if (!pi.pain.isDrawingEnabled()) {
for (size_t i = 0; i != nrows; ++i) {
Row const & row = pm.rows()[i];
// Adapt to cursor row scroll offset if applicable.
int row_x = x - bv_->horizScrollOffset(text_, pit, row.pos());
if (i)
y += row.ascent();
RowPainter rp(pi, *text_, pit, row, row_x, y);
rp.paintOnlyInsets();
y += row.descent();
}
return;
}
BufferParams const & bparams = bv_->buffer().params();
int const ww = bv_->workHeight();
Cursor const & cur = bv_->cursor(); Cursor const & cur = bv_->cursor();
DocIterator sel_beg = cur.selectionBegin(); DocIterator sel_beg = cur.selectionBegin();
DocIterator sel_end = cur.selectionEnd(); DocIterator sel_end = cur.selectionEnd();
@ -1909,10 +1925,18 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
RowPainter rp(pi, *text_, pit, row, row_x, y); RowPainter rp(pi, *text_, pit, row, row_x, y);
// It is not needed to draw on screen if we are not inside.
bool const inside = (y + row.descent() >= 0 bool const inside = (y + row.descent() >= 0
&& y - row.ascent() < ww); && y - row.ascent() < ww);
// It is not needed to draw on screen if we are not inside. pi.pain.setDrawingEnabled(inside);
pi.pain.setDrawingEnabled(inside && original_drawing_state); if (!inside) {
// Paint only the insets to set inset cache correctly
// FIXME: remove paintOnlyInsets when we know that positions
// have already been set.
rp.paintOnlyInsets();
y += row.descent();
continue;
}
if (selection) if (selection)
row.setSelectionAndMargins(sel_beg_par, sel_end_par); row.setSelectionAndMargins(sel_beg_par, sel_end_par);
@ -1929,8 +1953,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
} }
// Row signature; has row changed since last paint? // Row signature; has row changed since last paint?
if (pi.pain.isDrawingEnabled()) row.setCrc(pm.computeRowSignature(row, bparams));
row.setCrc(pm.computeRowSignature(row, bparams));
bool row_has_changed = row.changed() bool row_has_changed = row.changed()
|| bv_->hadHorizScrollOffset(text_, pit, row.pos()); || bv_->hadHorizScrollOffset(text_, pit, row.pos());
@ -1961,7 +1984,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
// Instrumentation for testing row cache (see also // Instrumentation for testing row cache (see also
// 12 lines lower): // 12 lines lower):
if (lyxerr.debugging(Debug::PAINTING) && inside if (lyxerr.debugging(Debug::PAINTING)
&& (row.selection() || pi.full_repaint || row_has_changed)) { && (row.selection() || pi.full_repaint || row_has_changed)) {
string const foreword = text_->isMainText() ? string const foreword = text_->isMainText() ?
"main text redraw " : "inset text redraw: "; "main text redraw " : "inset text redraw: ";
@ -1999,7 +2022,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
pi.full_repaint = tmp; pi.full_repaint = tmp;
} }
// Re-enable screen drawing for future use of the painter. // Re-enable screen drawing for future use of the painter.
pi.pain.setDrawingEnabled(original_drawing_state); pi.pain.setDrawingEnabled(true);
//LYXERR(Debug::PAINTING, "."); //LYXERR(Debug::PAINTING, ".");
} }