]> git.lyx.org Git - features.git/commitdiff
three-stage drawing: add a nodraw stage
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Sat, 15 Jul 2017 23:25:03 +0000 (01:25 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Tue, 29 Aug 2017 14:37:07 +0000 (16:37 +0200)
Normally the two stages of drawing are
1/ compute metrics of insets/rows/paragraphs/mathrow...
2/ draw the elements and cache their positions

Now the three stages are
1/ metrics
2/ nodraw: do not draw the elements, but cache their position
3/ draw the elements (and store again their position; it does not
   seems to hurt performance).

Revive the NullPainter: this replaces the setDrawingEnabled mechanism
with a painter that does nothing. The advantage is that updatePosCache
(renamed from setPosCache) does not need anymore to be invoked from
the frontend.

updatePosCache (the nodraw stage) is called at the end of
BufferView::updateMetrics.

src/BufferView.cpp
src/BufferView.h
src/RowPainter.cpp
src/TextMetrics.cpp
src/frontends/Makefile.am
src/frontends/NullPainter.h [new file with mode: 0644]
src/frontends/Painter.h
src/frontends/qt4/GuiPainter.cpp
src/frontends/qt4/GuiPainter.h
src/frontends/qt4/GuiWorkArea.cpp
src/mathed/InsetMathMacroTemplate.cpp

index d2215627cfbdb2ef7be4b54793ce4dc5ed78dd99..00de06080ad75e4a4e76d83b5b1fa95558627b54 100644 (file)
@@ -70,6 +70,7 @@
 #include "frontends/Application.h"
 #include "frontends/Delegates.h"
 #include "frontends/FontMetrics.h"
+#include "frontends/NullPainter.h"
 #include "frontends/Painter.h"
 #include "frontends/Selection.h"
 
@@ -2745,6 +2746,9 @@ void BufferView::updateMetrics()
 
        d->update_strategy_ = FullScreenUpdate;
 
+       // Now update the positions of insets in the cache.
+       updatePosCache();
+
        if (lyxerr.debugging(Debug::WORKAREA)) {
                LYXERR(Debug::WORKAREA, "BufferView::updateMetrics");
                d->coord_cache_.dump();
@@ -2752,6 +2756,15 @@ void BufferView::updateMetrics()
 }
 
 
+void BufferView::updatePosCache()
+{
+       // this is the "nodraw" drawing stage: only set the positions of the
+       // insets in metrics cache.
+       frontend::NullPainter np;
+       draw(np);
+}
+
+
 void BufferView::insertLyXFile(FileName const & fname)
 {
        LASSERT(d->cursor_.inTexted(), return);
@@ -2997,12 +3010,11 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi)
                 * at this point.
                 */
                // Force the recomputation of inset positions
-               bool const drawing = pi.pain.isDrawingEnabled();
-               pi.pain.setDrawingEnabled(false);
+               frontend::NullPainter np;
+               PainterInfo(this, np);
                // No need to care about vertical position.
                RowPainter rp(pi, buffer().text(), row, -d->horiz_scroll_offset_, 0);
                rp.paintText();
-               pi.pain.setDrawingEnabled(drawing);
        }
 
        // Current x position of the cursor in pixels
