diff --git a/binaries/org.eclipse.swt.win32.win32.x86_64/.settings/.api_filters b/binaries/org.eclipse.swt.win32.win32.x86_64/.settings/.api_filters
index 5d0ce47678..2f6b29f36a 100644
--- a/binaries/org.eclipse.swt.win32.win32.x86_64/.settings/.api_filters
+++ b/binaries/org.eclipse.swt.win32.win32.x86_64/.settings/.api_filters
@@ -582,10 +582,11 @@
-
+
-
+
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
index 989cf68dfc..951d303d09 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
@@ -734,7 +734,7 @@ Image createButtonImage(Display display, int button) {
final Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0);
final Point imageSize = new Point(size.x - trim.width, size.y - trim.height);
Color transColor = renderer.parent.getBackground();
- final ImageGcDrawer imageGcDrawer = new TransparencyColorImageGcDrawer(transColor) {
+ return new Image(display, imageSize.x, imageSize.y, new TransparencyColorImageGcDrawer(transColor) {
@Override
public void drawOn(GC gc, int imageWidth, int imageHeight) {
Rectangle imageBounds = new Rectangle(0, 0, imageWidth, imageHeight);
@@ -742,8 +742,7 @@ public void drawOn(GC gc, int imageWidth, int imageHeight) {
gc.fillRectangle(imageBounds);
renderer.draw(button, SWT.NONE, imageBounds, gc);
}
- };
- return new Image(display, imageGcDrawer, imageSize.x, imageSize.y);
+ });
}
private void notifyItemCountChange() {
@@ -4007,7 +4006,8 @@ void updateBkImages(boolean colorChanged) {
if (colorChanged || !bounds.equals(bkImageBounds[i])) {
bkImageBounds[i] = bounds;
if (controlBkImages[i] != null) controlBkImages[i].dispose();
- controlBkImages[i] = new Image(control.getDisplay(), (gc, imageWidth, imageHeight) -> renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc), bounds.width, bounds.height);
+ controlBkImages[i] = new Image(control.getDisplay(), bounds.width, bounds.height,
+ (gc, w, h) -> renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc));
control.setBackground(null);
control.setBackgroundImage(controlBkImages[i]);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
index aa73e8ecd7..ef4f17fc41 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
@@ -1593,15 +1593,14 @@ void createCaretBitmaps() {
leftCaretBitmap.dispose();
}
int lineHeight = renderer.getLineHeight();
- final ImageGcDrawer leftCaretDrawer = (gc, width, height) -> {
+ leftCaretBitmap = new Image(display, caretWidth, lineHeight, (gc, width, height) -> {
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(0, 0, width, height);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(0,0,0,height);
gc.drawLine(0,0,width-1,0);
gc.drawLine(0,1,1,1);
- };
- leftCaretBitmap = new Image(display, leftCaretDrawer, caretWidth, lineHeight);
+ });
if (rightCaretBitmap != null) {
if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
@@ -1609,16 +1608,16 @@ void createCaretBitmaps() {
}
rightCaretBitmap.dispose();
}
- final ImageGcDrawer rightCaretDrawer = (gc, width, height) -> {
+ rightCaretBitmap = new Image(display, caretWidth, lineHeight, (gc, width, height) -> {
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(0, 0, width, height);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(width-1,0,width-1,height);
gc.drawLine(0,0,width-1,0);
gc.drawLine(width-1,1,1,1);
- };
- rightCaretBitmap = new Image(display, rightCaretDrawer, caretWidth, lineHeight);
+ });
}
+
/**
* Moves the selected text to the clipboard. The text will be put in the
* clipboard in plain text, HTML, and RTF formats.
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java
index 25ec987f0e..4d83037ed6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java
@@ -142,7 +142,7 @@ public final class Image extends Resource implements Drawable {
/**
* ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
*/
- private ImageGcDrawer imageGcDrawer;
+ private ImageDrawer imageGcDrawer;
/**
* Style flag used to differentiate normal, gray-scale and disabled images based
@@ -878,9 +878,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
*
ERROR_NULL_ARGUMENT - if device is null and there is no current device
* ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null
*
- * @since 3.129
+ * @since 3.130
*/
-public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+public Image(Device device, int width, int height, ImageDrawer imageGcDrawer) {
super(device);
if (imageGcDrawer == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
this.imageGcDrawer = imageGcDrawer;
@@ -905,13 +905,22 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
}
}
-private ImageData drawWithImageGcDrawer(ImageGcDrawer imageGcDrawer, int width, int height, int zoom) {
+/**
+ * @since 3.129
+ * @deprecated Instead use {@link #Image(Device, int, int, ImageGcDrawer)}
+ */
+@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
+public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+ this(device, width, height, imageGcDrawer);
+}
+
+private ImageData drawWithImageGcDrawer(ImageDrawer imageGcDrawer, int width, int height, int zoom) {
Image image = new Image(device, width, height);
- GC gc = new GC(image);
+ GC gc = new GC(image, ExtendedImageDrawer.getGCStyle(imageGcDrawer));
try {
imageGcDrawer.drawOn(gc, width, height);
ImageData imageData = image.getImageData(zoom);
- imageGcDrawer.postProcess(imageData);
+ ExtendedImageDrawer.postProcess(imageGcDrawer, imageData);
return imageData;
} finally {
gc.dispose();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDrawer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDrawer.java
new file mode 100644
index 0000000000..cd4293581c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDrawer.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Yatta and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Yatta - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.util.function.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.image.*;
+
+/**
+ * Interface to provide a callback mechanism to draw on different GC instances
+ * depending on the zoom the image will be used for. A common use case is when
+ * the application is moved from a low DPI monitor to a high DPI monitor. This
+ * provides API which will be called by SWT during the image rendering.
+ *
+ * This interface needs to be implemented by client code to provide logic that
+ * draws on the empty GC on demand.
+ *
+ * @since 3.130
+ */
+@FunctionalInterface
+public interface ImageDrawer {
+
+ /**
+ * Draws an image on a GC for a requested zoom level.
+ *
+ * @param gc The GC will draw on the underlying Image and is configured
+ * for the targeted zoom
+ * @param imageWidth The width of the image in points to draw on
+ * @param imageHeight The height of the image in points to draw on
+ */
+ void drawOn(GC gc, int imageWidth, int imageHeight);
+
+ /**
+ * @since 3.130
+ */
+ public static ImageDrawer withGCStyle(int style, ImageDrawer drawer) {
+ if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
+ return new ExtendedImageDrawer(extendedDrawer.original(), extendedDrawer.postProcessor(), style);
+ }
+ return new ExtendedImageDrawer(drawer, null, style);
+ }
+
+ /**
+ * @since 3.130
+ */
+ public static ImageDrawer create(ImageDrawer drawer, Consumer postProcessor) {
+ if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
+ return new ExtendedImageDrawer(extendedDrawer.original(), postProcessor, extendedDrawer.style());
+ }
+ return new ExtendedImageDrawer(drawer, postProcessor, SWT.NONE);
+ }
+
+ // TODO: or use some kind of builder pattern?
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageGcDrawer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageGcDrawer.java
index 78388ef93b..89722e53e8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageGcDrawer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageGcDrawer.java
@@ -13,8 +13,6 @@
*******************************************************************************/
package org.eclipse.swt.graphics;
-import org.eclipse.swt.*;
-
/**
* Interface to provide a callback mechanism to draw on different GC instances
* depending on the zoom the image will be used for. A common use case is when
@@ -26,7 +24,8 @@
*
* @since 3.129
*/
-public interface ImageGcDrawer {
+@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
+public interface ImageGcDrawer extends ImageDrawer {
/**
* Draws an image on a GC for a requested zoom level.
@@ -36,6 +35,7 @@ public interface ImageGcDrawer {
* @param imageWidth The width of the image in points to draw on
* @param imageHeight The height of the image in points to draw on
*/
+ @Override
void drawOn(GC gc, int imageWidth, int imageHeight);
/**
@@ -47,15 +47,4 @@ public interface ImageGcDrawer {
default void postProcess(ImageData imageData) {
}
- /**
- * Returns the GC style used when creating the GC instance. Default
- * implementation returns SWT.NONE
.
- *
- * @return the GC style constant
- *
- * @since 3.130
- */
- default int getGcStyle() {
- return SWT.NONE;
- }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/ExtendedImageDrawer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/ExtendedImageDrawer.java
new file mode 100644
index 0000000000..68b02a2997
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/ExtendedImageDrawer.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Hannes Wellmann and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Hannes Wellmann - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.swt.internal.image;
+
+import java.util.*;
+import java.util.function.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+public record ExtendedImageDrawer(ImageDrawer original, Consumer postProcessor, int style)
+ implements ImageDrawer {
+
+ public ExtendedImageDrawer {
+ Objects.requireNonNull(original);
+ }
+
+ @Override
+ public void drawOn(GC gc, int imageWidth, int imageHeight) {
+ original.drawOn(gc, imageWidth, imageHeight);
+ }
+
+ public static int getGCStyle(ImageDrawer drawer) {
+ if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
+ return extendedDrawer.style();
+ }
+ return SWT.NONE;
+ }
+
+ public static void postProcess(ImageDrawer drawer, ImageData data) {
+ if (drawer instanceof @SuppressWarnings("removal") ImageGcDrawer gcDrawer) {
+ gcDrawer.postProcess(data);
+ } else if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
+ Consumer postProcessor2 = extendedDrawer.postProcessor();
+ if (postProcessor2 != null) {
+ postProcessor2.accept(data);
+ }
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
index 9d69e5a314..27815fb1d9 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
@@ -156,7 +156,7 @@ public final class Image extends Resource implements Drawable {
/**
* ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
*/
- private ImageGcDrawer imageGcDrawer;
+ private ImageDrawer imageGcDrawer;
/**
* Style flag used to differentiate normal, gray-scale and disabled images based
@@ -670,9 +670,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
* ERROR_NULL_ARGUMENT - if device is null and there is no current device
* ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null
*
- * @since 3.129
+ * @since 3.130
*/
-public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+public Image(Device device, int width, int height, ImageDrawer imageGcDrawer) {
super(device);
if (imageGcDrawer == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
@@ -684,6 +684,15 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
init ();
}
+/**
+ * @since 3.129
+ * @deprecated Instead use {@link #Image(Device, int, int, ImageGcDrawer)}
+ */
+@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
+public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+ this(device, width, height, imageGcDrawer);
+}
+
/**
* Refreshes the image for the current device scale factor.
*
@@ -1159,11 +1168,11 @@ public ImageData getImageData (int zoom) {
private ImageData drawWithImageGcDrawer(int width, int height, int zoom) {
Image image = new Image(device, width, height);
- GC gc = new GC(image);
+ GC gc = new GC(image, ExtendedImageDrawer.getGCStyle(imageGcDrawer));
try {
imageGcDrawer.drawOn(gc, width, height);
ImageData imageData = image.getImageData(zoom);
- imageGcDrawer.postProcess(imageData);
+ ExtendedImageDrawer.postProcess(imageGcDrawer, imageData);
return imageData;
} finally {
gc.dispose();
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 6844fe9b43..e3ff610ab4 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
@@ -629,15 +629,24 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
*
ERROR_NULL_ARGUMENT - if device is null and there is no current device
* ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null
*
- * @since 3.129
+ * @since 3.130
*/
-public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+public Image(Device device, int width, int height, ImageDrawer imageGcDrawer) {
super(device);
this.imageProvider = new ImageGcDrawerWrapper(imageGcDrawer, width, height);
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
init();
}
+/**
+ * @since 3.129
+ * @deprecated Instead use {@link #Image(Device, int, int, ImageGcDrawer)}
+ */
+@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
+public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+ this(device, width, height, imageGcDrawer);
+}
+
private ImageData adaptImageDataIfDisabledOrGray(ImageData data) {
ImageData returnImageData = null;
switch (this.styleFlag) {
@@ -2476,12 +2485,12 @@ ImageDataProviderWrapper createCopy(Image image) {
}
private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
- private ImageGcDrawer drawer;
+ private ImageDrawer drawer;
private int width;
private int height;
- ImageGcDrawerWrapper(ImageGcDrawer imageGcDrawer, int width, int height) {
- checkProvider(imageGcDrawer, ImageGcDrawer.class);
+ ImageGcDrawerWrapper(ImageDrawer imageGcDrawer, int width, int height) {
+ checkProvider(imageGcDrawer, ImageDrawer.class);
this.drawer = imageGcDrawer;
this.width = width;
this.height = height;
@@ -2502,12 +2511,12 @@ ImageData getImageData(int zoom) {
ImageHandle getImageMetadata(int zoom) {
initialNativeZoom = zoom;
Image image = new Image(device, width, height, zoom);
- GC gc = new GC(image, drawer.getGcStyle());
+ GC gc = new GC(image, ExtendedImageDrawer.getGCStyle(drawer));
try {
gc.data.nativeZoom = zoom;
drawer.drawOn(gc, width, height);
ImageData imageData = image.getImageMetadata(zoom).getImageData();
- drawer.postProcess(imageData);
+ ExtendedImageDrawer.postProcess(drawer, imageData);
ImageData newData = adaptImageDataIfDisabledOrGray(imageData);
init(newData, zoom);
} finally {