@@ -172,8 +172,13 @@ private Image (Device device, int nativeZoom) {
172
172
* @see #dispose()
173
173
*/
174
174
public 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 ) {
175
180
super (device );
176
- initialNativeZoom = DPIUtil . getNativeDeviceZoom () ;
181
+ initialNativeZoom = nativeZoom ;
177
182
final int zoom = getZoom ();
178
183
width = DPIUtil .scaleUp (width , zoom );
179
184
height = DPIUtil .scaleUp (height , zoom );
@@ -602,6 +607,32 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
602
607
this .device .registerResourceWithZoomSupport (this );
603
608
}
604
609
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
+
605
636
private ImageData adaptImageDataIfDisabledOrGray (ImageData data ) {
606
637
ImageData returnImageData = null ;
607
638
switch (this .styleFlag ) {
@@ -1140,6 +1171,9 @@ ImageHandle initNative(String filename, int zoom) {
1140
1171
void destroy () {
1141
1172
device .deregisterResourceWithZoomSupport (this );
1142
1173
if (memGC != null ) memGC .dispose ();
1174
+ if (this .imageProvider != null ) {
1175
+ this .imageProvider .destroy ();
1176
+ }
1143
1177
destroyHandle ();
1144
1178
memGC = null ;
1145
1179
}
@@ -1282,14 +1316,17 @@ public Rectangle getBounds() {
1282
1316
1283
1317
Rectangle getBounds (int zoom ) {
1284
1318
if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
1285
- ImageHandle imageMetadata ;
1286
1319
if (zoomLevelToImageHandle .containsKey (zoom )) {
1287
- imageMetadata = zoomLevelToImageHandle .get (zoom );
1320
+ ImageHandle imageMetadata = zoomLevelToImageHandle .get (zoom );
1321
+ Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1322
+ return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
1323
+ } else if (this .imageProvider != null ) {
1324
+ return this .imageProvider .getBounds (zoom );
1288
1325
} else {
1289
- imageMetadata = zoomLevelToImageHandle .values ().iterator ().next ();
1326
+ ImageHandle imageMetadata = zoomLevelToImageHandle .values ().iterator ().next ();
1327
+ Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1328
+ return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
1290
1329
}
1291
- Rectangle rectangle = new Rectangle (0 , 0 , imageMetadata .width , imageMetadata .height );
1292
- return DPIUtil .scaleBounds (rectangle , zoom , imageMetadata .zoom );
1293
1330
}
1294
1331
1295
1332
/**
@@ -1932,6 +1969,9 @@ public void internal_dispose_GC (long hDC, GCData data) {
1932
1969
*/
1933
1970
@ Override
1934
1971
public boolean isDisposed () {
1972
+ if (this .imageProvider != null ) {
1973
+ return this .imageProvider .isDisposed ();
1974
+ }
1935
1975
return zoomLevelToImageHandle .isEmpty ();
1936
1976
}
1937
1977
@@ -2043,9 +2083,11 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
2043
2083
2044
2084
private abstract class AbstractImageProviderWrapper {
2045
2085
abstract Object getProvider ();
2086
+ protected abstract Rectangle getBounds (int zoom );
2046
2087
abstract ImageData getImageData (int zoom );
2047
2088
abstract ImageHandle getImageMetadata (int zoom );
2048
2089
abstract AbstractImageProviderWrapper createCopy (Image image );
2090
+ abstract boolean isDisposed ();
2049
2091
2050
2092
protected void checkProvider (Object provider , Class <?> expectedClass ) {
2051
2093
if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
@@ -2062,6 +2104,9 @@ public boolean equals(Object otherProvider) {
2062
2104
return otherProvider instanceof AbstractImageProviderWrapper aip //
2063
2105
&& getProvider ().equals (aip .getProvider ());
2064
2106
}
2107
+
2108
+ protected void destroy () {
2109
+ }
2065
2110
}
2066
2111
2067
2112
private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
@@ -2076,6 +2121,13 @@ private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper
2076
2121
this .provider = provider ;
2077
2122
}
2078
2123
2124
+ @ Override
2125
+ protected Rectangle getBounds (int zoom ) {
2126
+ ImageHandle imageHandle = zoomLevelToImageHandle .values ().iterator ().next ();
2127
+ Rectangle rectangle = new Rectangle (0 , 0 , imageHandle .width , imageHandle .height );
2128
+ return DPIUtil .scaleBounds (rectangle , zoom , imageHandle .zoom );
2129
+ }
2130
+
2079
2131
@ Override
2080
2132
ImageData getImageData (int zoom ) {
2081
2133
ElementAtZoom <String > fileName = DPIUtil .validateAndGetImagePathAtZoom (provider , zoom );
@@ -2099,6 +2151,11 @@ ImageHandle getImageMetadata(int zoom) {
2099
2151
return zoomLevelToImageHandle .get (zoom );
2100
2152
}
2101
2153
2154
+ @ Override
2155
+ boolean isDisposed () {
2156
+ return zoomLevelToImageHandle .isEmpty ();
2157
+ }
2158
+
2102
2159
@ Override
2103
2160
Object getProvider () {
2104
2161
return provider ;
@@ -2127,6 +2184,13 @@ private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2127
2184
this .provider = provider ;
2128
2185
}
2129
2186
2187
+ @ Override
2188
+ protected Rectangle getBounds (int zoom ) {
2189
+ ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2190
+ Rectangle rectangle = new Rectangle (0 , 0 , data .element ().width , data .element ().height );
2191
+ return DPIUtil .scaleBounds (rectangle , zoom , data .zoom ());
2192
+ }
2193
+
2130
2194
@ Override
2131
2195
ImageData getImageData (int zoom ) {
2132
2196
ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
@@ -2143,6 +2207,11 @@ ImageHandle getImageMetadata(int zoom) {
2143
2207
return zoomLevelToImageHandle .get (zoom );
2144
2208
}
2145
2209
2210
+ @ Override
2211
+ boolean isDisposed () {
2212
+ return zoomLevelToImageHandle .isEmpty ();
2213
+ }
2214
+
2146
2215
@ Override
2147
2216
Object getProvider () {
2148
2217
return provider ;
@@ -2154,6 +2223,70 @@ ImageDataProviderWrapper createCopy(Image image) {
2154
2223
}
2155
2224
}
2156
2225
2226
+ private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2227
+ private ImageGcDrawer drawer ;
2228
+ private int width ;
2229
+ private int height ;
2230
+ private boolean isDestroyed = false ;
2231
+
2232
+ public ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
2233
+ checkProvider (imageGcDrawer , ImageGcDrawer .class );
2234
+ this .drawer = imageGcDrawer ;
2235
+ this .width = width ;
2236
+ this .height = height ;
2237
+ }
2238
+
2239
+ @ Override
2240
+ protected Rectangle getBounds (int zoom ) {
2241
+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2242
+ return DPIUtil .scaleBounds (rectangle , zoom , 100 );
2243
+ }
2244
+
2245
+ @ Override
2246
+ ImageData getImageData (int zoom ) {
2247
+ return getImageMetadata (zoom ).getImageData ();
2248
+ }
2249
+
2250
+ @ Override
2251
+ ImageHandle getImageMetadata (int zoom ) {
2252
+ initialNativeZoom = zoom ;
2253
+ Image image = new Image (device , width , height , zoom );
2254
+ GC gc = new GC (image );
2255
+ try {
2256
+ gc .data .nativeZoom = zoom ;
2257
+ drawer .drawOn (gc );
2258
+ ImageData imageData = image .getImageMetadata (zoom ).getImageData ();
2259
+ drawer .postProcess (imageData );
2260
+ ImageData newData = adaptImageDataIfDisabledOrGray (imageData );
2261
+ init (newData , zoom );
2262
+ } finally {
2263
+ gc .dispose ();
2264
+ image .dispose ();
2265
+ }
2266
+ return zoomLevelToImageHandle .get (zoom );
2267
+ }
2268
+
2269
+ @ Override
2270
+ protected void destroy () {
2271
+ isDestroyed = true ;
2272
+ }
2273
+
2274
+ @ Override
2275
+ boolean isDisposed () {
2276
+ return isDestroyed ;
2277
+ }
2278
+
2279
+ @ Override
2280
+ Object getProvider () {
2281
+ return drawer ;
2282
+ }
2283
+
2284
+ @ Override
2285
+ ImageGcDrawerWrapper createCopy (Image image ) {
2286
+ return image .new ImageGcDrawerWrapper (drawer , width , height );
2287
+ }
2288
+ }
2289
+
2157
2290
private class ImageHandle {
2158
2291
private final long handle ;
2159
2292
private final int zoom ;
0 commit comments