@@ -3066,12 +3078,13 @@ void BufferView::draw(frontend::Painter & pain)
        switch (d->update_strategy_) {
 
        case NoScreenUpdate:
-               // If no screen painting is actually needed, only some the different
-               // coordinates of insets and paragraphs needs to be updated.
+               // no screen painting is actually needed. In nodraw stage
+               // however, the different coordinates of insets and paragraphs
+               // needs to be updated.
                LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate");
                pi.full_repaint = true;
-               pi.pain.setDrawingEnabled(false);
-               tm.draw(pi, 0, y);
+               if (pain.isNull())
+                       tm.draw(pi, 0, y);
                break;
 
        case SingleParUpdate:
index 92e898735065ac2f8146fbb7b14fd8a3f43fac80..83b4d39e3771aa0ab41142df4c7ca0f325182616 100644 (file)
@@ -283,6 +283,10 @@ public:
        /// update the internal \c ViewMetricsInfo.
        void updateMetrics();
 
+       // this is the "nodraw" drawing stage: only set the positions of the
+       // insets in metrics cache.
+       void updatePosCache();
+
        ///
        TextMetrics const & textMetrics(Text const * t) const;
        TextMetrics & textMetrics(Text const * t);
@@ -303,7 +307,6 @@ public:
        /// get the position and height of the cursor
        void cursorPosAndHeight(Point & p, int & h) const;
 
-
        ///
        void draw(frontend::Painter & pain);
 
index 2d7e12c445e2bb8d22efe7af6f969459d1e93580..2dc76664a91f099ab075e656934f72cf47b4a916 100644 (file)
@@ -576,7 +576,7 @@ void RowPainter::paintText()
                        paintStringAndSel(e);
 
                        // Paint the spelling marks if enabled.
-                       if (lyxrc.spellcheck_continuously && pi_.do_spellcheck && pi_.pain.isDrawingEnabled())
+                       if (lyxrc.spellcheck_continuously && pi_.do_spellcheck && !pi_.pain.isNull())
                                paintMisspelledMark(e);
                        break;
 
index f94accae67176f898c3fcce7f63ab485638f5909..c5784070d26cc8692735b45318802cb7fef60cd8 100644 (file)
@@ -1802,8 +1802,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                return;
        size_t const nrows = pm.rows().size();
 
-       // Use fast lane when drawing is disabled.
-       if (!pi.pain.isDrawingEnabled()) {
+       // Use fast lane in nodraw stage.
+       if (pi.pain.isNull()) {
                for (size_t i = 0; i != nrows; ++i) {
 
                        Row const & row = pm.rows()[i];
@@ -1855,17 +1855,11 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                if (i)
                        y += row.ascent();
 
-               RowPainter rp(pi, *text_, row, row_x, y);
-
                // It is not needed to draw on screen if we are not inside.
                bool const inside = (y + row.descent() >= 0
                        && y - row.ascent() < ww);
-               pi.pain.setDrawingEnabled(inside);
                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();
+                       // Inset positions have already been set in nodraw stage.
                        y += row.descent();
                        continue;
                }
@@ -1894,6 +1888,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                        text_->getPar(pit).spellCheck();
                }
 
+               RowPainter rp(pi, *text_, row, row_x, y);
+
                // Don't paint the row if a full repaint has not been requested
                // and if it has not changed.
                if (!pi.full_repaint && !row_has_changed) {
@@ -1924,7 +1920,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                                << " row_selection="    << row.selection()
                                << " full_repaint="     << pi.full_repaint
                                << " row_has_changed="  << row_has_changed
-                               << " drawingEnabled=" << pi.pain.isDrawingEnabled());
+                               << " null painter=" << pi.pain.isNull());
                }
 
                // Backup full_repaint status and force full repaint
@@ -1952,8 +1948,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                // Restore full_repaint status.
                pi.full_repaint = tmp;
        }
-       // Re-enable screen drawing for future use of the painter.
-       pi.pain.setDrawingEnabled(true);
 
        //LYXERR(Debug::PAINTING, ".");
 }
index 862613a67f51964dded997125b30f6fcd9cac155..22b7508a7ac5587cb40e426c0127fb02cbed84d3 100644 (file)
@@ -17,6 +17,7 @@ liblyxfrontends_a_SOURCES = \
        Delegates.h \
        KeyModifier.h \
        KeySymbol.h \
+       NullPainter.h \
        Painter.h \
        Clipboard.h \
        Selection.h \
