@@ -172,8 +172,13 @@ private Image (Device device, int nativeZoom) {
172172 * @see #dispose()
173173 */
174174public Image (Device device , int width , int height ) {
175+ this (device , width , height , DPIUtil .getNativeDeviceZoom ());
176+ }
177+
178+
179+ private Image (Device device , int width , int height , int nativeZoom ) {
175180 super (device );
176- initialNativeZoom = DPIUtil . getNativeDeviceZoom () ;
181+ initialNativeZoom = nativeZoom ;
177182 final int zoom = getZoom ();
178183 width = DPIUtil .scaleUp (width , zoom );
179184 height = DPIUtil .scaleUp (height , zoom );
@@ -602,6 +607,32 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
602607 this .device .registerResourceWithZoomSupport (this );
603608}
604609
610+ /**
611+ * The provided ImageGcDrawer will be called on demand whenever a new variant of the
612+ * Image for an additional zoom is required. Depending on the OS specific implementation
613+ * these calls will be done during the instantiation or later when a new variant is
614+ * requested
615+ * <p>
616+ *
617+ * @param device the device on which to create the image
618+ * @param imageGcDrawer the ImageGcDrawer object to be called when a new image variant
619+ * for another zoom is required.
620+ * @param width the width of the new image in points
621+ * @param height the height of the new image in points
622+ *
623+ * @exception IllegalArgumentException <ul>
624+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
625+ * <li>ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null</li>
626+ * </ul>
627+ * @since 3.129
628+ */
629+ public Image (Device device , ImageGcDrawer imageGcDrawer , int width , int height ) {
630+ super (device );
631+ this .imageProvider = new ImageGcDrawerWrapper (imageGcDrawer , width , height );
632+ initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
633+ init ();
634+ }
635+
605636private ImageData adaptImageDataIfDisabledOrGray (ImageData data ) {
606637 ImageData returnImageData = null ;
607638 switch (this .styleFlag ) {
@@ -1282,14 +1313,17 @@ public Rectangle getBounds() {
12821313
12831314Rectangle getBounds (int zoom ) {
12841315 if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
1285- ImageHandle imageMetadata ;
12861316 if (zoomLevelToImageHandle .containsKey (zoom )) {
1287- imageMetadata = zoomLevelToImageHandle .get (zoom );
1317+ ImageHandle imageMetadata = zoomLevelToImageHandle .get (zoom );
1318+ Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1319+ return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
1320+ } else if (this .imageProvider != null ) {
1321+ return this .imageProvider .getBounds (zoom );
12881322 } else {
1289- imageMetadata = zoomLevelToImageHandle .values ().iterator ().next ();
1323+ ImageHandle imageMetadata = zoomLevelToImageHandle .values ().iterator ().next ();
1324+ Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1325+ return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
12901326 }
1291- Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1292- return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
12931327}
12941328
12951329/**
@@ -1932,6 +1966,9 @@ public void internal_dispose_GC (long hDC, GCData data) {
19321966 */
19331967@ Override
19341968public boolean isDisposed () {
1969+ if (this .imageProvider != null ) {
1970+ return this .imageProvider .isDisposed ();
1971+ }
19351972 return zoomLevelToImageHandle .isEmpty ();
19361973}
19371974
@@ -2043,9 +2080,11 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
20432080
20442081private abstract class AbstractImageProviderWrapper {
20452082 abstract Object getProvider ();
2083+ protected abstract Rectangle getBounds (int zoom );
20462084 abstract ImageData getImageData (int zoom );
20472085 abstract ImageHandle getImageMetadata (int zoom );
20482086 abstract AbstractImageProviderWrapper createCopy (Image image );
2087+ abstract boolean isDisposed ();
20492088
20502089 protected void checkProvider (Object provider , Class <?> expectedClass ) {
20512090 if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
@@ -2076,6 +2115,13 @@ private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper
20762115 this .provider = provider ;
20772116 }
20782117
2118+ @ Override
2119+ protected Rectangle getBounds (int zoom ) {
2120+ ImageHandle imageHandle = zoomLevelToImageHandle .values ().iterator ().next ();
2121+ Rectangle rectangle = new Rectangle (0 , 0 , imageHandle .width , imageHandle .height );
2122+ return DPIUtil .scaleBounds (rectangle , zoom , imageHandle .zoom );
2123+ }
2124+
20792125 @ Override
20802126 ImageData getImageData (int zoom ) {
20812127 ElementAtZoom <String > fileName = DPIUtil .validateAndGetImagePathAtZoom (provider , zoom );
@@ -2099,6 +2145,11 @@ ImageHandle getImageMetadata(int zoom) {
20992145 return zoomLevelToImageHandle .get (zoom );
21002146 }
21012147
2148+ @ Override
2149+ boolean isDisposed () {
2150+ return zoomLevelToImageHandle .isEmpty ();
2151+ }
2152+
21022153 @ Override
21032154 Object getProvider () {
21042155 return provider ;
@@ -2127,6 +2178,13 @@ private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
21272178 this .provider = provider ;
21282179 }
21292180
2181+ @ Override
2182+ protected Rectangle getBounds (int zoom ) {
2183+ ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2184+ Rectangle rectangle = new Rectangle (0 , 0 , data .element ().width , data .element ().height );
2185+ return DPIUtil .scaleBounds (rectangle , zoom , data .zoom ());
2186+ }
2187+
21302188 @ Override
21312189 ImageData getImageData (int zoom ) {
21322190 ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
@@ -2143,6 +2201,11 @@ ImageHandle getImageMetadata(int zoom) {
21432201 return zoomLevelToImageHandle .get (zoom );
21442202 }
21452203
2204+ @ Override
2205+ boolean isDisposed () {
2206+ return zoomLevelToImageHandle .isEmpty ();
2207+ }
2208+
21462209 @ Override
21472210 Object getProvider () {
21482211 return provider ;
@@ -2154,6 +2217,63 @@ ImageDataProviderWrapper createCopy(Image image) {
21542217 }
21552218}
21562219
2220+ private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2221+ private ImageGcDrawer drawer ;
2222+ private int width ;
2223+ private int height ;
2224+
2225+ public ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
2226+ checkProvider (imageGcDrawer , ImageGcDrawer .class );
2227+ this .drawer = imageGcDrawer ;
2228+ this .width = width ;
2229+ this .height = height ;
2230+ }
2231+
2232+ @ Override
2233+ protected Rectangle getBounds (int zoom ) {
2234+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2235+ return DPIUtil .scaleBounds (rectangle , zoom , 100 );
2236+ }
2237+
2238+ @ Override
2239+ ImageData getImageData (int zoom ) {
2240+ return getImageMetadata (zoom ).getImageData ();
2241+ }
2242+
2243+ @ Override
2244+ ImageHandle getImageMetadata (int zoom ) {
2245+ initialNativeZoom = zoom ;
2246+ Image image = new Image (device , width , height , zoom );
2247+ GC gc = new GC (image );
2248+ try {
2249+ gc .data .nativeZoom = zoom ;
2250+ drawer .drawOn (gc );
2251+ ImageData id = image .getImageMetadata (zoom ).getImageData ();
2252+ ImageData newData = adaptImageDataIfDisabledOrGray (id );
2253+ init (newData , zoom );
2254+ } finally {
2255+ gc .dispose ();
2256+ image .dispose ();
2257+ }
2258+ return zoomLevelToImageHandle .get (zoom );
2259+ }
2260+
2261+ @ Override
2262+ boolean isDisposed () {
2263+ return false ;
2264+ }
2265+
2266+ @ Override
2267+ Object getProvider () {
2268+ return drawer ;
2269+ }
2270+
2271+ @ Override
2272+ ImageGcDrawerWrapper createCopy (Image image ) {
2273+ return image .new ImageGcDrawerWrapper (drawer , width , height );
2274+ }
2275+ }
2276+
21572277private class ImageHandle {
21582278 private final long handle ;
21592279 private final int zoom ;
0 commit comments