From 1185b0d0f0cf245857e951bb48d43d7977b7ae0a 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. --- .../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 3183837259ef5c246ec8af49ffade4fe3cbede2b 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()]);