X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=development%2FPAINTING_ANALYSIS;h=a52a036aaa882ffa316da458fbd5ff44be8aa9a7;hb=e2f81b3a8486e70a89b7293701e1b6eced636256;hp=4934c5e1b6b10289c3511545fe3f58eaac3512f8;hpb=78eaf8333bacec8d735eae06c0745163d06a5122;p=lyx.git diff --git a/development/PAINTING_ANALYSIS b/development/PAINTING_ANALYSIS index 4934c5e1b6..a52a036aaa 100644 --- a/development/PAINTING_ANALYSIS +++ b/development/PAINTING_ANALYSIS @@ -20,15 +20,9 @@ following section. Some actions are proposed. ** SinglePar update -The flag Update::SinglePar is set in many places but never acted on. -Instead, metrics update is skipped whenever the recorded height of -current paragraph did not change and Update::Force was not specified. -Is it better to keep that (which incurs extra work) or to condition it -on Update::SinglePar? If the first solution is kept, the flag -SingleParUpdate shall be removed. - -Moreover, I fail to see (yet) where the 'single' part of the program -is acted on. +This flag only has an effect in the current BufferView, but I think it +is useful in other views too. Doing this will require some work on the +update pipeline, though. ** Buffer::change issues @@ -40,6 +34,7 @@ a good value? NoScreenUpdate? On a related note, what is the semantics of a call to Buffer::changed(false)? What does the caller mean? + ** How to avoid redraw with FitCursor when the cursor is already OK? In this case, we invoke Buffer::change(false) with drawing disabled @@ -58,78 +53,39 @@ The global idea would be to extend FitCursor to cover also horizontal cursor. -* Proposals - * Clean-up of drawing code -The goal is to make painting with drawing disable fast enough that it -can be used after every metrics computation. Then we can separate real -drawing from metrics. - -** DONE RowPainter - -Inset position is set in paintInset, paintOnlyInsets, and paintText. -This should be done only once in paintInset - -** DONE TextMetrics::drawParagraph - -We can really simplify the code when drawing is disabled only -paintInset needs to be called. - + do right at the start when drawing is already disabled - + do it in the loop for rows that are not visible on screen. - -The only thing we want to do here is to set inset positions (for -text). The other insets still use the painter with drawing disabled. - -** Painter::text +** Set Row::changed() in a finer way -We cannot remove (or make private) the version that uses a -FontInfo because it is used by PainterInfo::draw. Document this and -remove unused arguments rtl and double spacing. This would become a specialized helper. -Proposed solution: keep the existing function, but private and without -optional arguments. +*** singleParUpdate -Avoid to return (and thus compute) the width of strings? - + used by InsetSpecialChar (fixable) - + used by textDecoration() in text(): more difficult to fix +When the height of the current paragraph changes, there is no need for +a full screen update. Only the rows after the current one need to have +their position recomputed. -Idea: add a version of text where wordspacing and textwidth (giving -the width of strings) are required parameters and remove optional -version. +This is also true when scrolling (how to do that?) -==> more versions, no optional parameters. +*** redoParagraph -** Set inset position during metrics phase +It should be possible to check whether the new row is the same as the +old one and keep its changed() status in this case. This would reduce +a lot the amount of stuff to redraw. -In order to do that, a no-paint drawing will be initiated after every -redoParagraph. This code path will need to be made as fast as possible. +** Put labels and friends in the Row as elements -Effect: avoid depending on actual drawing having taken place. In turn, -it will allow to do drawing on paint events, like any reasonable -application would do. +It should not be necessary to access the Paragraph object to draw. +Adding the static elements to Row is a lot of work, but worth it IMO. -** Cleanup after complete metrics - Then the following can be done: - + remove hack in InsetMathNest::drawSelection - + remove painting when not inside in drawParagraph - + remove Cursor::inCoordCache? +** Create a unique row by paragraph and break it afterwards -** Use Row for MathData +This should be a performance gain (only if paragraph breaking still +shows as expensive after the rest is done) -It may not be so difficult. Implement x2pos and pos2x from -the TM:cursorX and TM::getPosNearX, and use them for both text and -math. +** do not add the vertical margin of main text to first/last row -Will the strings display OK if drawing string-wise? - -Then it would be possible to streamline drawing with disabled painter. - -** Paint directly to screen - -Instead of using an intermediary pixmap. I have no idea of how -difficult it will prove. -One benefit will be that subpixel aliasing will work again (#9972) +Would make code cleaner. Probably no so difficult. +** When a paragraph ends with a newline, compute correctly the height of the extra row. ** Merging bv::updateMetrics and tm::metrics While the full metrics computation tries hard to limit the number of @@ -139,25 +95,25 @@ insets. We should re-use the bv::updateMetrics logic: + transfer all the logic of bv::updateMetrics to tm. + Main InsetText should not be special. -The difficuly for a tall table cell for example, is that it may be +The difficulty for a tall table cell for example, is that it may be necessary to break the whole contents to know the width of the cell. * Description of current drawing mechanism -** Two stage drawing +** Three-stage drawing -There are two parts to drawing the work area: +There are three parts to drawing the work area: + the metrics phase computes the size of insets and breaks the paragraphs into rows. It stores the dimension of insets (both normal and math) in bv::coordCache. - + the drawing phase draws the contents and caches the inset - positions. Since the caching of positions is useful in itself, - there is a provision for drawing "without" drawing when the only - thing we want is to cache inset positions - (Painter::setDrawingEnabled). + + the nodraw drawing phase paints the screen (see below) with a null + painter. The only useful effect is to store the inset positions. + + + an update() signal is sent. This in turn will trigger a paint + event, and the actual screen painting will happen then. The machinery is controlled via bv::processUpdateFlags. This method is called at the end of bv::mouseEventDispatch and in @@ -172,33 +128,40 @@ DecorationUpdate). It triggers a recomputation of the metrics when either: + Update::Force has been specified + Update::FitCursor has been specified and there is a need to scroll the display. - + the current paragraph, after rebreak, does not have the same height as in - existing metrics. Note that the Update::SinglePar flag is *never* - taken into account. + + Update::SinglePar has been specified and the current paragraph has + not changed height. + +If a computation of metrics has taken place, Force is removed from the +flags and ForceDraw is added instead. + +It is OK to call processUpateFlags several times before an update. In +this case, the effects are cumulative. processUpdateFlags executes the +metrics-related actions, but defers the actual drawing to the next +paint event. The screen is drawn (with appropriate update strategy), except when update flag is Update::None. -** Metrics computation +** Metrics computation (and nodraw drawing phase) This is triggered by bv::updateMetrics, which calls tm::redoParagraph for - + all visible paragraphs - + paragraph above the screen (up to one page) - + paragraphs below the screen (up to one page again) - -The paragraphs outside of the screen are required to make PageUp/Down -work. +all visible paragraphs. Some Paragraphs above or below the screen (needed +for page up/down) and computed as needed. tm::redoParagraph will call Inset::metrics for each inset. In the case of text insets, this will invoke recursively tm::metrics, which redoes all the paragraphs of the inset. +At the end of the function, bv::updatePosCache is called. It triggers +a repaint of the document with a NullPainter (a painter that does +nothing). This has the effect of caching all insets positions. ** Drawing the work area. -This is done in bv::draw. This method is triggered mainly by -Buffer::changed, which draws all the work areas that show the given buffer. +This is done in bv::draw. This method is triggered by a paint event, +mainly called through Buffer::changed, which draws all the work areas +that show the given buffer. Note that, When Buffer::changed is called outside of bv::processUpdateFlags, it is not clear whether the update strategy @@ -228,3 +191,6 @@ The action depends on the update strategy: + SingleParUpdate: only tries to repaint current paragraph in a way that is not yet very clear to me. + +BufferView::draw can also be called with a null painter from +BufferView::updateMetrics().