Skip to content

Commit 05dcf9f

Browse files
committed
[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 2974864 commit 05dcf9f

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
@@ -177,11 +177,8 @@ public Image(Device device, int width, int height) {
177177

178178
private 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-
14931461
static 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

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

Comments
 (0)