Skip to content

Commit 956ed43

Browse files
committed
Use Path to represent file-system paths for ImageData creation
Use java.nio.file.Path to model file-system paths instead of String to represent file-system paths. Add the new way to create ImageData as static factory instead of a constructor, because a constructor is not really suitable to create a copy of the first element of an array of ImageData. Also inline the ImageDataLoader and use the new ImageData.load() factories instead.
1 parent 9a9efe1 commit 956ed43

File tree

9 files changed

+467
-207
lines changed

9 files changed

+467
-207
lines changed

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

+70-39
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616

1717
import java.io.*;
18+
import java.nio.file.Path;
1819
import java.util.*;
1920
import java.util.function.*;
2021

@@ -129,9 +130,9 @@ public final class Image extends Resource implements Drawable {
129130
static final int DEFAULT_SCANLINE_PAD = 4;
130131

131132
/**
132-
* ImageFileNameProvider to provide file names at various Zoom levels
133+
* ImageFileProvider to provide files at various Zoom levels
133134
*/
134-
private ImageFileNameProvider imageFileNameProvider;
135+
private ImagePathProvider imageFileProvider;
135136

136137
/**
137138
* ImageDataProvider to provide ImageData at various Zoom levels
@@ -390,11 +391,11 @@ public Image(Device device, Image srcImage, int flag) {
390391
/* Create the 100% representation for the new image from source image & apply flag */
391392
createRepFromSourceAndApplyFlag(srcImage.getRepresentation (100), srcWidth, srcHeight, flag);
392393

393-
imageFileNameProvider = srcImage.imageFileNameProvider;
394+
imageFileProvider = srcImage.imageFileProvider;
394395
imageDataProvider = srcImage.imageDataProvider;
395396
imageGcDrawer = srcImage.imageGcDrawer;
396397
this.styleFlag = srcImage.styleFlag | flag;
397-
if (imageFileNameProvider != null || imageDataProvider != null ||srcImage.imageGcDrawer != null) {
398+
if (imageFileProvider != null || imageDataProvider != null ||srcImage.imageGcDrawer != null) {
398399
/* If source image has 200% representation then create the 200% representation for the new image & apply flag */
399400
NSBitmapImageRep rep200 = srcImage.getRepresentation (200);
400401
if (rep200 != null) createRepFromSourceAndApplyFlag(rep200, srcWidth * 2, srcHeight * 2, flag);
@@ -652,18 +653,11 @@ public Image(Device device, ImageData source, ImageData mask) {
652653
* </p>
653654
* <pre>
654655
* static Image loadImage (Display display, Class clazz, String string) {
655-
* InputStream stream = clazz.getResourceAsStream (string);
656-
* if (stream == null) return null;
657-
* Image image = null;
658-
* try {
659-
* image = new Image (display, stream);
660-
* } catch (SWTException ex) {
661-
* } finally {
662-
* try {
663-
* stream.close ();
664-
* } catch (IOException ex) {}
665-
* }
666-
* return image;
656+
* try (InputStream stream = clazz.getResourceAsStream(string)){
657+
* if (stream == null) return null;
658+
* return new Image (display, stream);
659+
* } catch (SWTException | IOException ex) {
660+
* }
667661
* }
668662
* </pre>
669663
* <p>
@@ -698,8 +692,8 @@ public Image(Device device, InputStream stream) {
698692
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
699693
try {
700694
byte[] input = stream.readAllBytes();
701-
initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom),
702-
zoom -> ImageDataLoader.load(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom).element());
695+
initWithSupplier(zoom -> ImageLoader.canLoadAtZoom(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom),
696+
zoom -> ImageData.load(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom).element());
703697
init();
704698
} catch (IOException e) {
705699
SWT.error(SWT.ERROR_INVALID_ARGUMENT, e);
@@ -746,10 +740,11 @@ public Image(Device device, String filename) {
746740
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
747741
try {
748742
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
749-
initNative(filename);
743+
Path file = Path.of(filename);
744+
initNative(file);
750745
if (this.handle == null) {
751-
initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(filename, FileFormat.DEFAULT_ZOOM, zoom),
752-
zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom).element());
746+
initWithSupplier(zoom -> ImageLoader.canLoadAtZoom(file, FileFormat.DEFAULT_ZOOM, zoom),
747+
zoom -> ImageData.load(file, FileFormat.DEFAULT_ZOOM, zoom).element());
753748
}
754749
init();
755750
} finally {
@@ -785,28 +780,63 @@ public Image(Device device, String filename) {
785780
* <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
786781
* </ul>
787782
* @since 3.104
783+
* @deprecated Instead use {@link #Image(Device, ImagePathProvider)}
788784
*/
785+
@Deprecated(since = "2025-06")
789786
public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
787+
this(device, DPIUtil.asImageFileProvider(imageFileNameProvider));
788+
}
789+
790+
/**
791+
* Constructs an instance of this class by loading its representation
792+
* from the file retrieved from the {@link ImagePathProvider}. Throws an
793+
* error if an error occurs while loading the image, or if the result
794+
* is an image of an unsupported type.
795+
* <p>
796+
* This constructor is provided for convenience for loading image as
797+
* per DPI level.
798+
*
799+
* @param device the device on which to create the image
800+
* @param imageFileProvider the {@link ImagePathProvider} object that is
801+
* to be used to get the file
802+
*
803+
* @exception IllegalArgumentException <ul>
804+
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
805+
* <li>ERROR_NULL_ARGUMENT - if the ImageFileNameProvider is null</li>
806+
* <li>ERROR_INVALID_ARGUMENT - if the fileName provided by ImageFileNameProvider is null at 100% zoom</li>
807+
* </ul>
808+
* @exception SWTException <ul>
809+
* <li>ERROR_IO - if an IO error occurs while reading from the file</li>
810+
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
811+
* <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
812+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
813+
* </ul>
814+
* @exception SWTError <ul>
815+
* <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
816+
* </ul>
817+
* @since 3.130
818+
*/
819+
public Image(Device device, ImagePathProvider imageFileProvider) {
790820
super(device);
791-
if (imageFileNameProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
792-
this.imageFileNameProvider = imageFileNameProvider;
793-
String filename = imageFileNameProvider.getImagePath(100);
794-
if (filename == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
821+
if (imageFileProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
822+
this.imageFileProvider = imageFileProvider;
823+
Path file = imageFileProvider.getImagePath(100);
824+
if (file == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
795825
NSAutoreleasePool pool = null;
796826
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
797827
try {
798-
initNative(filename);
799-
if (this.handle == null) init(ImageDataLoader.load(filename, 100, 100).element());
828+
initNative(file);
829+
if (this.handle == null) init(ImageData.load(file, 100, 100).element());
800830
init();
801-
String filename2x = imageFileNameProvider.getImagePath(200);
802-
if (filename2x != null) {
831+
Path file2x = imageFileProvider.getImagePath(200);
832+
if (file2x != null) {
803833
alphaInfo_200 = new AlphaInfo();
804-
id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(filename2x));
834+
id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(file2x.toString()));
805835
NSImageRep rep = new NSImageRep(id);
806836
handle.addRepresentation(rep);
807-
} else if (ImageDataLoader.canLoadAtZoom(filename, 100, 200)) {
837+
} else if (ImageLoader.canLoadAtZoom(file, 100, 200)) {
808838
// Try to natively scale up the image (e.g. possible if it's an SVG)
809-
ImageData imageData2x = ImageDataLoader.load(filename, 100, 200).element();
839+
ImageData imageData2x = ImageData.load(file, 100, 200).element();
810840
alphaInfo_200 = new AlphaInfo();
811841
NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200);
812842
handle.addRepresentation(rep);
@@ -885,7 +915,7 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
885915
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
886916
* <li>ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null</li>
887917
* </ul>
888-
* @since 3.129
918+
* @since 3.130
889919
*/
890920
public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
891921
super(device);
@@ -928,7 +958,7 @@ private ImageData drawWithImageGcDrawer(ImageGcDrawer imageGcDrawer, int width,
928958

929959
private AlphaInfo _getAlphaInfoAtCurrentZoom (NSBitmapImageRep rep) {
930960
int deviceZoom = DPIUtil.getDeviceZoom();
931-
if (deviceZoom != 100 && (imageFileNameProvider != null || imageDataProvider != null)) {
961+
if (deviceZoom != 100 && (imageFileProvider != null || imageDataProvider != null)) {
932962
if (alphaInfo_100.alphaData != null && alphaInfo_200 != null) {
933963
if (alphaInfo_200.alphaData == null) initAlpha_200(rep);
934964
return alphaInfo_200;
@@ -1202,8 +1232,8 @@ public boolean equals (Object object) {
12021232
if (device != image.device || alphaInfo_100.transparentPixel != image.alphaInfo_100.transparentPixel) return false;
12031233
if (imageDataProvider != null && image.imageDataProvider != null) {
12041234
return styleFlag == image.styleFlag && imageDataProvider.equals (image.imageDataProvider);
1205-
} else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
1206-
return styleFlag == image.styleFlag && imageFileNameProvider.equals (image.imageFileNameProvider);
1235+
} else if (imageFileProvider != null && image.imageFileProvider != null) {
1236+
return styleFlag == image.styleFlag && imageFileProvider.equals (image.imageFileProvider);
12071237
} else if (imageGcDrawer != null && image.imageGcDrawer != null) {
12081238
return styleFlag == image.styleFlag && imageGcDrawer.equals(image.imageGcDrawer) && width == image.width
12091239
&& height == image.height;
@@ -1441,8 +1471,8 @@ NSBitmapImageRep createImageRep(NSSize targetSize) {
14411471
public int hashCode () {
14421472
if (imageDataProvider != null) {
14431473
return imageDataProvider.hashCode();
1444-
} else if (imageFileNameProvider != null) {
1445-
return imageFileNameProvider.hashCode();
1474+
} else if (imageFileProvider != null) {
1475+
return imageFileProvider.hashCode();
14461476
} else if (imageGcDrawer != null) {
14471477
return Objects.hash(imageGcDrawer, height, width);
14481478
} else {
@@ -1546,7 +1576,8 @@ void initAlpha_100(NSBitmapImageRep nativeRep) {
15461576

15471577
}
15481578

1549-
void initNative(String filename) {
1579+
void initNative(Path file) {
1580+
String filename = file.toString();
15501581
NSAutoreleasePool pool = null;
15511582
NSImage nativeImage = null;
15521583

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

+102-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2016 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -15,9 +15,12 @@
1515

1616

1717
import java.io.*;
18+
import java.nio.file.Path;
19+
import java.util.*;
1820

1921
import org.eclipse.swt.*;
2022
import org.eclipse.swt.internal.*;
23+
import org.eclipse.swt.internal.DPIUtil.*;
2124

2225
/**
2326
* Instances of this class are device-independent descriptions
@@ -239,6 +242,90 @@ public final class ImageData implements Cloneable {
239242
{ 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000, 0x880000, 0x280000, 0xa80000 }
240243
};
241244

245+
/**
246+
* Creates an {@code ImageData} loaded from the specified file. Throws an error
247+
* if an error occurs loading the image, or if the image has an unsupported
248+
* type.
249+
* <p>
250+
* This factory is provided for convenience when loading a single image only. If
251+
* the file contains multiple images, only the first one will be loaded. To load
252+
* multiple images, use {@link ImageLoader#load(Path)}.
253+
* </p>
254+
*
255+
* @param file the file to load the image from (must not be null)
256+
*
257+
* @exception IllegalArgumentException <ul>
258+
* <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
259+
* </ul>
260+
* @exception SWTException <ul>
261+
* <li>ERROR_IO - if an IO error occurs while reading from the file</li>
262+
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
263+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
264+
* </ul>
265+
* @since 3.130
266+
*/
267+
public static ImageData load(Path file) {
268+
return first(Arrays.asList(new ImageLoader().load(file)));
269+
}
270+
271+
/**
272+
* Creates an <code>ImageData</code> loaded from the specified input stream.
273+
* Throws an error if an error occurs while loading the image, or if the image
274+
* has an unsupported type. Application code is still responsible for closing
275+
* the input stream.
276+
* <p>
277+
* This factory is provided for convenience when loading a single image only. If
278+
* the stream contains multiple images, only the first one will be loaded. To
279+
* load multiple images, use {@link ImageLoader#load(InputStream)}.
280+
* </p>
281+
* <p>
282+
* This factory may be used to load a resource as follows:
283+
* </p>
284+
*
285+
* <pre>
286+
* static ImageData loadImageData(Class clazz, String string) {
287+
* try (InputStream stream = clazz.getResourceAsStream(string)) {
288+
* if (stream == null) return null;
289+
* return ImageData.load(stream);
290+
* } catch (SWTException | IOException ex) {
291+
* // handle exception appropriately
292+
* }
293+
* }
294+
* </pre>
295+
*
296+
* @param stream the input stream to load the image from (must not be null)
297+
*
298+
* @exception IllegalArgumentException <ul>
299+
* <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
300+
* </ul>
301+
* @exception SWTException <ul>
302+
* <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
303+
* <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
304+
* <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
305+
* </ul>
306+
*
307+
* @see ImageLoader#load(InputStream)
308+
* @since 3.130
309+
*/
310+
public static ImageData load(InputStream stream) {
311+
return first(Arrays.asList(new ImageLoader().load(stream)));
312+
}
313+
314+
static ElementAtZoom<ImageData> load(InputStream stream, int fileZoom, int targetZoom) {
315+
return first(new ImageLoader().load(stream, fileZoom, targetZoom));
316+
}
317+
318+
static ElementAtZoom<ImageData> load(Path file, int fileZoom, int targetZoom) {
319+
return first(new ImageLoader().load(file, fileZoom, targetZoom));
320+
}
321+
322+
private static <T> T first(List<T> data) {
323+
if (data.isEmpty()) {
324+
SWT.error(SWT.ERROR_INVALID_IMAGE);
325+
}
326+
return data.get(0);
327+
}
328+
242329
/**
243330
* Constructs a new, empty ImageData with the given width, height,
244331
* depth and palette. The data will be initialized to an (all zero)
@@ -296,24 +383,18 @@ scanlinePad, checkData(data), 0, null,
296383
* This constructor is provided for convenience when loading a single
297384
* image only. If the stream contains multiple images, only the first
298385
* one will be loaded. To load multiple images, use
299-
* <code>ImageLoader.load()</code>.
386+
* {@link ImageLoader#load(InputStream)}.
300387
* </p><p>
301388
* This constructor may be used to load a resource as follows:
302389
* </p>
303390
* <pre>
304391
* static ImageData loadImageData (Class clazz, String string) {
305-
* InputStream stream = clazz.getResourceAsStream (string);
306-
* if (stream == null) return null;
307-
* ImageData imageData = null;
308-
* try {
309-
* imageData = new ImageData (stream);
310-
* } catch (SWTException ex) {
311-
* } finally {
312-
* try {
313-
* stream.close ();
314-
* } catch (IOException ex) {}
392+
* try (InputStream stream = clazz.getResourceAsStream (string)) {
393+
* if (stream == null) return null;
394+
* return ImageData.load(stream);
395+
* } catch (SWTException |IOException ex) {
396+
* // handle exception appropriately
315397
* }
316-
* return imageData;
317398
* }
318399
* </pre>
319400
*
@@ -329,9 +410,11 @@ scanlinePad, checkData(data), 0, null,
329410
* </ul>
330411
*
331412
* @see ImageLoader#load(InputStream)
413+
* @deprecated Instead use {@link #load(InputStream)}
332414
*/
415+
@Deprecated(since = "2025-06")
333416
public ImageData(InputStream stream) {
334-
ImageData i = ImageDataLoader.load(stream);
417+
ImageData i = load(stream);
335418
setAllFields(
336419
i.width,
337420
i.height,
@@ -360,7 +443,7 @@ public ImageData(InputStream stream) {
360443
* This constructor is provided for convenience when loading a single
361444
* image only. If the file contains multiple images, only the first
362445
* one will be loaded. To load multiple images, use
363-
* <code>ImageLoader.load()</code>.
446+
* {@link ImageLoader#load(String)}.
364447
* </p>
365448
*
366449
* @param filename the name of the file to load the image from (must not be null)
@@ -373,9 +456,12 @@ public ImageData(InputStream stream) {
373456
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
374457
* <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
375458
* </ul>
459+
* @deprecated Instead use {@link #load(Path)}
376460
*/
461+
@Deprecated(since = "2025-06")
377462
public ImageData(String filename) {
378-
ImageData i = ImageDataLoader.load(filename);
463+
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
464+
ImageData i = load(Path.of(filename));
379465
setAllFields(
380466
i.width,
381467
i.height,

0 commit comments

Comments
 (0)