@@ -178,11 +178,8 @@ public Image(Device device, int width, int height) {
178178
179179private Image (Device device , int width , int height , int nativeZoom ) {
180180 super (device );
181- initialNativeZoom = nativeZoom ;
182- final int zoom = getZoom ();
183- width = DPIUtil .scaleUp (width , zoom );
184- height = DPIUtil .scaleUp (height , zoom );
185- init (width , height );
181+ this .initialNativeZoom = nativeZoom ;
182+ this .imageProvider = new PlainImageProviderWrapper (width , height );
186183 init ();
187184 this .device .registerResourceWithZoomSupport (this );
188185}
@@ -331,8 +328,7 @@ public Image(Device device, Rectangle bounds) {
331328 super (device );
332329 if (bounds == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
333330 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
334- bounds = DPIUtil .scaleUp (bounds , getZoom ());
335- init (bounds .width , bounds .height );
331+ this .imageProvider = new PlainImageProviderWrapper (bounds .width , bounds .height );
336332 init ();
337333 this .device .registerResourceWithZoomSupport (this );
338334}
@@ -1406,6 +1402,10 @@ public ImageData getImageData (int zoom) {
14061402 return imageProvider .getImageData (zoom );
14071403 }
14081404
1405+ return getScaledImageData (zoom );
1406+ }
1407+
1408+ private ImageData getScaledImageData (int zoom ) {
14091409 // if a GC is initialized with an Image (memGC != null), the image data must not be resized, because it would
14101410 // be a destructive operation. Therefor, always the current image data must be returned
14111411 if (memGC != null ) {
@@ -1416,6 +1416,7 @@ public ImageData getImageData (int zoom) {
14161416 return DPIUtil .scaleImageData (device , getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
14171417}
14181418
1419+
14191420/**
14201421 * Returns an <code>ImageData</code> based on the receiver.
14211422 * Modifications made to this <code>ImageData</code> will not
@@ -1458,39 +1459,6 @@ public int hashCode () {
14581459 return (int )win32_getHandle (this , getZoom ());
14591460}
14601461
1461- void init (int width , int height ) {
1462- if (width <= 0 || height <= 0 ) {
1463- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
1464- }
1465- type = SWT .BITMAP ;
1466- long hDC = device .internal_new_GC (null );
1467- ImageHandle imageMetadata = new ImageHandle (OS .CreateCompatibleBitmap (hDC , width , height ), getZoom ());
1468- /*
1469- * Feature in Windows. CreateCompatibleBitmap() may fail
1470- * for large images. The fix is to create a DIB section
1471- * in that case.
1472- */
1473- if (imageMetadata .handle == 0 ) {
1474- int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
1475- int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
1476- int depth = bits * planes ;
1477- if (depth < 16 ) depth = 16 ;
1478- if (depth > 24 ) depth = 24 ;
1479- imageMetadata = new ImageHandle (createDIB (width , height , depth ), getZoom ());
1480- }
1481- if (imageMetadata .handle != 0 ) {
1482- long memDC = OS .CreateCompatibleDC (hDC );
1483- long hOldBitmap = OS .SelectObject (memDC , imageMetadata .handle );
1484- OS .PatBlt (memDC , 0 , 0 , width , height , OS .PATCOPY );
1485- OS .SelectObject (memDC , hOldBitmap );
1486- OS .DeleteDC (memDC );
1487- }
1488- device .internal_dispose_GC (hDC , null );
1489- if (imageMetadata .handle == 0 ) {
1490- SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
1491- }
1492- }
1493-
14941462static long createDIB (int width , int height , int depth ) {
14951463 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
14961464 bmiHeader .biSize = BITMAPINFOHEADER .sizeof ;
@@ -2082,13 +2050,114 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
20822050}
20832051
20842052private abstract class AbstractImageProviderWrapper {
2085- abstract Object getProvider ();
20862053 protected abstract Rectangle getBounds (int zoom );
20872054 abstract ImageData getImageData (int zoom );
20882055 abstract ImageHandle getImageMetadata (int zoom );
20892056 abstract AbstractImageProviderWrapper createCopy (Image image );
20902057 abstract boolean isDisposed ();
20912058
2059+ protected void destroy () {
2060+ }
2061+ }
2062+
2063+ private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
2064+ private boolean isDestroyed ;
2065+ private final int width ;
2066+ private final int height ;
2067+
2068+ PlainImageProviderWrapper (int width , int height ) {
2069+ if (width <= 0 || height <= 0 ) {
2070+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
2071+ }
2072+ this .width = width ;
2073+ this .height = height ;
2074+ type = SWT .BITMAP ;
2075+ }
2076+
2077+ @ Override
2078+ protected Rectangle getBounds (int zoom ) {
2079+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2080+ return DPIUtil .scaleUp (rectangle , zoom );
2081+ }
2082+
2083+ @ Override
2084+ ImageData getImageData (int zoom ) {
2085+ if (zoomLevelToImageHandle .isEmpty () || zoomLevelToImageHandle .containsKey (zoom )) {
2086+ return getImageMetadata (zoom ).getImageData ();
2087+ }
2088+
2089+ return getScaledImageData (zoom );
2090+ }
2091+
2092+ @ Override
2093+ ImageHandle getImageMetadata (int zoom ) {
2094+ if (zoomLevelToImageHandle .isEmpty ()) {
2095+ long handle = initBaseHandle (zoom );
2096+ ImageHandle imageHandle = new ImageHandle (handle , zoom );
2097+ zoomLevelToImageHandle .put (zoom , imageHandle );
2098+ return imageHandle ;
2099+ } else if (zoomLevelToImageHandle .containsKey (zoom )) {
2100+ return zoomLevelToImageHandle .get (zoom );
2101+ } else {
2102+ ImageData resizedData = getImageData (zoom );
2103+ ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
2104+ init (newData , zoom );
2105+ return zoomLevelToImageHandle .get (zoom );
2106+ }
2107+ }
2108+
2109+ private long initBaseHandle (int zoom ) {
2110+ if (isDisposed ()) SWT .error (SWT .ERROR_GRAPHIC_DISPOSED );
2111+ int scaledWidth = DPIUtil .scaleUp (width , zoom );
2112+ int scaledHeight = DPIUtil .scaleUp (height , zoom );
2113+ long hDC = device .internal_new_GC (null );
2114+ long newHandle = OS .CreateCompatibleBitmap (hDC , scaledWidth , scaledHeight );
2115+ /*
2116+ * Feature in Windows. CreateCompatibleBitmap() may fail
2117+ * for large images. The fix is to create a DIB section
2118+ * in that case.
2119+ */
2120+ if (newHandle == 0 ) {
2121+ int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
2122+ int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
2123+ int depth = bits * planes ;
2124+ if (depth < 16 ) depth = 16 ;
2125+ if (depth > 24 ) depth = 24 ;
2126+ newHandle = createDIB (scaledWidth , scaledHeight , depth );
2127+ }
2128+ if (newHandle != 0 ) {
2129+ long memDC = OS .CreateCompatibleDC (hDC );
2130+ long hOldBitmap = OS .SelectObject (memDC , newHandle );
2131+ OS .PatBlt (memDC , 0 , 0 , scaledWidth , scaledHeight , OS .PATCOPY );
2132+ OS .SelectObject (memDC , hOldBitmap );
2133+ OS .DeleteDC (memDC );
2134+ }
2135+ device .internal_dispose_GC (hDC , null );
2136+ if (newHandle == 0 ) {
2137+ SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
2138+ }
2139+ return newHandle ;
2140+ }
2141+
2142+ @ Override
2143+ AbstractImageProviderWrapper createCopy (Image image ) {
2144+ return image .new PlainImageProviderWrapper (width , height );
2145+ }
2146+
2147+ @ Override
2148+ protected void destroy () {
2149+ this .isDestroyed = true ;
2150+ }
2151+
2152+ @ Override
2153+ boolean isDisposed () {
2154+ return isDestroyed ;
2155+ }
2156+ }
2157+
2158+ private abstract class DynamicImageProviderWrapper extends AbstractImageProviderWrapper {
2159+ abstract Object getProvider ();
2160+
20922161 protected void checkProvider (Object provider , Class <?> expectedClass ) {
20932162 if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
20942163 if (!expectedClass .isAssignableFrom (provider .getClass ())) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
@@ -2101,15 +2170,12 @@ public int hashCode() {
21012170
21022171 @ Override
21032172 public boolean equals (Object otherProvider ) {
2104- return otherProvider instanceof AbstractImageProviderWrapper aip //
2105- && getProvider ().equals (aip .getProvider ());
2106- }
2107-
2108- protected void destroy () {
2173+ return otherProvider instanceof DynamicImageProviderWrapper aip
2174+ && Objects .equals (getProvider (), aip .getProvider ());
21092175 }
21102176}
21112177
2112- private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
2178+ private class ImageFileNameProviderWrapper extends DynamicImageProviderWrapper {
21132179
21142180 /**
21152181 * ImageFileNameProvider to provide file names at various Zoom levels
@@ -2175,7 +2241,7 @@ ImageFileNameProviderWrapper createCopy(Image image) {
21752241 }
21762242}
21772243
2178- private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2244+ private class ImageDataProviderWrapper extends DynamicImageProviderWrapper {
21792245
21802246 /**
21812247 * ImageDataProvider to provide ImageData at various Zoom levels
@@ -2225,13 +2291,13 @@ ImageDataProviderWrapper createCopy(Image image) {
22252291 }
22262292}
22272293
2228- private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2294+ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
22292295 private ImageGcDrawer drawer ;
22302296 private int width ;
22312297 private int height ;
22322298 private boolean isDestroyed ;
22332299
2234- public ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
2300+ ImageGcDrawerWrapper (ImageGcDrawer imageGcDrawer , int width , int height ) {
22352301 checkProvider (imageGcDrawer , ImageGcDrawer .class );
22362302 this .drawer = imageGcDrawer ;
22372303 this .width = width ;
0 commit comments