@@ -177,11 +177,8 @@ public Image(Device device, int width, int height) {
177177
178178private Image (Device device , int width , int height , int nativeZoom ) {
179179 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 );
185182 init ();
186183 this .device .registerResourceWithZoomSupport (this );
187184}
@@ -327,13 +324,7 @@ public Image(Device device, Image srcImage, int flag) {
327324 * @see #dispose()
328325 */
329326public 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 );
337328}
338329
339330/**
@@ -1465,39 +1456,6 @@ public int hashCode () {
14651456 return (int )win32_getHandle (this , getZoom ());
14661457}
14671458
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-
15011459static long createDIB (int width , int height , int depth ) {
15021460 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
15031461 bmiHeader .biSize = BITMAPINFOHEADER .sizeof ;
@@ -2089,13 +2047,122 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
20892047}
20902048
20912049private abstract class AbstractImageProviderWrapper {
2092- abstract Object getProvider ();
20932050 protected abstract Rectangle getBounds (int zoom );
20942051 abstract ImageData getImageData (int zoom );
20952052 abstract ImageHandle getImageMetadata (int zoom );
20962053 abstract AbstractImageProviderWrapper createCopy (Image image );
20972054 abstract boolean isDisposed ();
20982055
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+
20992166 protected void checkProvider (Object provider , Class <?> expectedClass ) {
21002167 if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
21012168 if (!expectedClass .isAssignableFrom (provider .getClass ())) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
@@ -2108,15 +2175,12 @@ public int hashCode() {
21082175
21092176 @ Override
21102177 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 ());
21162180 }
21172181}
21182182
2119- private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
2183+ private class ImageFileNameProviderWrapper extends DynamicImageProviderWrapper {
21202184
21212185 /**
21222186 * ImageFileNameProvider to provide file names at various Zoom levels
@@ -2179,7 +2243,7 @@ ImageFileNameProviderWrapper createCopy(Image image) {
21792243 }
21802244}
21812245
2182- private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2246+ private class ImageDataProviderWrapper extends DynamicImageProviderWrapper {
21832247
21842248 /**
21852249 * ImageDataProvider to provide ImageData at various Zoom levels
@@ -2230,7 +2294,7 @@ ImageDataProviderWrapper createCopy(Image image) {
22302294 }
22312295}
22322296
2233- private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2297+ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
22342298 private ImageGcDrawer drawer ;
22352299 private int width ;
22362300 private int height ;
0 commit comments