Skip to content

Commit 7c818d6

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Create ImageData based image handles on demand
This commit refactors the Image constructors using plain ImageData to create all handles on demand instead of creating a first handle in the constructor.
1 parent 329ed24 commit 7c818d6

File tree

1 file changed

+139
-15
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+139
-15
lines changed

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

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,7 @@ public Image(Device device, ImageData data) {
371371
super(device);
372372
if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
373373
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
374-
int deviceZoom = getZoom();
375-
data = scaleImageData(data, deviceZoom, 100);
376-
init(data, deviceZoom);
374+
this.imageProvider = new PlainImageDataProviderWrapper(data);
377375
init();
378376
this.device.registerResourceWithZoomSupport(this);
379377
}
@@ -416,10 +414,7 @@ public Image(Device device, ImageData source, ImageData mask) {
416414
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
417415
}
418416
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
419-
source = scaleImageData(source, getZoom(), 100);
420-
mask = scaleImageData(mask, getZoom(), 100);
421-
mask = ImageData.convertMask(mask);
422-
initIconHandle(this.device, source, mask, getZoom());
417+
this.imageProvider = new MaskedImageDataProviderWrapper(source, mask);
423418
init();
424419
this.device.registerResourceWithZoomSupport(this);
425420
}
@@ -479,11 +474,9 @@ public Image(Device device, ImageData source, ImageData mask) {
479474
*/
480475
public Image (Device device, InputStream stream) {
481476
super(device);
477+
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
482478
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
483-
int deviceZoom = getZoom();
484-
ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom);
485-
ImageData data = scaleImageData(imageCandidate.element(), deviceZoom, imageCandidate.zoom());
486-
init(data, deviceZoom);
479+
this.imageProvider = new ImageDataLoaderStreamProviderWrapper(stream);
487480
init();
488481
this.device.registerResourceWithZoomSupport(this);
489482
}
@@ -524,10 +517,16 @@ public Image (Device device, String filename) {
524517
super(device);
525518
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
526519
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
527-
int deviceZoom = getZoom();
528-
ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom);
529-
ImageData data = scaleImageData(imageCandidate.element(), deviceZoom, imageCandidate.zoom());
530-
init(data, deviceZoom);
520+
this.imageProvider = new ImageFileNameProviderWrapper(zoom -> {
521+
if (zoom == 100) {
522+
return filename;
523+
}
524+
return null;
525+
});
526+
if (imageProvider.getImageData(100) == null) {
527+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
528+
": [" + filename + "] returns null ImageData at 100% zoom.");
529+
}
531530
init();
532531
this.device.registerResourceWithZoomSupport(this);
533532
}
@@ -1947,6 +1946,131 @@ protected void destroy() {
19471946
}
19481947
}
19491948

