Skip to content

Commit 0a0b40c

Browse files
akoch-yattafedejeanne
authored andcommitted
[win32] Create plain image handles on demand
This commit refactors the Image constructor using width and height to create a bitmap to create handles on demand instead of creating a first handle in the constructor.
1 parent 17948a7 commit 0a0b40c

File tree

1 file changed

+116
-50
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+116
-50
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,8 @@ public Image(Device device, int width, int height) {
178178

179179
private 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-
14941462
static 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

20842052
private 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

Comments
 (0)