@@ -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}
@@ -1457,39 +1453,6 @@ public int hashCode () {
14571453 return (int )win32_getHandle (this , getZoom ());
14581454}
14591455
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-
14931456static long createDIB (int width , int height , int depth ) {
14941457 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
14951458 bmiHeader .biSize = BITMAPINFOHEADER .sizeof ;
@@ -2081,13 +2044,122 @@ public static Image win32_new(Device device, int type, long handle, int nativeZo
20812044}
20822045
20832046private abstract class AbstractImageProviderWrapper {
2084- abstract Object getProvider ();
20852047 protected abstract Rectangle getBounds (int zoom );
20862048 abstract ImageData getImageData (int zoom );
20872049 abstract ImageHandle getImageMetadata (int zoom );
20882050 abstract AbstractImageProviderWrapper createCopy (Image image );
20892051 abstract boolean isDisposed ();
20902052
2053+ protected void destroy () {
2054+ }
2055+ }
2056+
2057+ private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
2058+ private boolean isDestroyed ;
2059+ private final int width ;
2060+ private final int height ;
2061+
2062+ public PlainImageProviderWrapper (int width , int height ) {
2063+ if (width <= 0 || height <= 0 ) {
2064+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
2065+ }
2066+ this .width = width ;
2067+ this .height = height ;
2068+ type = SWT .BITMAP ;
2069+ }
2070+
2071+
2072+ @ Override
2073+ protected Rectangle getBounds (int zoom ) {
2074+ Rectangle rectangle = new Rectangle (0 , 0 , width , height );
2075+ return DPIUtil .scaleUp (rectangle , zoom );
2076+ }
2077+
2078+ @ Override
2079+ ImageData getImageData (int zoom ) {
2080+ if (zoomLevelToImageHandle .isEmpty () || zoomLevelToImageHandle .containsKey (zoom )) {
2081+ return getImageMetadata (zoom ).getImageData ();
2082+ }
2083+ // if a GC is initialized with an Image (memGC != null), the image data must not be resized, because it would
2084+ // be a destructive operation. Therefor, always the current image data must be returned
2085+ if (memGC != null ) {
2086+ return getImageDataAtCurrentZoom ();
2087+ }
2088+ TreeSet <Integer > availableZooms = new TreeSet <>(zoomLevelToImageHandle .keySet ());
2089+ int bestAvailableZoom = Optional .ofNullable (availableZooms .higher (zoom )).orElse (availableZooms .lower (zoom ));
2090+ return DPIUtil .scaleImageData (device , getImageMetadata (bestAvailableZoom ).getImageData (), zoom , bestAvailableZoom );
2091+ }
2092+
2093+ @ Override
2094+ ImageHandle getImageMetadata (int zoom ) {
2095+ if (zoomLevelToImageHandle .isEmpty ()) {
2096+ long handle = initBaseHandle (zoom );
2097+ ImageHandle imageHandle = new ImageHandle (handle , zoom );
2098+ zoomLevelToImageHandle .put (zoom , imageHandle );
2099+ return imageHandle ;
2100+ } else if (zoomLevelToImageHandle .containsKey (zoom )) {
2101+ return zoomLevelToImageHandle .get (zoom );
2102+ } else {
2103+ ImageData resizedData = getImageData (zoom );
2104+ ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
2105+ init (newData , zoom );
2106+ return zoomLevelToImageHandle .get (zoom );
2107+ }
2108+ }
2109+
2110+ private long initBaseHandle (int zoom ) {
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 ;
2115+ newHandle = OS .CreateCompatibleBitmap (hDC , scaledWidth , scaledHeight );
2116+ /*
2117+ * Feature in Windows. CreateCompatibleBitmap() may fail
2118+ * for large images. The fix is to create a DIB section
2119+ * in that case.
2120+ */
2121+ if (newHandle == 0 ) {
2122+ int bits = OS .GetDeviceCaps (hDC , OS .BITSPIXEL );
2123+ int planes = OS .GetDeviceCaps (hDC , OS .PLANES );
2124+ int depth = bits * planes ;
2125+ if (depth < 16 ) depth = 16 ;
2126+ if (depth > 24 ) depth = 24 ;
2127+ newHandle = createDIB (scaledWidth , scaledHeight , depth );
2128+ }
2129+ if (newHandle != 0 ) {
2130+ long memDC = OS .CreateCompatibleDC (hDC );
2131+ long hOldBitmap = OS .SelectObject (memDC , newHandle );
2132+ OS .PatBlt (memDC , 0 , 0 , scaledWidth , scaledHeight , OS .PATCOPY );
2133+ OS .SelectObject (memDC , hOldBitmap );
2134+ OS .DeleteDC (memDC );
2135+ }
2136+ device .internal_dispose_GC (hDC , null );
2137+ if (newHandle == 0 ) {
2138+ SWT .error (SWT .ERROR_NO_HANDLES , null , device .getLastError ());
2139+ }
2140+ return newHandle ;
2141+ }
2142+
2143+ @ Override
2144+ AbstractImageProviderWrapper createCopy (Image image ) {
2145+ return image .new PlainImageProviderWrapper (width , height );
2146+ }
2147+
2148+ @ Override
2149+ protected void destroy () {
2150+ this .isDestroyed = true ;
2151+ }
2152+
2153+ @ Override
2154+ boolean isDisposed () {
2155+ return isDestroyed ;
2156+ }
2157+ }
2158+
2159+
2160+ private abstract class DynamicImageProviderWrapper extends AbstractImageProviderWrapper {
2161+ abstract Object getProvider ();
2162+
20912163 protected void checkProvider (Object provider , Class <?> expectedClass ) {
20922164 if (provider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
20932165 if (!expectedClass .isAssignableFrom (provider .getClass ())) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
@@ -2100,15 +2172,12 @@ public int hashCode() {
21002172
21012173 @ Override
21022174 public boolean equals (Object otherProvider ) {
2103- return otherProvider instanceof AbstractImageProviderWrapper aip //
2104- && getProvider ().equals (aip .getProvider ());
2105- }
2106-
2107- protected void destroy () {
2175+ return otherProvider instanceof DynamicImageProviderWrapper aip //
2176+ && getProvider () != null && getProvider ().equals (aip .getProvider ());
21082177 }
21092178}
21102179
2111- private class ImageFileNameProviderWrapper extends AbstractImageProviderWrapper {
2180+ private class ImageFileNameProviderWrapper extends DynamicImageProviderWrapper {
21122181
21132182 /**
21142183 * ImageFileNameProvider to provide file names at various Zoom levels
@@ -2172,7 +2241,7 @@ ImageFileNameProviderWrapper createCopy(Image image) {
21722241 }
21732242}
21742243
2175- private class ImageDataProviderWrapper extends AbstractImageProviderWrapper {
2244+ private class ImageDataProviderWrapper extends DynamicImageProviderWrapper {
21762245
21772246 /**
21782247 * ImageDataProvider to provide ImageData at various Zoom levels
@@ -2222,7 +2291,7 @@ ImageDataProviderWrapper createCopy(Image image) {
22222291 }
22232292}
22242293
2225- private class ImageGcDrawerWrapper extends AbstractImageProviderWrapper {
2294+ private class ImageGcDrawerWrapper extends DynamicImageProviderWrapper {
22262295 private ImageGcDrawer drawer ;
22272296 private int width ;
22282297 private int height ;
0 commit comments