X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Frowpainter.C;h=b992b00143a71425bccc3eff85218e728ef80add;hb=9ee46b846e5e84ad40ceda4f4af94aeb86cd90a2;hp=d59934d19ef650393a0c1f61a77c61ff05dadfcd;hpb=52a2eb2c52bd990b44c35927338341fb6aefa4b0;p=lyx.git diff --git a/src/rowpainter.C b/src/rowpainter.C index d59934d19e..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_); @@ -489,9 +495,7 @@ void RowPainter::paintFirst() } else { spacing_val = buffer.params().spacing().getValue(); } -#ifdef WITH_WARNINGS -#warning Look is this correct? -#endif + int const labeladdon = int(font_metrics::maxHeight(font) * layout->spacing.getValue() * spacing_val); int const maxdesc = int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val) @@ -531,20 +535,23 @@ void RowPainter::paintFirst() else spacing_val = buffer.params().spacing().getValue(); + int const labeladdon = int(font_metrics::maxHeight(font) * layout->spacing.getValue() * spacing_val); + int maxdesc = int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val + (layout->labelbottomsep * defaultRowHeight())); double x = x_; if (layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) { - x = ((is_rtl ? leftMargin() : x_) - + width_ - text_.rightMargin(par_)) / 2; + if (is_rtl) + x = leftMargin(); + x += (width_ - text_.rightMargin(par_) - leftMargin()) / 2; x -= font_metrics::width(str, font) / 2; } else if (is_rtl) { x = width_ - leftMargin() - font_metrics::width(str, font); } - pain_.text(int(x), yo_ - maxdesc, str, font); + pain_.text(int(x), yo_ - maxdesc - labeladdon, str, font); } } } @@ -627,7 +634,7 @@ void RowPainter::paintText() } const int width_pos = - text_.singleWidth(par_, vpos, par_.getChar(vpos), font); + text_.singleWidth(par_, pos, par_.getChar(pos), font); if (x_ + width_pos < 0) { x_ += width_pos; @@ -711,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; @@ -726,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 @@ -751,48 +809,51 @@ 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(); } - - // paint one paragraph above and one below + // Cache one paragraph above and one below // Note MV: this cannot be suppressed even for singlepar. // Try viewing the User Guide Mobius figure + if (vi.p1 > 0) { text->redoParagraph(vi.p1 - 1); - paintPar(pi, *bv.text(), vi.p1 - 1, 0, - vi.y1 - text->getPar(vi.p1 - 1).descent()); + theCoords.parPos()[bv.text()][vi.p1 - 1] = + Point(0, vi.y1 - text->getPar(vi.p1 - 1).descent()); } if (vi.p2 < lyx::pit_type(text->paragraphs().size()) - 1) { text->redoParagraph(vi.p2 + 1); - paintPar(pi, *bv.text(), vi.p2 + 1, 0, - vi.y2 + text->getPar(vi.p2 + 1).ascent()); + theCoords.parPos()[bv.text()][vi.p2 + 1] = + Point(0, vi.y2 + text->getPar(vi.p2 + 1).ascent()); } // and grey out above (should not happen later) // lyxerr << "par ascent: " << text->getPar(vi.p1).ascent() << endl; - if (vi.y1 > 0) + if (vi.y1 > 0 && !vi.singlepar) pain.fillRectangle(0, 0, bv.workWidth(), vi.y1, LColor::bottomarea); // and possibly grey out below // lyxerr << "par descent: " << text->getPar(vi.p1).ascent() << endl; - if (vi.y2 < bv.workHeight()) + if (vi.y2 < bv.workHeight() && !vi.singlepar) pain.fillRectangle(0, vi.y2, bv.workWidth(), bv.workHeight() - vi.y2, LColor::bottomarea); } @@ -804,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(); } }