From 447a6a438bf184006be8b74ddbb4b4d986011c23 Mon Sep 17 00:00:00 2001 From: "Klare, Heiko" Date: Thu, 21 May 2026 13:43:45 +0200 Subject: [PATCH] [Win32] Avoid unnecessary creation of GC operations The storage of executed operations in a GC has been added to support the situation that a Drawable is created with a GC without knowing the final zoom in which the Drawable is supposed to be used. A common example is the creation of a (buffer) image, which is later to be drawn on a control, but at the time of drawing the image that zoom is not known. The operations allow to recreate the image for that required zoom. In most use cases of a GC, however, there is no need and no possibility to recreate the underlying drawable from a GC. In particular, when drawing to a control, the zoom of that control is known while drawing such that no storage of GC operations is necessary. The storage of GC operations can become rather expensive, in particular if the drawing of images is involved and copies of those images need to be created upon their disposal. For that reason, this change reduces the cases in which operations are actually stored to those where they are really required for recreation of the underlying drawable. Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/3296 --- .../win32/org/eclipse/swt/graphics/GC.java | 13 ++++++++++--- .../win32/org/eclipse/swt/graphics/GCData.java | 1 + .../win32/org/eclipse/swt/graphics/Image.java | 3 ++- .../junit/Test_org_eclipse_swt_graphics_GC.java | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index 5a422f01859..75889472a5f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -6002,8 +6002,11 @@ Point textExtentInPixels(String string, int flags) { return new Point(rect.right, rect.bottom); } -void refreshFor(Drawable drawable, ImageHandle imageHandle) { +void reapplyTo(Drawable drawable, ImageHandle imageHandle) { if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (!data.reapplicable) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } destroy(); GCData newData = new GCData(); originalData.copyTo(newData); @@ -6109,9 +6112,13 @@ int getZoom() { } private void storeAndApplyOperationForExistingHandle(Operation operation) { - removePreviousOperationIfSupercededBy(operation); - operations.add(operation); operation.apply(); + if (data.reapplicable) { + removePreviousOperationIfSupercededBy(operation); + operations.add(operation); + } else { + operation.disposeAll(); + } } private void removePreviousOperationIfSupercededBy(Operation operation) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java index a8ccae520a9..d6aa2371674 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java @@ -49,6 +49,7 @@ public final class GCData { public int alpha = 0xFF; public int nativeZoom; int imageZoom; + boolean reapplicable; public Image image; public PAINTSTRUCT ps; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index 76ccd1c7b9d..fe0c3a3f310 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -2333,6 +2333,7 @@ public Collection getPreservedZoomLevels() { @Override protected long configureGCData(GCData data) { + data.reapplicable = true; return configureGC(data, new ZoomContext(DPIUtil.getDeviceZoom(), DPIUtil.getNativeDeviceZoom())); } @@ -2374,7 +2375,7 @@ protected DestroyableImageHandle newImageHandle(ZoomContext zoomContext) { GC currentGC = memGC; memGC = null; DestroyableImageHandle imageHandle = createHandle(targetZoom); - currentGC.refreshFor(new DrawableWrapper(Image.this, zoomContext), imageHandle); + currentGC.reapplyTo(new DrawableWrapper(Image.this, zoomContext), imageHandle); return imageHandle; } diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java index cafb4f91468..2806c1d8650 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java @@ -487,8 +487,8 @@ public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataAtSizePro Exception e = assertThrows(IllegalArgumentException.class, () -> gc.drawImage(image, 0, 0, 1, 1)); assertSWTProblem("Incorrect exception thrown for provider == null", SWT.ERROR_INVALID_ARGUMENT, e); } finally { - image.dispose(); drawToImage.dispose(); + image.dispose(); } }