From 0e5c5b6c1816cc81f1364022ac1851327e82f532 Mon Sep 17 00:00:00 2001 From: Thomas Singer Date: Thu, 27 Aug 2026 14:22:09 +0200 Subject: [PATCH 1/2] StyledText: selecting larger number of rows gets very slow #3523 StyledText.getSelectionRanges() is quite expensive: for a larger number of selected rows it can take up to ~30-40ms on my machine. Invoking this method for each drawn row (!) is very inefficient, because it expensively calculates the same information again and again. Hence, we just invoke it one time for each drawLines invocation. Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/3523 --- .../org/eclipse/swt/custom/StyledTextRenderer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index fa0281c2b31..006e55d0d7d 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -471,6 +471,7 @@ private LineDrawInfo makeLineDrawInfo(int lineIndex) { } int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, Color widgetBackground, Color widgetForeground) { + final int[] selectionRanges = styledText.getSelectionRanges(); // When fixed line metrics is in effect, tall unicode characters // will not always fit line's height. In this case, they will // draw out of line's bounds. To prevent them from being clipped @@ -503,7 +504,7 @@ int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, C // Draw foreground y = begY; for (LineDrawInfo lineInfo : drawInfos) { - drawLineForeground(lineInfo, begX, y, gc, widgetForeground); + drawLineForeground(lineInfo, begX, y, gc, widgetForeground, selectionRanges); y += lineInfo.height; } @@ -519,7 +520,7 @@ int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, C for (int iLine = startLine; y < endY && iLine < endLine; iLine++) { LineDrawInfo lineInfo = makeLineDrawInfo(iLine); drawLineBackground(lineInfo, y, gc, widgetBackground); - drawLineForeground(lineInfo, begX, y, gc, widgetForeground); + drawLineForeground(lineInfo, begX, y, gc, widgetForeground, selectionRanges); disposeTextLayout(lineInfo.layout); y += lineInfo.height; } @@ -546,10 +547,10 @@ private void drawLineBackground(LineDrawInfo lineInfo, int paintY, GC gc, Color } } -private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground) { +private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground, int[] selectionRanges) { int lineLength = lineInfo.text.length(); gc.setForeground(widgetForeground); - Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength); + Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength, selectionRanges); if (styledText.getBlockSelection() || selection.length == 0) { lineInfo.layout.draw(gc, paintX, paintY); } else { @@ -614,8 +615,7 @@ private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, G } } -private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset) { - int[] selectionRanges = styledText.getSelectionRanges(); +private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset, int[] selectionRanges) { int lineLength = toOffset - fromOffset; List res = new ArrayList<>(); for (int i = 0; i < selectionRanges.length; i += 2) { From 1d1714cd90021e174b43d26f36f4b173e835549f Mon Sep 17 00:00:00 2001 From: Thomas Singer Date: Thu, 27 Aug 2026 14:25:15 +0200 Subject: [PATCH 2/2] StyledTextRenderer.intersectingRelativeNonEmptySelections: only create a point instance if we need it --- .../org/eclipse/swt/custom/StyledTextRenderer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index 006e55d0d7d..a1c9c4b53b3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -619,11 +619,11 @@ private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOff int lineLength = toOffset - fromOffset; List res = new ArrayList<>(); for (int i = 0; i < selectionRanges.length; i += 2) { - // ranges are assumed to be sorted by start offset, then (positive)length or higher end offset - Point relativeSelection = new Point(selectionRanges[i] - fromOffset, selectionRanges[i] + selectionRanges[i + 1] - fromOffset); - if (relativeSelection.x != relativeSelection.y && - relativeSelection.x <= lineLength && relativeSelection.y >= 0) { - res.add(relativeSelection); + // ranges are assumed to be sorted by start offset, then (positive) length or higher end offset + final int x = selectionRanges[i] - fromOffset; + final int y = selectionRanges[i] + selectionRanges[i + 1] - fromOffset; + if (x != y && x <= lineLength && y >= 0) { + res.add(new Point(x, y)); } } return res.toArray(new Point[res.size()]);