]> git.lyx.org Git - lyx.git/blobdiff - src/rowpainter.C
Add GTK bibitem dialog
[lyx.git] / src / rowpainter.C
index 907a3c220e7c5b2cd9d7a4490380e74ad8069059..b992b00143a71425bccc3eff85218e728ef80add 100644 (file)
@@ -40,6 +40,8 @@
 
 #include "support/textutils.h"
 
+#include <boost/crc.hpp>
+
 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<BufferView *>(&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_);
@@ -537,8 +543,9 @@ void RowPainter::paintFirst()
 
                        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() -
@@ -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<BufferView *>(&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();
        }
 }