diff --git a/src/BufferView.cpp b/src/BufferView.cpp index d2215627cf..00de06080a 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -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: diff --git a/src/BufferView.h b/src/BufferView.h index 92e8987350..83b4d39e37 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -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); diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp index 2d7e12c445..2dc76664a9 100644 --- a/src/RowPainter.cpp +++ b/src/RowPainter.cpp @@ -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; diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index f94accae67..c5784070d2 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -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, "."); } diff --git a/src/frontends/Makefile.am b/src/frontends/Makefile.am index 862613a67f..22b7508a7a 100644 --- a/src/frontends/Makefile.am +++ b/src/frontends/Makefile.am @@ -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 index 0000000000..19ac8b66a2 --- /dev/null +++ b/src/frontends/NullPainter.h @@ -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 diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h index d03ebf40e8..79c907d23f 100644 --- a/src/frontends/Painter.h +++ b/src/frontends/Painter.h @@ -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_; } diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index a3cb089e78..56e9cc4aec 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -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 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 diff --git a/src/frontends/qt4/GuiPainter.h b/src/frontends/qt4/GuiPainter.h index 9657ed9770..7513965ea6 100644 --- a/src/frontends/qt4/GuiPainter.h +++ b/src/frontends/qt4/GuiPainter.h @@ -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, diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp index fe7082da64..1218061741 100644 --- a/src/frontends/qt4/GuiWorkArea.cpp +++ b/src/frontends/qt4/GuiWorkArea.cpp @@ -16,6 +16,11 @@ #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" @@ -26,11 +31,6 @@ #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); } diff --git a/src/mathed/InsetMathMacroTemplate.cpp b/src/mathed/InsetMathMacroTemplate.cpp index 17fc2d04a2..a2fc064c00 100644 --- a/src/mathed/InsetMathMacroTemplate.cpp +++ b/src/mathed/InsetMathMacroTemplate.cpp @@ -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); }