Skip to content

Commit 4ad1d7b

Browse files
committed
Allow to test for loading image at zoom
The ImageLoader and FileFormat implementations currently combine the check whether an image can be provided at a specific scale value and the provision of an image in the scale itself. In case a consumer wants to test whether an image can be provided at a specific scale, it needs to request that image at that scale, even if it will not be used later one, e.g., because it cannot be provided in the required scale. With this change, ImageLoader and FileFormat provide separate methods for validating whether an image can be retrieved at a specific zoom (such as from an SVG) and the retrieval of the image itself.
1 parent 3670670 commit 4ad1d7b

File tree

9 files changed

+95
-43
lines changed

9 files changed

+95
-43
lines changed

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

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import org.eclipse.swt.*;
2222
import org.eclipse.swt.internal.*;
23-
import org.eclipse.swt.internal.DPIUtil.*;
2423
import org.eclipse.swt.internal.cocoa.*;
2524
import org.eclipse.swt.internal.graphics.*;
2625
import org.eclipse.swt.internal.image.*;
@@ -695,7 +694,8 @@ public Image(Device device, InputStream stream) {
695694
NSAutoreleasePool pool = null;
696695
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
697696
try {
698-
initWithSupplier(zoom -> ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, zoom));
697+
initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(stream, FileFormat.DEFAULT_ZOOM, zoom),
698+
zoom -> ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, zoom).element());
699699
init();
700700
} finally {
701701
if (pool != null) pool.release();
@@ -741,7 +741,10 @@ public Image(Device device, String filename) {
741741
try {
742742
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
743743
initNative(filename);
744-
if (this.handle == null) initWithSupplier(zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom));
744+
if (this.handle == null) {
745+
initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(filename, FileFormat.DEFAULT_ZOOM, zoom),
746+
zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom).element());
747+
}
745748
init();
746749
} finally {
747750
if (pool != null) pool.release();
@@ -795,15 +798,13 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
795798
id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(filename2x));
796799
NSImageRep rep = new NSImageRep(id);
797800
handle.addRepresentation(rep);
798-
} else {
801+
} else if (ImageDataLoader.canLoadAtZoom(filename, 100, 200)) {
799802
// Try to natively scale up the image (e.g. possible if it's an SVG)
800-
ElementAtZoom<ImageData> imageData2x = ImageDataLoader.load(filename, 100, 200);
801-
if (imageData2x.zoom() == 200) {
802-
alphaInfo_200 = new AlphaInfo();
803-
NSBitmapImageRep rep = createRepresentation (imageData2x.element(), alphaInfo_200);
804-
handle.addRepresentation(rep);
805-
rep.release();
806-
}
803+
ImageData imageData2x = ImageDataLoader.load(filename, 100, 200).element();
804+
alphaInfo_200 = new AlphaInfo();
805+
NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200);
806+
handle.addRepresentation(rep);
807+
rep.release();
807808
}
808809
} finally {
809810
if (pool != null) pool.release();
@@ -1484,17 +1485,11 @@ void init(ImageData image) {
14841485
handle.setCacheMode(OS.NSImageCacheNever);
14851486
}
14861487

1487-
private void initWithSupplier(Function<Integer, ElementAtZoom<ImageData>> zoomToImageData) {
1488-
ElementAtZoom<ImageData> imageData = zoomToImageData.apply(DPIUtil.getDeviceZoom());
1489-
ImageData imageData2x = null;
1490-
if (imageData.zoom() == 200) {
1491-
imageData2x = imageData.element();
1492-
}
1493-
if (imageData.zoom() != 100) {
1494-
imageData = zoomToImageData.apply(100);
1495-
}
1496-
init(imageData.element());
1497-
if (imageData2x != null) {
1488+
private void initWithSupplier(Function<Integer, Boolean> canLoadAtZoom, Function<Integer, ImageData> zoomToImageData) {
1489+
ImageData imageData = zoomToImageData.apply(100);
1490+
init(imageData);
1491+
if (canLoadAtZoom.apply(200)) {
1492+
ImageData imageData2x = zoomToImageData.apply(200);
14981493
alphaInfo_200 = new AlphaInfo();
14991494
NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200);
15001495
handle.addRepresentation(rep);

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/internal/NativeImageLoader.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222

2323
public class NativeImageLoader {
2424

25-
public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
25+
public static boolean canLoadAtZoom(ElementAtZoom<InputStream> streamAtZoom, int targetZoom) {
26+
return FileFormat.canLoadAtZoom(streamAtZoom, targetZoom);
27+
}
28+
29+
public static List<ImageData> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
2630
return FileFormat.load(streamAtZoom, imageLoader, targetZoom);
2731
}
2832

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDataLoader.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,40 @@ public static ImageData load(String filename) {
3737
return data[0];
3838
}
3939

40+
public static boolean canLoadAtZoom(InputStream stream, int fileZoom, int targetZoom) {
41+
return new ImageLoader().canLoadAtZoom(stream, fileZoom, targetZoom);
42+
}
43+
4044
public static ElementAtZoom<ImageData> load(InputStream stream, int fileZoom, int targetZoom) {
41-
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(stream, fileZoom, targetZoom);
45+
List<ImageData> data;
46+
int zoom;
47+
if (canLoadAtZoom(stream, fileZoom, targetZoom)) {
48+
data = new ImageLoader().load(stream, fileZoom, targetZoom);
49+
zoom = targetZoom;
50+
} else {
51+
data = new ImageLoader().load(stream, fileZoom, fileZoom);
52+
zoom = fileZoom;
53+
}
4254
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
43-
return data.get(0);
55+
return new ElementAtZoom<>(data.get(0), zoom);
56+
}
57+
58+
public static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) {
59+
return new ImageLoader().canLoadAtZoom(filename, fileZoom, targetZoom);
4460
}
4561

4662
public static ElementAtZoom<ImageData> load(String filename, int fileZoom, int targetZoom) {
47-
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(filename, fileZoom, targetZoom);
63+
List<ImageData> data;
64+
int zoom;
65+
if (canLoadAtZoom(filename, fileZoom, targetZoom)) {
66+
data = new ImageLoader().load(filename, fileZoom, targetZoom);
67+
zoom = targetZoom;
68+
} else {
69+
data = new ImageLoader().load(filename, fileZoom, fileZoom);
70+
zoom = fileZoom;
71+
}
4872
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
49-
return data.get(0);
73+
return new ElementAtZoom<>(data.get(0), zoom);
5074
}
5175

5276
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,19 @@ public ImageData[] load(InputStream stream) {
155155
return data;
156156
}
157157

158-
List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int targetZoom) {
158+
List<ImageData> load(InputStream stream, int fileZoom, int targetZoom) {
159159
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
160160
reset();
161-
List<ElementAtZoom<ImageData>> images = NativeImageLoader.load(new ElementAtZoom<>(stream, fileZoom), this, targetZoom);
162-
data = images.stream().map(ElementAtZoom::element).toArray(ImageData[]::new);
161+
List<ImageData> images = NativeImageLoader.load(new ElementAtZoom<>(stream, fileZoom), this, targetZoom);
162+
data = images.stream().toArray(ImageData[]::new);
163163
return images;
164164
}
165165

166+
boolean canLoadAtZoom(InputStream stream, int fileZoom, int targetZoom) {
167+
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
168+
return NativeImageLoader.canLoadAtZoom(new ElementAtZoom<>(stream, fileZoom), targetZoom);
169+
}
170+
166171
/**
167172
* Loads an array of <code>ImageData</code> objects from the
168173
* file with the specified name. Throws an error if either
@@ -186,7 +191,7 @@ public ImageData[] load(String filename) {
186191
return data;
187192
}
188193

189-
List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoom) {
194+
List<ImageData> load(String filename, int fileZoom, int targetZoom) {
190195
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
191196
try (InputStream stream = new FileInputStream(filename)) {
192197
return load(stream, fileZoom, targetZoom);
@@ -196,6 +201,16 @@ List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoo
196201
return null;
197202
}
198203

204+
boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) {
205+
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
206+
try (InputStream stream = new FileInputStream(filename)) {
207+
return canLoadAtZoom(stream, fileZoom, targetZoom);
208+
} catch (IOException e) {
209+
SWT.error(SWT.ERROR_IO, e);
210+
}
211+
return false;
212+
}
213+
199214
/**
200215
* Saves the image data in this ImageLoader to the specified stream.
201216
* The format parameter can have one of the following values:

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ static abstract class StaticImageFileFormat extends FileFormat {
8282
abstract ImageData[] loadFromByteStream();
8383

8484
@Override
85-
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom) {
86-
return Arrays.stream(loadFromByteStream()).map(d -> new ElementAtZoom<>(d, fileZoom)).toList();
85+
List<ImageData> loadFromByteStream(int fileZoom, int targetZoom) {
86+
if (fileZoom != targetZoom) {
87+
throw new IllegalArgumentException("Cannot load static image at different zoom than the file is in (fileZoom = " + fileZoom + ", targetZoom = " + targetZoom);
88+
}
89+
return Arrays.asList(loadFromByteStream());
8790
}
8891
}
8992

@@ -102,13 +105,13 @@ List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom)
102105
* Format that do not implement {@link StaticImageFileFormat} MUST return
103106
* {@link ImageData} with the specified {@code targetZoom}.
104107
*/
105-
abstract List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom);
108+
abstract List<ImageData> loadFromByteStream(int fileZoom, int targetZoom);
106109

107110
/**
108111
* Read the specified input stream, and return the
109112
* device independent image array represented by the stream.
110113
*/
111-
public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, int fileZoom, int targetZoom) {
114+
public List<ImageData> loadFromStream(LEDataInputStream stream, int fileZoom, int targetZoom) {
112115
try {
113116
inputStream = stream;
114117
return loadFromByteStream(fileZoom, targetZoom);
@@ -126,7 +129,7 @@ public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, i
126129
* Read the specified input stream using the specified loader, and
127130
* return the device independent image array represented by the stream.
128131
*/
129-
public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> is, ImageLoader loader, int targetZoom) {
132+
public static List<ImageData> load(ElementAtZoom<InputStream> is, ImageLoader loader, int targetZoom) {
130133
LEDataInputStream stream = new LEDataInputStream(is.element());
131134
FileFormat fileFormat = determineFileFormat(stream).orElseGet(() -> {
132135
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
@@ -136,6 +139,10 @@ public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> is,
136139
return fileFormat.loadFromStream(stream, is.zoom(), targetZoom);
137140
}
138141

142+
public static boolean canLoadAtZoom(ElementAtZoom<InputStream> is, int targetZoom) {
143+
return is.zoom() == targetZoom || isDynamicallySizableFormat(is.element());
144+
}
145+
139146
/**
140147
* Write the device independent image array stored in the specified loader
141148
* to the specified output stream using the specified file format.

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/SVGFileFormat.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import org.eclipse.swt.*;
2020
import org.eclipse.swt.graphics.*;
21-
import org.eclipse.swt.internal.DPIUtil.*;
2221

2322
/**
2423
* A {@link FileFormat} implementation for handling SVG (Scalable Vector
@@ -43,7 +42,7 @@ boolean isFileFormat(LEDataInputStream stream) throws IOException {
4342
}
4443

4544
@Override
46-
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom) {
45+
List<ImageData> loadFromByteStream(int fileZoom, int targetZoom) {
4746
if (RASTERIZER == null) {
4847
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT, null, " [No SVG rasterizer found]");
4948
}
@@ -52,7 +51,7 @@ List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom)
5251
}
5352
try {
5453
ImageData rasterizedImageData = RASTERIZER.rasterizeSVG(inputStream, 100 * targetZoom / fileZoom);
55-
return List.of(new ElementAtZoom<>(rasterizedImageData, targetZoom));
54+
return List.of(rasterizedImageData);
5655
} catch (IOException e) {
5756
SWT.error(SWT.ERROR_INVALID_IMAGE, e);
5857
return List.of();

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ ImageData loadIcon(int[] iconHeader) {
133133
StaticImageFileFormat png = new PNGFileFormat();
134134
if (png.isFileFormat(inputStream)) {
135135
png.loader = this.loader;
136-
return png.loadFromStream(inputStream, DEFAULT_ZOOM, DEFAULT_ZOOM).get(0).element();
136+
return png.loadFromStream(inputStream, DEFAULT_ZOOM, DEFAULT_ZOOM).get(0);
137137
}
138138
} catch (Exception e) {
139139
}

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/NativeImageLoader.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ public class NativeImageLoader {
3333

3434
// --- loading ---
3535

36-
public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
36+
public static boolean canLoadAtZoom(ElementAtZoom<InputStream> streamAtZoom, int targetZoom) {
37+
return FileFormat.canLoadAtZoom(streamAtZoom, targetZoom);
38+
}
39+
40+
public static List<ImageData> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
3741
// 1) Load InputStream into byte array
3842
byte[] data_buffer;
3943
InputStream stream = streamAtZoom.element();
@@ -139,7 +143,7 @@ public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> str
139143
}
140144
OS.g_free(buffer_ptr);
141145
OS.g_object_unref(loader);
142-
return Arrays.stream(imgDataArray).map(data -> new ElementAtZoom<>(data, streamAtZoom.zoom())).toList();
146+
return Arrays.asList(imgDataArray);
143147
}
144148

145149
/**

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/NativeImageLoader.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222

2323
public class NativeImageLoader {
2424

25-
public static List<ElementAtZoom<ImageData>> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
25+
public static boolean canLoadAtZoom(ElementAtZoom<InputStream> streamAtZoom, int targetZoom) {
26+
return FileFormat.canLoadAtZoom(streamAtZoom, targetZoom);
27+
}
28+
29+
public static List<ImageData> load(ElementAtZoom<InputStream> streamAtZoom, ImageLoader imageLoader, int targetZoom) {
2630
return FileFormat.load(streamAtZoom, imageLoader, targetZoom);
2731
}
2832

0 commit comments

Comments
 (0)