fix glyph-overhang artifacts in partial row repaint
repaintColumns cleared and redrew only [start,end], but a neighbouring cell's glyph can overhang into that span. The clearRect erased the overhang and the neighbour was never redrawn, leaving black notches through the line 1-2 cells before the cursor that survived until a full rerender. Redraw text for a couple of extra cells on each side, clipped to the cleared span, so overhang from just-outside cells is restored without touching their own cell areas. Keeps the per-column repaint efficiency (vs the full-row repaint debug toggle, which fixed the bars but repainted every dirty cell). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,11 @@ final class TerminalPaneNode extends Region {
|
|||||||
private static final int DIRTY_PARTIAL = 1;
|
private static final int DIRTY_PARTIAL = 1;
|
||||||
private static final int DIRTY_FULL = 2;
|
private static final int DIRTY_FULL = 2;
|
||||||
|
|
||||||
|
// Glyphs (bold/italic/wide) can overhang into neighbouring cells. When repainting a
|
||||||
|
// column run we redraw this many extra cells of text on each side, clipped to the
|
||||||
|
// cleared span, so a neighbour's overhang is restored without disturbing its own cell.
|
||||||
|
private static final int GLYPH_OVERHANG_CELLS = 2;
|
||||||
|
|
||||||
// Debug toggle: when set, skip the per-column repaint and always repaint the whole row.
|
// Debug toggle: when set, skip the per-column repaint and always repaint the whole row.
|
||||||
// Used to bisect partial-repaint artifacts (stale black bars near the cursor).
|
// Used to bisect partial-repaint artifacts (stale black bars near the cursor).
|
||||||
private static final boolean FULL_ROW_REPAINT =
|
private static final boolean FULL_ROW_REPAINT =
|
||||||
@@ -851,7 +856,18 @@ final class TerminalPaneNode extends Region {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawRowBackgrounds(gc, row, localCellTop, cellWidth, lineHeight, startColumn, endColumn);
|
drawRowBackgrounds(gc, row, localCellTop, cellWidth, lineHeight, startColumn, endColumn);
|
||||||
drawRowText(gc, row, baseline, cellWidth, startColumn, endColumn);
|
|
||||||
|
// Repaint text for a few neighbouring cells too, clipped to the cleared span, so
|
||||||
|
// any glyph overhang from just-outside cells (erased by the clearRect above) is
|
||||||
|
// restored. The clip keeps us from touching those neighbours' own cell areas.
|
||||||
|
gc.save();
|
||||||
|
gc.beginPath();
|
||||||
|
gc.rect(x, 0.0, width, canvas.getHeight());
|
||||||
|
gc.clip();
|
||||||
|
int textStart = Math.max(0, startColumn - GLYPH_OVERHANG_CELLS);
|
||||||
|
int textEnd = Math.min(row.cells().size() - 1, endColumn + GLYPH_OVERHANG_CELLS);
|
||||||
|
drawRowText(gc, row, baseline, cellWidth, textStart, textEnd);
|
||||||
|
gc.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void paintSidePadding(GraphicsContext gc, RenderRow row, double paneWidth, double bandHeight) {
|
private void paintSidePadding(GraphicsContext gc, RenderRow row, double paneWidth, double bandHeight) {
|
||||||
|
|||||||
Reference in New Issue
Block a user