1949+
private abstract class ImageFromImageDataProviderWrapper extends AbstractImageProviderWrapper {
1950+
1951+
protected abstract ElementAtZoom<ImageData> loadImageData(int zoom);
1952+
1953+
void initImage() {
1954+
// As the init call configured some Image attributes (e.g. type)
1955+
// it must be called
1956+
ImageData imageDataAt100 = getImageData(100);
1957+
init(imageDataAt100, 100);
1958+
destroyHandleForZoom(100);
1959+
}
1960+
1961+
@Override
1962+
ImageData getImageData(int zoom) {
1963+
if (zoomLevelToImageHandle.containsKey(zoom)) {
1964+
return zoomLevelToImageHandle.get(zoom).getImageData();
1965+
}
1966+
if (!zoomLevelToImageHandle.isEmpty()) {
1967+
return getScaledImageData(zoom);
1968+
}
1969+
ElementAtZoom<ImageData> loadedImageData = loadImageData(zoom);
1970+
return DPIUtil.scaleImageData(device, loadedImageData, zoom);
1971+
}
1972+
1973+
@Override
1974+
ImageHandle getImageMetadata(int zoom) {
1975+
if (zoomLevelToImageHandle.containsKey(zoom)) {
1976+
return zoomLevelToImageHandle.get(zoom);
1977+
} else {
1978+
ImageData scaledImageData = getImageData(zoom);
1979+
ImageHandle imageHandle = init(scaledImageData, zoom);
1980+
return imageHandle;
1981+
}
1982+
}
1983+
}
1984+
1985+
private class PlainImageDataProviderWrapper extends ImageFromImageDataProviderWrapper {
1986+
private ImageData imageDataAt100;
1987+
1988+
PlainImageDataProviderWrapper(ImageData imageData) {
1989+
this.imageDataAt100 = (ImageData) imageData.clone();
1990+
initImage();
1991+
}
1992+
1993+
@Override
1994+
protected Rectangle getBounds(int zoom) {
1995+
Rectangle rectangle = new Rectangle(0, 0, imageDataAt100.width, imageDataAt100.height);
1996+
return DPIUtil.scaleUp(rectangle, zoom);
1997+
}
1998+
1999+
@Override
2000+
protected ElementAtZoom<ImageData> loadImageData(int zoom) {
2001+
return new ElementAtZoom<>(imageDataAt100, 100);
2002+
}
2003+
2004+
@Override
2005+
AbstractImageProviderWrapper createCopy(Image image) {
2006+
return image.new PlainImageDataProviderWrapper(this.imageDataAt100);
2007+
}
2008+
}
2009+
2010+
private class MaskedImageDataProviderWrapper extends ImageFromImageDataProviderWrapper {
2011+
private final ImageData srcAt100;
2012+
private final ImageData maskAt100;
2013+
2014+
MaskedImageDataProviderWrapper(ImageData srcAt100, ImageData maskAt100) {
2015+
this.srcAt100 = (ImageData) srcAt100.clone();
2016+
this.maskAt100 = (ImageData) maskAt100.clone();
2017+
initImage();
2018+
}
2019+
2020+
@Override
2021+
protected Rectangle getBounds(int zoom) {
2022+
Rectangle rectangle = new Rectangle(0, 0, srcAt100.width, srcAt100.height);
2023+
return DPIUtil.scaleUp(rectangle, zoom);
2024+
}
2025+
2026+
@Override
2027+
protected ElementAtZoom<ImageData> loadImageData(int zoom) {
2028+
ImageData scaledSource = DPIUtil.scaleImageData(device, srcAt100, zoom, 100);
2029+
ImageData scaledMask = DPIUtil.scaleImageData(device, maskAt100, zoom, 100);
2030+
scaledMask = ImageData.convertMask(scaledMask);
2031+
ImageData mergedData = applyMask(scaledSource, scaledMask);
2032+
return new ElementAtZoom<>(mergedData, zoom);
2033+
}
2034+
2035+
@Override
2036+
AbstractImageProviderWrapper createCopy(Image image) {
2037+
return image.new MaskedImageDataProviderWrapper(this.srcAt100, this.maskAt100);
2038+
}
2039+
}
2040+
2041+
private class ImageDataLoaderStreamProviderWrapper extends ImageFromImageDataProviderWrapper {
2042+
private byte[] inputStreamData;
2043+
2044+
ImageDataLoaderStreamProviderWrapper(InputStream inputStream) {
2045+
try {
2046+
this.inputStreamData = inputStream.readAllBytes();
2047+
initImage();
2048+
} catch (IOException e) {
2049+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, e);
2050+
}
2051+
}
2052+
2053+
private ImageDataLoaderStreamProviderWrapper(byte[] inputStreamData) {
2054+
this.inputStreamData = inputStreamData;
2055+
}
2056+
2057+
@Override
2058+
protected ElementAtZoom<ImageData> loadImageData(int zoom) {
2059+
return ImageDataLoader.load(new ByteArrayInputStream(inputStreamData), FileFormat.DEFAULT_ZOOM, zoom);
2060+
}
2061+
2062+
@Override
2063+
protected Rectangle getBounds(int zoom) {
2064+
ImageData scaledImageData = getImageData(zoom);
2065+
return new Rectangle(0, 0, scaledImageData.width, scaledImageData.height);
2066+
}
2067+
2068+
@Override
2069+
AbstractImageProviderWrapper createCopy(Image image) {
2070+
return new ImageDataLoaderStreamProviderWrapper(inputStreamData);
2071+
}
2072+
}
2073+
19502074
private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
19512075
private final int width;
19522076
private final int height;

0 commit comments

Comments
 (0)