X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Frowpainter.C;h=b992b00143a71425bccc3eff85218e728ef80add;hb=9ee46b846e5e84ad40ceda4f4af94aeb86cd90a2;hp=8543e147debb00e34680de51d50d402027b5e7f7;hpb=6f8059d09f4cfa0b0a5b2d713176affad0829b48;p=lyx.git diff --git a/src/rowpainter.C b/src/rowpainter.C index 8543e147de..b992b00143 100644 --- a/src/rowpainter.C +++ b/src/rowpainter.C @@ -40,6 +40,8 @@ #include "support/textutils.h" +#include + using lyx::pos_type; using lyx::pit_type; @@ -154,7 +156,11 @@ void RowPainter::paintInset(pos_type const pos, LyXFont const & font) InsetBase const * inset = par_.getInset(pos); BOOST_ASSERT(inset); PainterInfo pi(const_cast(&bv_), pain_); - pi.base.font = font; + // FIXME: We should always use font, see documentation of + // noFontChange() in insetbase.h. + pi.base.font = inset->noFontChange() ? + bv_.buffer()->params().getLyXTextClass().defaultfont() : + font; pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0); pi.erased_ = erased_ || isDeletedText(par_, pos); theCoords.insets().add(inset, int(x_), yo_); @@ -712,8 +718,32 @@ void RowPainter::paintText() } +lyx::size_type calculateRowSignature(Row const & row, Paragraph const & par) +{ + boost::crc_32_type crc; + for (lyx::pos_type i = row.pos(); i < row.endpos(); ++i) { + const unsigned char b[] = { par.getChar(i) }; + crc.process_bytes(b, 1); + } + return crc.checksum(); +} + + +bool isCursorOnRow(PainterInfo & pi, pit_type pit, RowList::const_iterator rit) +{ + LCursor & cur = pi.base.bv->cursor(); + for (lyx::size_type d = 0; d < cur.depth(); d++) + if (cur[d].pit() == pit + && cur[d].pos() >= rit->pos() + && cur[d].pos() <= rit->endpos()) + return true; + return false; +} + + void paintPar - (PainterInfo & pi, LyXText const & text, pit_type pit, int x, int y) + (PainterInfo & pi, LyXText const & text, pit_type pit, int x, int y, + bool repaintAll) { // lyxerr << " paintPar: pit: " << pit << " at y: " << y << endl; static NullPainter nop; @@ -727,22 +757,49 @@ void paintPar theCoords.parPos()[&text][pit] = Point(x, y); y -= rb->ascent(); - for (RowList::const_iterator rit = rb; rit != re; ++rit) { + lyx::size_type rowno(0); + for (RowList::const_iterator rit = rb; rit != re; ++rit, ++rowno) { y += rit->ascent(); - bool const inside = (y + rit->descent() >= 0 - && y - rit->ascent() < ww); - RowPainter rp(inside ? pi : nullpi, text, pit, *rit, x, y); + // Row signature; has row changed since last paint? + lyx::size_type const row_sig = calculateRowSignature(*rit, par); + + bool cursor_on_row = isCursorOnRow(pi, pit, rit); + + // If selection is on, the current row signature differs from + // from cache, or cursor is inside an inset _on this row_, + // then paint the row + if (repaintAll || par.rowSignature()[rowno] != row_sig + || cursor_on_row) { + // Add to row signature cache + par.rowSignature()[rowno] = row_sig; + + bool const inside = (y + rit->descent() >= 0 + && y - rit->ascent() < ww); + RowPainter rp(inside ? pi : nullpi, text, pit, *rit, x, y); + // Clear background of this row + // (if paragraph background was not cleared) + if (!repaintAll) { + pi.pain.fillRectangle(x, y - rit->ascent(), + pi.base.bv->workWidth(), rit->height(), + text.backgroundColor()); + } + + // Instrumentation for testing row cache (see also + // 12 lines lower): + //lyxerr << "#"; + rp.paintAppendix(); + rp.paintDepthBar(); + rp.paintChangeBar(); + if (rit == rb) + rp.paintFirst(); + if (rit + 1 == re) + rp.paintLast(); + rp.paintText(); + } y += rit->descent(); - rp.paintAppendix(); - rp.paintDepthBar(); - rp.paintChangeBar(); - if (rit == rb) - rp.paintFirst(); - if (rit + 1 == re) - rp.paintLast(); - rp.paintText(); } + //lyxerr << "." << endl; } } // namespace anon @@ -752,22 +809,25 @@ void paintText(BufferView const & bv, ViewMetricsInfo const & vi) { Painter & pain = bv.painter(); LyXText * const text = bv.text(); + bool const select = bv.cursor().selection(); - // clear background - pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, - LColor::background); - - // draw selection PainterInfo pi(const_cast(&bv), pain); - - text->drawSelection(pi, 0, 0); + if (select || !vi.singlepar) { + // Clear background (Delegated to rows if no selection) + pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, + text->backgroundColor()); + } + if (select) { + text->drawSelection(pi, 0, 0); + } int yy = vi.y1; // draw contents for (pit_type pit = vi.p1; pit <= vi.p2; ++pit) { - yy += text->getPar(pit).ascent(); - paintPar(pi, *bv.text(), pit, 0, yy); - yy += text->getPar(pit).descent(); + Paragraph const & par = text->getPar(pit); + yy += par.ascent(); + paintPar(pi, *bv.text(), pit, 0, yy, select || !vi.singlepar); + yy += par.descent(); } // Cache one paragraph above and one below @@ -805,7 +865,7 @@ void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y) y -= text.getPar(0).ascent(); for (int pit = 0; pit < int(text.paragraphs().size()); ++pit) { y += text.getPar(pit).ascent(); - paintPar(pi, text, pit, x, y); + paintPar(pi, text, pit, x, y, true); y += text.getPar(pit).descent(); } }