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 4d29c190884..4a8f3fdccbe 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 @@ -17,6 +17,7 @@ import org.eclipse.swt.accessibility.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.*; import org.eclipse.swt.widgets.*; /** @@ -717,26 +718,24 @@ public Rectangle computeTrim (int x, int y, int width, int height) { } return trim; } + Image createButtonImage(Display display, int button) { - return new Image(display, (ImageDataProvider) zoom -> { - GC tempGC = new GC (CTabFolder.this); - Point size = renderer.computeSize(button, SWT.NONE, tempGC, SWT.DEFAULT, SWT.DEFAULT); - tempGC.dispose(); - - Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0); - Image image = new Image (display, size.x - trim.width, size.y - trim.height); - GC gc = new GC (image); - Color transColor = renderer.parent.getBackground(); - gc.setBackground(transColor); - gc.fillRectangle(image.getBounds()); - renderer.draw(button, SWT.NONE, new Rectangle(trim.x, trim.y, size.x, size.y), gc); - gc.dispose (); - - final ImageData imageData = image.getImageData (zoom); - imageData.transparentPixel = imageData.palette.getPixel(transColor.getRGB()); - image.dispose(); - return imageData; - }); + final GC tempGC = new GC (CTabFolder.this); + final Point size = renderer.computeSize(button, SWT.NONE, tempGC, SWT.DEFAULT, SWT.DEFAULT); + tempGC.dispose(); + + final Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0); + final Rectangle imageBounds = new Rectangle(0, 0, size.x - trim.width, size.y - trim.height); + Color transColor = renderer.parent.getBackground(); + final ImageGcDrawer imageGcDrawer = new TransparancyColorImageGcDrawer(transColor) { + @Override + public void drawOn(GC gc) { + gc.setBackground(transColor); + gc.fillRectangle(imageBounds); + renderer.draw(button, SWT.NONE, new Rectangle(trim.x, trim.y, size.x, size.y), gc); + } + }; + return new Image(display, imageGcDrawer, imageBounds.width, imageBounds.height); } private void notifyItemCountChange() { 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 f20ab4fc55c..b1d1c8b26ec 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 @@ -135,6 +135,11 @@ public final class Image extends Resource implements Drawable { */ private ImageDataProvider imageDataProvider; + /** + * ImageGcDrawer to provide a callback to draw on a GC for various zoom levels + */ + private ImageGcDrawer imageGcDrawer; + /** * Style flag used to differentiate normal, gray-scale and disabled images based * on image data providers. Without this, a normal and a disabled image of the @@ -384,8 +389,9 @@ public Image(Device device, Image srcImage, int flag) { imageFileNameProvider = srcImage.imageFileNameProvider; imageDataProvider = srcImage.imageDataProvider; + imageGcDrawer = srcImage.imageGcDrawer; this.styleFlag = srcImage.styleFlag | flag; - if (imageFileNameProvider != null || imageDataProvider != null) { + if (imageFileNameProvider != null || imageDataProvider != null ||srcImage.imageGcDrawer != null) { /* If source image has 200% representation then create the 200% representation for the new image & apply flag */ NSBitmapImageRep rep200 = srcImage.getRepresentation (200); if (rep200 != null) createRepFromSourceAndApplyFlag(rep200, srcWidth * 2, srcHeight * 2, flag); @@ -843,6 +849,62 @@ public Image(Device device, ImageDataProvider imageDataProvider) { } } +/** + * The provided ImageGcDrawer will be called on demand whenever a new variant of the + * Image for an additional zoom is required. Depending on the OS specific implementation + * these calls will be done during the instantiation or later when a new variant is + * requested + *
+ * + * @param device the device on which to create the image + * @param imageGcDrawer the ImageGcDrawer object to be called when a new image variant + * for another zoom is required. + * @param width the width of the new image in points + * @param height the height of the new image in points + * + * @exception IllegalArgumentException
+ *
+ * @param gc
+ * The GC will draw on the underlying Image and is configured for the targeted zoom
+ * @since 3.129
+ */
+ void drawOn(GC gc);
+
+ /**
+ * Implement this method if any post processing of the ImageData created by the operations on the
+ * GC in drawOn
is necessary.
+ *
+ *
+ * @param imageData
+ * The resulting ImageData after drawOn
was called
+ * @since 3.129
+ */
+ default void postProcess(ImageData imageData) {}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/TransparancyColorImageGcDrawer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/TransparancyColorImageGcDrawer.java
new file mode 100644
index 00000000000..f054c6d9677
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/TransparancyColorImageGcDrawer.java
@@ -0,0 +1,18 @@
+package org.eclipse.swt.internal;
+
+import org.eclipse.swt.graphics.*;
+
+public abstract class TransparancyColorImageGcDrawer implements ImageGcDrawer {
+
+ private final Color transparancyColor;
+
+ public TransparancyColorImageGcDrawer(Color transparancyColor) {
+ this.transparancyColor = transparancyColor;
+ }
+
+ @Override
+ public void postProcess(ImageData imageData) {
+ imageData.transparentPixel = imageData.palette.getPixel(transparancyColor.getRGB());
+ }
+
+}
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 2b48e4b34a5..1ea53b07701 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
@@ -151,6 +151,11 @@ public final class Image extends Resource implements Drawable {
*/
private ImageDataProvider imageDataProvider;
+ /**
+ * ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
+ */
+ private ImageGcDrawer imageGcDrawer;
+
/**
* Style flag used to differentiate normal, gray-scale and disabled images based
* on image data providers. Without this, a normal and a disabled image of the
@@ -263,6 +268,7 @@ public Image(Device device, Image srcImage, int flag) {
this.type = srcImage.type;
this.imageDataProvider = srcImage.imageDataProvider;
this.imageFileNameProvider = srcImage.imageFileNameProvider;
+ this.imageGcDrawer = srcImage.imageGcDrawer;
this.styleFlag = srcImage.styleFlag | flag;
this.currentDeviceZoom = srcImage.currentDeviceZoom;
@@ -661,6 +667,37 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
init ();
}
+/**
+ * The provided ImageGcDrawer will be called on demand whenever a new variant of the
+ * Image for an additional zoom is required. Depending on the OS specific implementation
+ * these calls will be done during the instantiation or later when a new variant is
+ * requested
+ *
+ * + * @param device the device on which to create the image + * @param imageGcDrawer the ImageGcDrawer object to be called when a new image variant + * for another zoom is required. + * @param width the width of the new image in points + * @param height the height of the new image in points + * + * @exception IllegalArgumentException
@@ -722,6 +759,17 @@ boolean refreshImageForZoom () {
refreshed = true;
currentDeviceZoom = deviceZoomLevel;
}
+ } else if (imageGcDrawer != null) {
+ int deviceZoomLevel = deviceZoom;
+ if (deviceZoomLevel != currentDeviceZoom) {
+ ImageData data = drawWithImageGcDrawer(width, height, deviceZoomLevel);
+ /* Release current native resources */
+ destroy ();
+ init(data);
+ init();
+ refreshed = true;
+ currentDeviceZoom = deviceZoomLevel;
+ }
} else {
if (!DPIUtil.useCairoAutoScale()) {
int deviceZoomLevel = deviceZoom;
@@ -904,6 +952,8 @@ public boolean equals (Object object) {
return (styleFlag == image.styleFlag) && imageDataProvider.equals (image.imageDataProvider);
} else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
return (styleFlag == image.styleFlag) && imageFileNameProvider.equals (image.imageFileNameProvider);
+ } else if (imageGcDrawer != null && image.imageGcDrawer != null) {
+ return styleFlag == image.styleFlag && imageGcDrawer.equals (image.imageGcDrawer);
} else {
return surface == image.surface;
}
@@ -1110,11 +1160,33 @@ public ImageData getImageData (int zoom) {
} else if (imageFileNameProvider != null) {
ElementAtZoom
@@ -1179,6 +1251,8 @@ public int hashCode () {
return imageDataProvider.hashCode();
} else if (imageFileNameProvider != null) {
return imageFileNameProvider.hashCode();
+ } else if (imageGcDrawer != null) {
+ return imageGcDrawer.hashCode();
} else {
return (int)surface;
}
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 ddd2aaeaee3..3d5a8a9d8a3 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
@@ -172,8 +172,13 @@ private Image (Device device, int nativeZoom) {
* @see #dispose()
*/
public Image(Device device, int width, int height) {
+ this(device, width, height, DPIUtil.getNativeDeviceZoom());
+}
+
+
+private Image(Device device, int width, int height, int nativeZoom) {
super(device);
- initialNativeZoom = DPIUtil.getNativeDeviceZoom();
+ initialNativeZoom = nativeZoom;
final int zoom = getZoom();
width = DPIUtil.scaleUp (width, zoom);
height = DPIUtil.scaleUp (height, zoom);
@@ -602,6 +607,32 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
this.device.registerResourceWithZoomSupport(this);
}
+/**
+ * The provided ImageGcDrawer will be called on demand whenever a new variant of the
+ * Image for an additional zoom is required. Depending on the OS specific implementation
+ * these calls will be done during the instantiation or later when a new variant is
+ * requested
+ *
+ *
+ * @param device the device on which to create the image
+ * @param imageGcDrawer the ImageGcDrawer object to be called when a new image variant
+ * for another zoom is required.
+ * @param width the width of the new image in points
+ * @param height the height of the new image in points
+ *
+ * @exception IllegalArgumentException
+ *
+ * @since 3.129
+ */
+public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
+ super(device);
+ this.imageProvider = new ImageGcDrawerWrapper(imageGcDrawer, width, height);
+ initialNativeZoom = DPIUtil.getNativeDeviceZoom();
+ init();
+}
+
private ImageData adaptImageDataIfDisabledOrGray(ImageData data) {
ImageData returnImageData = null;
switch (this.styleFlag) {
@@ -1140,6 +1171,9 @@ ImageHandle initNative(String filename, int zoom) {
void destroy () {
device.deregisterResourceWithZoomSupport(this);
if (memGC != null) memGC.dispose();
+ if (this.imageProvider != null) {
+ this.imageProvider.destroy();
+ }
destroyHandle();
memGC = null;
}
@@ -1282,14 +1316,17 @@ public Rectangle getBounds() {
Rectangle getBounds(int zoom) {
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
- ImageHandle imageMetadata;
if (zoomLevelToImageHandle.containsKey(zoom)) {
- imageMetadata = zoomLevelToImageHandle.get(zoom);
+ ImageHandle imageMetadata = zoomLevelToImageHandle.get(zoom);
+ Rectangle rectangle = new Rectangle(0, 0, imageMetadata.width, imageMetadata.height);
+ return DPIUtil.scaleBounds(rectangle, zoom, imageMetadata.zoom);
+ } else if (this.imageProvider != null) {
+ return this.imageProvider.getBounds(zoom);
} else {
- imageMetadata = zoomLevelToImageHandle.values().iterator().next();
+ ImageHandle imageMetadata = zoomLevelToImageHandle.values().iterator().next();
+ Rectangle rectangle = new Rectangle(0, 0, imageMetadata.width, imageMetadata.height);
+ return DPIUtil.scaleBounds(rectangle, zoom, imageMetadata.zoom);
}
- Rectangle rectangle = new Rectangle(0, 0, imageMetadata.width, imageMetadata.height);
- return DPIUtil.scaleBounds(rectangle, zoom, imageMetadata.zoom);
}
/**
@@ -1932,6 +1969,9 @@ public void internal_dispose_GC (long hDC, GCData data) {
*/
@Override
public boolean isDisposed() {
+ if (this.imageProvider != null) {
+ return this.imageProvider.isDisposed();
+ }
return zoomLevelToImageHandle.isEmpty();
}
@@ -2043,9 +2083,11 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
private abstract class AbstractImageProviderWrapper {
abstract Object getProvider();
+ protected abstract Rectangle getBounds(int zoom);
abstract ImageData getImageData(int zoom);
abstract ImageHandle getImageMetadata(int zoom);
abstract AbstractImageProviderWrapper createCopy(Image image);
+ abstract boolean isDisposed();
protected void checkProvider(Object provider, Class> expectedClass) {
if (provider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
@@ -2062,6 +2104,9 @@ public boolean equals(Object otherProvider) {
return otherProvider instanceof AbstractImageProviderWrapper aip //
&& getProvider().equals(aip.getProvider());
}
+
+ protected void destroy() {
+ }
}
private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
@@ -2076,6 +2121,13 @@ private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper
this.provider = provider;
}
+ @Override
+ protected Rectangle getBounds(int zoom) {
+ ImageHandle imageHandle = zoomLevelToImageHandle.values().iterator().next();
+ Rectangle rectangle = new Rectangle(0, 0, imageHandle.width, imageHandle.height);
+ return DPIUtil.scaleBounds(rectangle, zoom, imageHandle.zoom);
+ }
+
@Override
ImageData getImageData(int zoom) {
ElementAtZoom