diff --git a/src/frontends/NullPainter.h b/src/frontends/NullPainter.h
new file mode 100644 (file)
index 0000000..19ac8b6
--- /dev/null
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+/**
+ * \file NullPainter.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author unknown
+ * \author John Levon
+ * \author Jean-Marc Lasgouttes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef NULLPAINTER_H
+#define NULLPAINTER_H
+
+#include "Painter.h"
+
+namespace lyx {
+
+namespace frontend {
+
+/**
+ * NullPainter - A painter instance that does nothing
+ */
+class NullPainter : public Painter {
+public:
+       NullPainter() : Painter(1) {}
+
+       ~NullPainter() {}
+
+       /// draw a line from point to point
+       void line(int, int, int, int, Color,
+               line_style = line_solid, int = thin_line) {}
+
+       ///
+       void lines(int const *, int const *, int, Color,
+               fill_style = fill_none, line_style = line_solid,
+               int = thin_line) {}
+
+       ///
+       void path(int const *, int const *, int const *, int const *,
+               int const *, int const *, int, Color,
+               fill_style = fill_none, line_style = line_solid, int = thin_line) {}
+
+       /// draw a rectangle
+       void rectangle(int, int, int, int, Color,
+               line_style = line_solid, int = thin_line) {}
+
+       /// draw a filled rectangle
+       void fillRectangle(int, int, int, int, Color) {}
+
+       /// draw an arc
+       void arc(int, int, unsigned int, unsigned int, int, int, Color) {}
+
+       /// draw a pixel
+       void point(int, int, Color) {}
+
+       /// draw an image from the image cache
+       void image(int, int, int, int, graphics::Image const &) {}
+
+       /// draw a string
+       void text(int, int, docstring const &, FontInfo const &) {}
+
+       /// draw a char
+       void text(int, int, char_type, FontInfo const &) {}
+
+       /// draw a string
+       void text(int, int, docstring const &, Font const &, double, double) {}
+
+       ///
+       void text(int, int, docstring const &, Font const &,
+                 Color, size_type, size_type, double, double) {}
+
+       /// This painter does not paint
+       bool isNull() const { return true; }
+
+       /// draw the underbar, strikeout, xout, uuline and uwave font attributes
+       void textDecoration(FontInfo const &, int, int, int) {}
+
+       /**
+        * Draw a string and enclose it inside a rectangle. If
+        * back color is specified, the background is cleared with
+        * the given color. If frame is specified, a thin frame is drawn
+        * around the text with the given color.
+        */
+       void rectText(int, int, docstring const &,
+                     FontInfo const &, Color, Color) {}
+
+       /// draw a string and enclose it inside a button frame
+       void buttonText(int, int, docstring const &,
+                       FontInfo const &, Color, Color, int) {}
+
+       /// draw a character of a preedit string for cjk support.
+       int preeditText(int, int, char_type, FontInfo const &,
+                       preedit_style) { return 0; }
+
+       /// start monochrome painting mode, i.e. map every color into [min,max]
+       void enterMonochromeMode(Color const &, Color const &) {}
+       /// leave monochrome painting mode
+       void leaveMonochromeMode() {}
+       /// draws a wavy line that can be used for underlining.
+       void wavyHorizontalLine(int, int, int, ColorCode) {}
+};
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // NULLPAINTER_H
index d03ebf40e8415517b11b2383fb1f7ae16244e36e..79c907d23f6a97dfaecd631401e6cdc80bde7ec9 100644 (file)
@@ -147,11 +147,8 @@ public:
                          Color other, size_type from, size_type to,
                       double wordspacing, double textwidth) = 0;
 
-       void setDrawingEnabled(bool drawing_enabled)
-       { drawing_enabled_ = drawing_enabled; }
-
-       /// Indicate wether real screen drawing shall be done or not.
-       bool isDrawingEnabled() const { return drawing_enabled_; }
+       // Returns true if the painter does not actually paint.
+       virtual bool isNull() const = 0;
 
        double pixelRatio() const { return pixel_ratio_; }
 
index a3cb089e7877f80629dbe0ea2853cb2a18047dd6..56e9cc4aec11f0ea66462135683ecabe68df0b5a 100644 (file)
@@ -171,9 +171,6 @@ void GuiPainter::leaveMonochromeMode()
 
 void GuiPainter::point(int x, int y, Color col)
 {
-       if (!isDrawingEnabled())
-               return;
-
        setQPainterPen(computeColor(col));
        drawPoint(x, y);
 }
