Line clipping

10 views
Skip to first unread message

Neil Hodgson

unread,
Sep 18, 2022, 8:03:39 PM9/18/22
to Scintilla mailing list
Scintilla originally drew each line independently without any overlap between lines for extra high and low character ascenders and descenders or indicators. This was relaxed in 2014 with multiple phase drawing (SC_PHASES_MULTIPLE) which allowed some pixels to overlap (10% of lineHeight with a minimum of 2 pixels).

This overlap has become more important with some indicators, particularly the top and bottom point indicators being used for change history. Allowing these indicators to draw one pixel into the previous or next line allows them to be much more prominent while avoiding obscuring the text too much.

However, they also draw intermittently into other lines in the common 2 phase drawing (SC_PHASES_TWO) mode. What happens is that lines are drawn from top to bottom and lines are able to draw over the previous line. The benefit here was that high ascenders like the ring on Å may be visible in some cases. They (and some of top point indicators) may then disappear if the previous line is redrawn in isolation.

This inconsistent drawing of overlapping elements is a problem that should be fixed: applications that want overlapping should choose SC_PHASES_MULTIPLE to achieve correct overlap but applications that want to use SC_PHASES_TWO (likely for performance reasons) should see a consistent display.

Consistent display can be achieved by clipping drawing of each line to that line's area for SC_PHASES_TWO and the archaic SC_PHASES_ONE.

This patch achieves that clipping.

diff -r da25fe4abc02 src/EditView.cxx
--- a/src/EditView.cxx Sat Sep 17 21:59:27 2022 +1000
+++ b/src/EditView.cxx Mon Sep 19 09:36:45 2022 +1000
@@ -2354,6 +2355,11 @@
return; // No further drawing
}

+ const bool clipLine = !bufferedDraw && !LinesOverlap();
+ if (clipLine) {
+ surface->SetClip(rcLine);
+ }
+
// See if something overrides the line background colour.
const std::optional<ColourRGBA> background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);

@@ -2429,6 +2435,10 @@
if (FlagSet(phase, DrawPhase::lineTranslucent)) {
DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine, subLine, Layer::OverText);
}
+
+ if (clipLine) {
+ surface->PopClip();
+ }
}

static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,

Neil

Neil Hodgson

unread,
Sep 24, 2022, 10:19:14 PM9/24/22
to Scintilla mailing list
Me:

> Consistent display can be achieved by clipping drawing of each line to that line's area for SC_PHASES_TWO and the archaic SC_PHASES_ONE.

Committed with
https://sourceforge.net/p/scintilla/code/ci/d9bdcc6d6abbe68dc7b53c561f07c94acbcd156c/
Neil

Reply all
Reply to author
Forward
0 new messages