@@ -177,11 +177,8 @@ public Image(Device device, int width, int height) {
177
177
178
178
private Image (Device device , int width , int height , int nativeZoom ) {
179
179
super (device );
180
- initialNativeZoom = nativeZoom ;
181
- final int zoom = getZoom ();
182
- width = DPIUtil .scaleUp (width , zoom );
183
- height = DPIUtil .scaleUp (height , zoom );
184
- init (width , height );
180
+ this .initialNativeZoom = nativeZoom ;
181
+ this .imageProvider = new PlainImageProviderWrapper (width , height );
185
182
init ();
186
183
this .device .registerResourceWithZoomSupport (this );
187
184
}
@@ -327,13 +324,7 @@ public Image(Device device, Image srcImage, int flag) {
327
324
* @see #dispose()
328
325
*/
329
326
public Image (Device device , Rectangle bounds ) {
330
- super (device );
331
- if (bounds == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
332
- initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
333
- bounds = DPIUtil .scaleUp (bounds , getZoom ());
334
- init (bounds .width , bounds .height );
335
- init ();
336
- this .device .registerResourceWithZoomSupport (this );
327
+ this (device , bounds .width , bounds .height );
337
328
}
338
329
339
330
/**
@@ -1465,39 +1456,6 @@ public int hashCode () {
1465
1456
return (int )win32_getHandle (this , getZoom ());
1466
1457
}
1467
1458
1468
- void init (int width , int height ) {
1469
- if (width <= 0 || height <= 0 ) {
1470
- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
1471
- }
1472
- type = SWT .BITMAP ;
1473
- long hDC = device .internal_new_GC (null );
1474
- ImageHandle imageMetadata = new ImageHandle (OS .CreateCompatibleBitmap (hDC , width , height ), getZoom ());
1475
- /*
1476
- * Feature in Windows. CreateCompatibleBitmap() may fail
1477
- * for large images. The fix is to create a DIB section
1478
- * in that case.
1479
- */
1480
- if (imageMetadata .handle == 0 ) {
1481
- int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
1482
- int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
1483
- int depth = bits * planes ;
1484
- if (depth < 16 ) depth = 16 ;
1485
- if (depth > 24 ) depth = 24 ;
1486
- imageMetadata = new ImageHandle (createDIB (width , height , depth ), getZoom ());
1487
- }
1488
- if (imageMetadata .handle != 0 ) {
1489
- long memDC = OS .CreateCompatibleDC (hDC );
1490
- long hOldBitmap = OS .SelectObject (memDC , imageMetadata .handle );
1491
- OS .PatBlt (memDC , 0 , 0 , width , height , OS .PATCOPY );
1492
- OS .SelectObject (memDC , hOldBitmap );
1493
- OS .DeleteDC (memDC );
1494
- }
1495
- device .internal_dispose_GC (hDC , null );
1496
- if (imageMetadata .handle == 0 ) {
1497
- SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
1498
- }
1499
- }
1500
-
1501
1459
static long createDIB (int width , int height , int depth ) {
1502
1460
BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
1503
1461
bmiHeader .biSize = BITMAPINFOHEADER .sizeof ;
@@ -2089,13 +2047,122 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
2089
2047
}
2090
2048
2091
2049
private abstract class AbstractImageProviderWrapper {
2092
- abstract Object getProvider ();
2093
2050
protected abstract Rectangle getBounds (int zoom );
2094
2051
abstract ImageData getImageData (int zoom );
2095
2052
abstract ImageHandle getImageMetadata (int zoom );
2096
2053
abstract AbstractImageProviderWrapper createCopy (Image image );
2097
2054
abstract boolean isDisposed ();
2098
2055
2056
+ protected void destroy () {
2057
+ }
2058
+ }
2059
+
2060
+ private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
2061
+ private boolean isDestroyed ;
2062
+ private final int width ;
2063
+ private final int height ;
2064
+
2065
+ public PlainImageProviderWrapper (int width , int height ) {
2066
+ if (width <= 0 || height <= 0 ) {
2067
+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
2068
+ }
2069
+ this .width = width ;
2070
+ this .height = height ;
2071
+ type = SWT .BITMAP ;
2072
+ }
2073
+
2074
+
2075
+ @ Override
2076
+ protected Rectangle getBounds (int zoom ) {
2077
+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2078
+ return DPIUtil .scaleUp (rectangle , zoom );
2079
+ }
2080
+
2081
+ @ Override
2082
+ ImageData getImageData (int zoom ) {
2083
+ if (zoomLevelToImageHandle .isEmpty () || zoomLevelToImageHandle .containsKey (zoom )) {
2084
+ return getImageMetadata (zoom ).getImageData ();
2085
+ }
2086
+ // if a GC is initialized with an Image (memGC != null), the image data must not be resized, because it would
2087
+ // be a destructive operation. Therefor, always the current image data must be returned
2088
+ if (memGC != null ) {
2089
+ return getImageDataAtCurrentZoom ();
2090
+ }
2091
+ TreeSet <Integer > availableZooms = new TreeSet <>(zoomLevelToImageHandle .keySet ());
2092
+ int bestAvailableZoom = Optional .ofNullable (availableZooms .higher (zoom )).orElse (availableZooms .lower (zoom ));
2093
+ return DPIUtil .scaleImageData (device , getImageMetadata (bestAvailableZoom ).getImageData (), zoom , bestAvailableZoom );
2094
+ }
2095
+
2096
+ @ Override
2097
+ ImageHandle getImageMetadata (int zoom ) {
2098
+ if (zoomLevelToImageHandle .isEmpty ()) {
2099
+ long handle = initBaseHandle (zoom );
2100
+ ImageHandle imageHandle = new ImageHandle (handle , zoom );
2101
+ zoomLevelToImageHandle .put (zoom , imageHandle );
2102
+ return imageHandle ;
2103
+ } else if (zoomLevelToImageHandle .containsKey (zoom )) {
2104
+ return zoomLevelToImageHandle .get (zoom );
2105
+ } else {
2106
+ ImageData resizedData = getImageData (zoom );
2107
+ ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
2108
+ init (newData , zoom );
2109
+ return zoomLevelToImageHandle .get (zoom );
2110
+ }
2111
+ }
2112
+
2113
+ private long initBaseHandle (int zoom ) {
2114
+ int scaledWidth = DPIUtil .scaleUp (width , zoom );
2115
+ int scaledHeight = DPIUtil .scaleUp (height , zoom );
2116
+ long hDC = device .internal_new_GC (null );
2117
+ long newHandle ;
2118
+ newHandle = OS .CreateCompatibleBitmap (hDC , scaledWidth , scaledHeight );
2119
+ /*
2120
+ * Feature in Windows. CreateCompatibleBitmap() may fail
2121
+ * for large images. The fix is to create a DIB section
2122
+ * in that case.
2123
+ */
2124
+ if (newHandle == 0 ) {
2125
+ int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
2126
+ int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
2127
+ int depth = bits * planes ;
2128
+ if (depth < 16 ) depth = 16 ;
2129
+ if (depth > 24 ) depth = 24 ;
2130
+ newHandle = createDIB (scaledWidth , scaledHeight , depth );
2131
+ }
2132
+ if (newHandle != 0 ) {
2133
+ long memDC = OS .CreateCompatibleDC (hDC );
2134
+ long hOldBitmap = OS .SelectObject (memDC , newHandle );
2135
+ OS .PatBlt (memDC , 0 , 0 , scaledWidth , scaledHeight , OS .PATCOPY );
2136
+ OS .SelectObject (memDC , hOldBitmap );
2137
+ OS .DeleteDC (memDC );
2138
+ }
2139
+ device .internal_dispose_GC (hDC , null );
2140
+ if (newHandle == 0 ) {
2141
+ SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
2142
+ }
2143
+ return newHandle ;
2144
+ }
2145
+
2146
+ @ Override
2147
+ AbstractImageProviderWrapper createCopy (Image image ) {
2148
+ return image .new PlainImageProviderWrapper (width , height );
2149
+ }
2150
+
2151
+ @ Override
2152
+ protected void destroy () {
2153
+ this .isDestroyed = true ;
2154
+ }
2155
+
2156
+ @ Override
2157
+ boolean isDisposed () {
2158
+ return isDestroyed ;
2159
+ }
2160
+ }
2161
+
2162
+
2163
+ private abstract class DynamicImageProviderWrapper extends AbstractImageProviderWrapper {
2164
+ abstract Object getProvider ();
2165
+
2099
2166
protected void checkProvider (Object provider , Class <?> expectedClass ) {
2100
2167
if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
2101
2168
if (!expectedClass .isAssignableFrom (provider .getClass ())) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
@@ -2108,15 +2175,12 @@ public int hashCode() {
2108
2175
2109
2176
@ Override
2110
2177
public boolean equals (Object otherProvider ) {
2111
- return otherProvider instanceof AbstractImageProviderWrapper aip //
2112
- && getProvider ().equals (aip .getProvider ());
2113
- }
2114
-
2115
- protected void destroy () {
2178
+ return otherProvider instanceof DynamicImageProviderWrapper aip //
2179
+ && getProvider () != null && getProvider ().equals (aip .getProvider ());
2116
2180
}
2117
2181
}
2118
2182
2119
- private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
2183
+ private class ImageFileNameProviderWrapper extends DynamicImageProviderWrapper {
2120
2184
2121
2185
/**
2122
2186
* ImageFileNameProvider to provide file names at various Zoom levels
@@ -2179,7 +2243,7 @@ ImageFileNameProviderWrapper createCopy(Image image) {
2179
2243
}
2180
2244
}
2181
2245
2182
- private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2246
+ private class ImageDataProviderWrapper extends DynamicImageProviderWrapper {
2183
2247
2184
2248
/**
2185
2249
* ImageDataProvider to provide ImageData at various Zoom levels
@@ -2230,7 +2294,7 @@ ImageDataProviderWrapper createCopy(Image image) {
2230
2294
}
2231
2295
}
2232
2296
2233
- private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2297
+ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
2234
2298
private ImageGcDrawer drawer ;
2235
2299
private int width ;
2236
2300
private int height ;
0 commit comments