@@ -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}
@@ -330,8 +327,7 @@ public Image(Device device, Rectangle bounds) {
330327 super (device );
331328 if (bounds == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
332329 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
333- bounds = DPIUtil .scaleUp (bounds , getZoom ());
334- init (bounds .width , bounds .height );
330+ this .imageProvider = new PlainImageProviderWrapper (bounds .width , bounds .height );
335331 init ();
336332 this .device .registerResourceWithZoomSupport (this );
337333}
@@ -1405,6 +1401,10 @@ public ImageData getImageData (int zoom) {
14051401 return imageProvider .getImageData (zoom );
14061402 }
14071403
1404+ return getScaledImageData (zoom );
1405+ }
1406+
1407+ private ImageData getScaledImageData (int zoom ) {
14081408 // if a GC is initialized with an Image (memGC != null), the image data must not be resized, because it would
14091409 // be a destructive operation. Therefor, always the current image data must be returned
14101410 if (memGC != null ) {
@@ -1415,6 +1415,7 @@ public ImageData getImageData (int zoom) {
14151415 return DPIUtil .scaleImageData (device , getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
14161416}
14171417
1418+
14181419/**
14191420 * Returns an <code>ImageData</code> based on the receiver.
14201421 * Modifications made to this <code>ImageData</code> will not
@@ -1457,39 +1458,6 @@ public int hashCode () {
14571458 return (int )win32_getHandle (this , getZoom ());
14581459}
14591460
1460- void init (int width , int height ) {
1461- if (width <= 0 || height <= 0 ) {
1462- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
1463- }
1464- type = SWT .BITMAP ;
1465- long hDC = device .internal_new_GC (null );
1466- ImageHandle imageMetadata = new ImageHandle (OS .CreateCompatibleBitmap (hDC , width , height ), getZoom ());
1467- /*
1468- * Feature in Windows. CreateCompatibleBitmap() may fail
1469- * for large images. The fix is to create a DIB section
1470- * in that case.
1471- */
1472- if (imageMetadata .handle == 0 ) {
1473- int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
1474- int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
1475- int depth = bits * planes ;
1476- if (depth < 16 ) depth = 16 ;
1477- if (depth > 24 ) depth = 24 ;
1478- imageMetadata = new ImageHandle (createDIB (width , height , depth ), getZoom ());
1479- }
1480- if (imageMetadata .handle != 0 ) {
1481- long memDC = OS .CreateCompatibleDC (hDC );
1482- long hOldBitmap = OS .SelectObject (memDC , imageMetadata .handle );
1483- OS .PatBlt (memDC , 0 , 0 , width , height , OS .PATCOPY );
1484- OS .SelectObject (memDC , hOldBitmap );
1485- OS .DeleteDC (memDC );
1486- }
1487- device .internal_dispose_GC (hDC , null );
1488- if (imageMetadata .handle == 0 ) {
1489- SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
1490- }
1491- }
1492-
14931461static long createDIB (int width , int height , int depth ) {
14941462 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
14951463 bmiHeader .biSize = BITMAPINFOHEADER .sizeof ;
@@ -2081,13 +2049,114 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
20812049}
20822050
20832051private abstract class AbstractImageProviderWrapper {
2084- abstract Object getProvider ();
20852052 protected abstract Rectangle getBounds (int zoom );
20862053 abstract ImageData getImageData (int zoom );
20872054 abstract ImageHandle getImageMetadata (int zoom );
20882055 abstract AbstractImageProviderWrapper createCopy (Image image );
20892056 abstract boolean isDisposed ();
20902057
2058+ protected void destroy () {
2059+ }
2060+ }
2061+
2062+ private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
2063+ private boolean isDestroyed ;
2064+ private final int width ;
2065+ private final int height ;
2066+
2067+ PlainImageProviderWrapper (int width , int height ) {
2068+ if (width <= 0 || height <= 0 ) {
2069+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
2070+ }
2071+ this .width = width ;
2072+ this .height = height ;
2073+ type = SWT .BITMAP ;
2074+ }
2075+
2076+ @ Override
2077+ protected Rectangle getBounds (int zoom ) {
2078+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2079+ return DPIUtil .scaleUp (rectangle , zoom );
2080+ }
2081+
2082+ @ Override
2083+ ImageData getImageData (int zoom ) {
2084+ if (zoomLevelToImageHandle .isEmpty () || zoomLevelToImageHandle .containsKey (zoom )) {
2085+ return getImageMetadata (zoom ).getImageData ();
2086+ }
2087+
2088+ return getScaledImageData (zoom );
2089+ }
2090+
2091+ @ Override
2092+ ImageHandle getImageMetadata (int zoom ) {
2093+ if (zoomLevelToImageHandle .isEmpty ()) {
2094+ long handle = initBaseHandle (zoom );
2095+ ImageHandle imageHandle = new ImageHandle (handle , zoom );
2096+ zoomLevelToImageHandle .put (zoom , imageHandle );
2097+ return imageHandle ;
2098+ } else if (zoomLevelToImageHandle .containsKey (zoom )) {
2099+ return zoomLevelToImageHandle .get (zoom );
2100+ } else {
2101+ ImageData resizedData = getImageData (zoom );
2102+ ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
2103+ init (newData , zoom );
2104+ return zoomLevelToImageHandle .get (zoom );
2105+ }
2106+ }
2107+
2108+ private long initBaseHandle (int zoom ) {
2109+ if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
2110+ int scaledWidth = DPIUtil .scaleUp (width , zoom );
2111+ int scaledHeight = DPIUtil .scaleUp (height , zoom );
2112+ long hDC = device .internal_new_GC (null );
2113+ long newHandle = OS .CreateCompatibleBitmap (hDC , scaledWidth , scaledHeight );
2114+ /*
2115+ * Feature in Windows. CreateCompatibleBitmap() may fail
2116+ * for large images. The fix is to create a DIB section
2117+ * in that case.
2118+ */
2119+ if (newHandle == 0 ) {
2120+ int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
2121+ int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
2122+ int depth = bits * planes ;
2123+ if (depth < 16 ) depth = 16 ;
2124+ if (depth > 24 ) depth = 24 ;
2125+ newHandle = createDIB (scaledWidth , scaledHeight , depth );
2126+ }
2127+ if (newHandle != 0 ) {
2128+ long memDC = OS .CreateCompatibleDC (hDC );
2129+ long hOldBitmap = OS .SelectObject (memDC , newHandle );
2130+ OS .PatBlt (memDC , 0 , 0 , scaledWidth , scaledHeight , OS .PATCOPY );
2131+ OS .SelectObject (memDC , hOldBitmap );
2132+ OS .DeleteDC (memDC );
2133+ }
2134+ device .internal_dispose_GC (hDC , null );
2135+ if (newHandle == 0 ) {
2136+ SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
2137+ }
2138+ return newHandle ;
2139+ }
2140+
2141+ @ Override
2142+ AbstractImageProviderWrapper createCopy (Image image ) {
2143+ return image .new PlainImageProviderWrapper (width , height );
2144+ }
2145+
2146+ @ Override
2147+ protected void destroy () {
2148+ this .isDestroyed = true ;
2149+ }
2150+
2151+ @ Override
2152+ boolean isDisposed () {
2153+ return isDestroyed ;
2154+ }
2155+ }
2156+
2157+ private abstract class DynamicImageProviderWrapper extends AbstractImageProviderWrapper {
2158+ abstract Object getProvider ();
2159+
20912160 protected void checkProvider (Object provider , Class <?> expectedClass ) {
20922161 if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
20932162 if (!expectedClass .isAssignableFrom (provider .getClass ())) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
@@ -2100,15 +2169,12 @@ public int hashCode() {
21002169
21012170 @ Override
21022171 public boolean equals (Object otherProvider ) {
2103- return otherProvider instanceof AbstractImageProviderWrapper aip //
2104- && getProvider ().equals (aip .getProvider ());
2105- }
2106-
2107- protected void destroy () {
2172+ return otherProvider instanceof DynamicImageProviderWrapper aip
2173+ && Objects .equals (getProvider (), aip .getProvider ());
21082174 }
21092175}
21102176
2111- private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
2177+ private class ImageFileNameProviderWrapper extends DynamicImageProviderWrapper {
21122178
21132179 /**
21142180 * ImageFileNameProvider to provide file names at various Zoom levels
@@ -2172,7 +2238,7 @@ ImageFileNameProviderWrapper createCopy(Image image) {
21722238 }
21732239}
21742240
2175- private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2241+ private class ImageDataProviderWrapper extends DynamicImageProviderWrapper {
21762242
21772243 /**
21782244 * ImageDataProvider to provide ImageData at various Zoom levels
@@ -2222,13 +2288,13 @@ ImageDataProviderWrapper createCopy(Image image) {
22222288 }
22232289}
22242290
2225- private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2291+ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
22262292 private ImageGcDrawer drawer ;
22272293 private int width ;
22282294 private int height ;
22292295 private boolean isDestroyed ;
22302296
2231- public ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
2297+ ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
22322298 checkProvider (imageGcDrawer , ImageGcDrawer .class );
22332299 this .drawer = imageGcDrawer ;
22342300 this .width = width ;
0 commit comments