mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-11 13:46:43 +00:00
three-stage drawing: add a nodraw stage
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.
This commit is contained in:
parent
48f099d93a
commit
efc7359015
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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, ".");
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ liblyxfrontends_a_SOURCES = \
|
||||
Delegates.h \
|
||||
KeyModifier.h \
|
||||
KeySymbol.h \
|
||||
NullPainter.h \
|
||||
Painter.h \
|
||||
Clipboard.h \
|
||||
Selection.h \
|
||||
|
109
src/frontends/NullPainter.h
Normal file
109
src/frontends/NullPainter.h
Normal file
@ -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
|
@ -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_; }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user