Skip to content

Commit eb8637e

Browse files
committed
[Win32] Ensure consistent image data returned for data-based images
Due to the on-demand creation of image handles, there is not necessarily a handles anymore from which image data is retrieved when requesting is via the getImageData(...) methods. This results in potentially different kinds of image data (including different anti-aliasing results) depending on whether a handle has already been created for an image at the given zoom or not. This change adapts the implementation of Image based on static ImageData and streams to always use the image data retrieved from a native handle. To this end, it temporarily creates a handle if necessary. In order to avoid repeated loading and handle creation for the same source of image, a cache for the already retrieved image data is introduced.
1 parent 6a2b931 commit eb8637e

File tree

2 files changed

+49
-24
lines changed

2 files changed

+49
-24
lines changed

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

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,11 +1251,7 @@ public ImageData getImageData (int zoom) {
12511251
if (zoomLevelToImageHandle.containsKey(zoom)) {
12521252
return zoomLevelToImageHandle.get(zoom).getImageData();
12531253
}
1254-
if (imageProvider != null) {
1255-
return imageProvider.getImageData(zoom);
1256-
}
1257-
1258-
return getScaledImageData(zoom);
1254+
return imageProvider.getImageData(zoom);
12591255
}
12601256

12611257
private ImageData getScaledImageData (int zoom) {
@@ -1948,39 +1944,43 @@ protected void destroy() {
19481944
}
19491945

19501946
private abstract class ImageFromImageDataProviderWrapper extends AbstractImageProviderWrapper {
1947+
private final Map<Integer, ImageData> cachedImageData = new HashMap<>();
19511948

19521949
protected abstract ElementAtZoom<ImageData> loadImageData(int zoom);
19531950

19541951
void initImage() {
19551952
// As the init call configured some Image attributes (e.g. type)
19561953
// it must be called
1957-
ImageData imageDataAt100 = getImageData(100);
1958-
init(imageDataAt100, 100);
1959-
destroyHandleForZoom(100);
1954+
getImageData(100);
19601955
}
19611956

19621957
@Override
1963-
ImageData getImageData(int zoom) {
1964-
if (zoomLevelToImageHandle.containsKey(zoom)) {
1965-
return zoomLevelToImageHandle.get(zoom).getImageData();
1966-
}
1967-
if (!zoomLevelToImageHandle.isEmpty()) {
1968-
return getScaledImageData(zoom);
1969-
}
1970-
ElementAtZoom<ImageData> loadedImageData = loadImageData(zoom);
1971-
return DPIUtil.scaleImageData(device, loadedImageData, zoom);
1958+
final ImageData getImageData(int zoom) {
1959+
Function<Integer, ImageData> imageDataRetrival = zoomToRetrieve -> {
1960+
ImageHandle handle = initializeHandleFromSource(zoomToRetrieve);
1961+
ImageData data = handle.getImageData();
1962+
destroyHandleForZoom(zoomToRetrieve);
1963+
return data;
1964+
};
1965+
return cachedImageData.computeIfAbsent(zoom, imageDataRetrival);
19721966
}
19731967

19741968
@Override
1975-
ImageHandle getImageMetadata(int zoom) {
1976-
if (zoomLevelToImageHandle.containsKey(zoom)) {
1977-
return zoomLevelToImageHandle.get(zoom);
1978-
} else {
1979-
ImageData scaledImageData = getImageData(zoom);
1980-
ImageHandle imageHandle = init(scaledImageData, zoom);
1981-
return imageHandle;
1969+
final ImageHandle getImageMetadata(int zoom) {
1970+
ImageData cachedData = cachedImageData.remove(zoom);
1971+
if (cachedData != null) {
1972+
return init(cachedData, zoom);
19821973
}
1974+
return initializeHandleFromSource(zoom);
19831975
}
1976+
1977+
private ImageHandle initializeHandleFromSource(int zoom) {
1978+
ElementAtZoom<ImageData> imageDataAtZoom = loadImageData(zoom);
1979+
ImageData imageData = scaleImageData(imageDataAtZoom.element(), zoom, imageDataAtZoom.zoom());
1980+
imageData = adaptImageDataIfDisabledOrGray(imageData);
1981+
return init(imageData, zoom);
1982+
}
1983+
19841984
}
19851985

19861986
private class PlainImageDataProviderWrapper extends ImageFromImageDataProviderWrapper {

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Image.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,31 @@ public void test_imageDataSameViaDifferentProviders() {
13041304
dataProviderImage.dispose();
13051305
}
13061306

1307+
@Test
1308+
public void test_imageDataSameViaProviderAndSimpleData() {
1309+
assumeFalse("Cocoa generates inconsistent image data", SwtTestUtil.isCocoa);
1310+
String imagePath = getPath("collapseall.png");
1311+
ImageFileNameProvider imageFileNameProvider = __ -> {
1312+
return imagePath;
1313+
};
1314+
ImageDataProvider dataProvider = __ -> {
1315+
try (InputStream imageStream = Files.newInputStream(Path.of(imagePath))) {
1316+
return new ImageData(imageStream);
1317+
} catch (IOException e) {
1318+
}
1319+
return null;
1320+
};
1321+
Image fileNameProviderImage = new Image(display, imageFileNameProvider);
1322+
Image dataImage = new Image(display, dataProvider.getImageData(100));
1323+
ImageData dataFromFileNameProviderImage = fileNameProviderImage.getImageData(100);
1324+
ImageData dataFromImageWithSimpleData = dataImage.getImageData(100);
1325+
assertEquals(0, imageDataComparator().compare(dataFromFileNameProviderImage, dataFromImageWithSimpleData));
1326+
1327+
fileNameProviderImage.dispose();
1328+
dataImage.dispose();
1329+
}
1330+
1331+
13071332
private Comparator<ImageData> imageDataComparator() {
13081333
return Comparator.<ImageData>comparingInt(d -> d.width) //
13091334
.thenComparing(d -> d.height) //

0 commit comments

Comments
 (0)