@@ -184,9 +181,6 @@ void GuiPainter::line(int x1, int y1, int x2, int y2,
        line_style ls,
        int lw)
 {
-       if (!isDrawingEnabled())
-               return;
-
        setQPainterPen(computeColor(col), ls, lw);
        bool const do_antialiasing = renderHints() & TextAntialiasing
                && x1 != x2 && y1 != y2 && ls != line_solid_aliased;
@@ -202,9 +196,6 @@ void GuiPainter::lines(int const * xp, int const * yp, int np,
        line_style ls,
        int lw)
 {
-       if (!isDrawingEnabled())
-               return;
-
        // double the size if needed
        // FIXME THREAD
        static QVector<QPoint> points(32);
@@ -247,9 +238,6 @@ void GuiPainter::path(int const * xp, int const * yp,
        line_style ls,
        int lw)
 {
-       if (!isDrawingEnabled())
-               return;
-
        QPainterPath bpath;
        // This is the starting point, so its control points are meaningless
        bpath.moveTo(xp[0], yp[0]);
@@ -278,9 +266,6 @@ void GuiPainter::rectangle(int x, int y, int w, int h,
        line_style ls,
        int lw)
 {
-       if (!isDrawingEnabled())
-               return;
-
        setQPainterPen(computeColor(col), ls, lw);
        drawRect(x, y, w, h);
 }
@@ -288,9 +273,6 @@ void GuiPainter::rectangle(int x, int y, int w, int h,
 
 void GuiPainter::fillRectangle(int x, int y, int w, int h, Color col)
 {
-       if (!isDrawingEnabled())
-               return;
-
        fillRect(x, y, w, h, guiApp->colorCache().get(col));
 }
 
@@ -298,9 +280,6 @@ void GuiPainter::fillRectangle(int x, int y, int w, int h, Color col)
 void GuiPainter::arc(int x, int y, unsigned int w, unsigned int h,
        int a1, int a2, Color col)
 {
-       if (!isDrawingEnabled())
-               return;
-
        // LyX usings 1/64ths degree, Qt usings 1/16th
        setQPainterPen(computeColor(col));
        bool const do_antialiasing = renderHints() & TextAntialiasing;
@@ -317,9 +296,6 @@ void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i)
 
        fillRectangle(x, y, w, h, Color_graphicsbg);
 
-       if (!isDrawingEnabled())
-               return;
-
        QImage const image = qlimage.image();
        QRectF const drect = QRectF(x, y, w, h);
        QRectF const srect = QRectF(0, 0, image.width(), image.height());
@@ -391,7 +367,7 @@ void GuiPainter::text(int x, int y, docstring const & s,
                       double const wordspacing, double const tw)
 {
        //LYXERR0("text: x=" << x << ", s=" << s);
-       if (s.empty() || !isDrawingEnabled())
+       if (s.empty())
                return;
 
        /* Caution: The following ucs4 to QString conversions work for symbol fonts
index 9657ed9770c401fe17063c8f62581b39567908dd..7513965ea6ec2df61cb7e49095e6440514980866 100644 (file)
@@ -37,6 +37,9 @@ public:
        GuiPainter(QPaintDevice *, double pixel_ratio);
        virtual ~GuiPainter();
 
+       /// This painter paints
+       virtual bool isNull() const { return false; }
+
        /// draw a line from point to point
        virtual void line(
                int x1, int y1,
index fe7082da64316249c1c4b2507bce4a1ef37e79b1..12180617413b739bca16f20cb4200860aeff9aeb 100644 (file)
 
 #include "ColorCache.h"
 #include "FontLoader.h"
+#include "GuiApplication.h"
+#include "GuiCompleter.h"
+#include "GuiKeySymbol.h"
+#include "GuiPainter.h"
+#include "GuiView.h"
 #include "Menus.h"
 
 #include "Buffer.h"
 #include "Cursor.h"
 #include "Font.h"
 #include "FuncRequest.h"
-#include "GuiApplication.h"
-#include "GuiCompleter.h"
-#include "GuiKeySymbol.h"
-#include "GuiPainter.h"
-#include "GuiView.h"
 #include "KeySymbol.h"
 #include "Language.h"
 #include "LyX.h"
@@ -1271,9 +1271,8 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
                return;
        }
 
-       GuiPainter pain(d->screen_, pixelRatio());
        d->buffer_view_->updateMetrics();
-       d->buffer_view_->draw(pain);
+       d->updateScreen();
        // FIXME: shall we use real_current_font here? (see #10478)
        FontInfo font = d->buffer_view_->cursor().getFont().fontInfo();
        FontMetrics const & fm = theFontMetrics(font);
@@ -1365,6 +1364,7 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
                        ps = Painter::preedit_cursor;
 
                // draw one character and update cur_x.
+               GuiPainter pain(d->screen_, pixelRatio());
                cur_x += pain.preeditText(cur_x, cur_y, typed_char, font, ps);
        }
 
index 17fc2d04a2148464193becee154fe3d36be3eab6..a2fc064c00581cf68fd61cd46fdffbb3d8b79542 100644 (file)
@@ -231,25 +231,17 @@ void InsetDisplayLabelBox::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        InsetLabelBox::metrics(mi, dim);
        if (!parent_.editing(mi.base.bv)
-           && parent_.cell(parent_.displayIdx()).empty()) {
-               dim.wid = 0;
-               dim.asc = 0;
-               dim.des = 0;
-       }
+           && parent_.cell(parent_.displayIdx()).empty())
+               dim.clear();
 }
 
 
 void InsetDisplayLabelBox::draw(PainterInfo & pi, int x, int y) const
 {
        if (parent_.editing(pi.base.bv)
-           || !parent_.cell(parent_.displayIdx()).empty()) {
-               InsetLabelBox::draw(pi, x, y);
-       } else {
-               bool enabled = pi.pain.isDrawingEnabled();
-               pi.pain.setDrawingEnabled(false);
-               InsetLabelBox::draw(pi, x, y);
-               pi.pain.setDrawingEnabled(enabled);
-       }
+           || !parent_.cell(parent_.displayIdx()).empty()
+               || pi.pain.isNull())
+           InsetLabelBox::draw(pi, x, y);
 }