Skip to content

Commit df741bc

Browse files
Michael5601HannesWell
authored andcommitted
Enable Loading of SVGs in arbitrary sized for ImageDataProvider
1 parent 037c5d7 commit df741bc

File tree

3 files changed

+86
-39
lines changed

3 files changed

+86
-39
lines changed

bundles/org.eclipse.jface/.settings/org.eclipse.jdt.core.prefs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ org.eclipse.jdt.core.compiler.problem.deadCode=warning
4646
org.eclipse.jdt.core.compiler.problem.deprecation=warning
4747
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
4848
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
49-
org.eclipse.jdt.core.compiler.problem.discouragedReference=error
49+
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
5050
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
5151
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
5252
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

bundles/org.eclipse.jface/src/org/eclipse/jface/resource/FileImageDescriptor.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.eclipse.core.runtime.IPath;
3232
import org.eclipse.core.runtime.Status;
3333
import org.eclipse.jface.internal.InternalPolicy;
34+
import org.eclipse.jface.resource.URLImageDescriptor.SourceAtZoom;
3435
import org.eclipse.jface.util.Policy;
3536
import org.eclipse.swt.SWT;
3637
import org.eclipse.swt.SWTException;
@@ -52,16 +53,16 @@ public String getImagePath(int zoom) {
5253
if (zoom == 100) {
5354
return getFilePath(name, logIOException);
5455
}
55-
String xName = getxName(name, zoom);
56+
SourceAtZoom<String> xName = getxName(name, zoom);
5657
if (xName != null) {
57-
String xResult = getFilePath(xName, logIOException);
58+
String xResult = getFilePath(xName.source(), logIOException);
5859
if (xResult != null) {
5960
return xResult;
6061
}
6162
}
62-
String xPath = getxPath(name, zoom);
63+
SourceAtZoom<String> xPath = getxPath(name, zoom);
6364
if (xPath != null) {
64-
String xResult = getFilePath(xPath, logIOException);
65+
String xResult = getFilePath(xPath.source(), logIOException);
6566
if (xResult != null) {
6667
return xResult;
6768
}
@@ -122,10 +123,10 @@ public boolean equals(Object o) {
122123
*/
123124
@Override
124125
public ImageData getImageData(int zoom) {
125-
InputStream in = getStream(zoom);
126-
if (in != null) {
127-
try (BufferedInputStream stream = new BufferedInputStream(in)) {
128-
return new ImageData(stream);
126+
SourceAtZoom<InputStream> inputStream = getStream(zoom);
127+
if (inputStream != null) {
128+
try (InputStream stream = new BufferedInputStream(inputStream.source())) {
129+
return URLImageDescriptor.loadImageFromStream(stream, inputStream.zoom(), zoom);
129130
} catch (SWTException e) {
130131
if (e.code != SWT.ERROR_INVALID_IMAGE) {
131132
throw e;
@@ -146,24 +147,28 @@ public ImageData getImageData(int zoom) {
146147
* @return the buffered stream on the file or <code>null</code> if the
147148
* file cannot be found
148149
*/
149-
private InputStream getStream(int zoom) {
150-
if (zoom == 100) {
151-
return getStream(name);
150+
private SourceAtZoom<InputStream> getStream(int zoom) {
151+
if (zoom == 100 || canLoadAtZoom(zoom)) {
152+
return getStream(new SourceAtZoom<>(name, zoom));
152153
}
153154

154-
InputStream xstream = getStream(getxName(name, zoom));
155+
SourceAtZoom<InputStream> xstream = getStream(getxName(name, zoom));
155156
if (xstream != null) {
156157
return xstream;
157158
}
158159

159-
InputStream xpath = getStream(getxPath(name, zoom));
160+
SourceAtZoom<InputStream> xpath = getStream(getxPath(name, zoom));
160161
if (xpath != null) {
161162
return xpath;
162163
}
163164

164165
return null;
165166
}
166167

168+
private boolean canLoadAtZoom(int zoom) {
169+
return URLImageDescriptor.canLoadAtZoom(() -> getStream(new SourceAtZoom<>(name, zoom)).source(), zoom);
170+
}
171+
167172
/**
168173
* try to obtain a stream for a given name, if the name does not match a valid
169174
* resource null is returned
@@ -172,21 +177,22 @@ private InputStream getStream(int zoom) {
172177
* @return an {@link InputStream} to read from, or <code>null</code> if fileName
173178
* does not denotes an existing resource
174179
*/
175-
private InputStream getStream(String fileName) {
180+
@SuppressWarnings("resource")
181+
private SourceAtZoom<InputStream> getStream(SourceAtZoom<String> fileName) {
176182
if (fileName != null) {
177183
if (location != null) {
178-
return location.getResourceAsStream(fileName);
184+
return new SourceAtZoom<>(location.getResourceAsStream(fileName.source()), fileName.zoom());
179185
}
180186
try {
181-
return new FileInputStream(fileName);
187+
return new SourceAtZoom<>(new FileInputStream(fileName.source()), fileName.zoom());
182188
} catch (FileNotFoundException e) {
183189
return null;
184190
}
185191
}
186192
return null;
187193
}
188194

189-
static String getxPath(String name, int zoom) {
195+
static SourceAtZoom<String> getxPath(String name, int zoom) {
190196
Matcher matcher = XPATH_PATTERN.matcher(name);
191197
if (matcher.find()) {
192198
try {
@@ -196,15 +202,16 @@ static String getxPath(String name, int zoom) {
196202
int desiredHeight = Math.round((zoom / 100f) * currentHeight);
197203
String lead = name.substring(0, matcher.start(1));
198204
String tail = name.substring(matcher.end(2));
199-
return lead + desiredWidth + "x" + desiredHeight + tail; //$NON-NLS-1$
205+
String xPath = lead + desiredWidth + "x" + desiredHeight + tail; //$NON-NLS-1$
206+
return new SourceAtZoom<>(xPath, desiredHeight);
200207
} catch (RuntimeException e) {
201208
// should never happen but if then we can't use the alternative name...
202209
}
203210
}
204211
return null;
205212
}
206213

207-
static String getxName(String name, int zoom) {
214+
static SourceAtZoom<String> getxName(String name, int zoom) {
208215
int dot = name.lastIndexOf('.');
209216
if (dot != -1 && (zoom == 150 || zoom == 200)) {
210217
String lead = name.substring(0, dot);
@@ -213,7 +220,7 @@ static String getxName(String name, int zoom) {
213220
tail = ".png"; //$NON-NLS-1$
214221
}
215222
String x = zoom == 150 ? "@1.5x" : "@2x"; //$NON-NLS-1$ //$NON-NLS-2$
216-
return lead + x + tail;
223+
return new SourceAtZoom<>(lead + x + tail, zoom);
217224
}
218225
return null;
219226
}

bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
*******************************************************************************/
1818
package org.eclipse.jface.resource;
1919

20+
2021
import java.io.BufferedInputStream;
2122
import java.io.IOException;
2223
import java.io.InputStream;
2324
import java.net.MalformedURLException;
2425
import java.net.URL;
2526
import java.nio.file.Files;
2627
import java.nio.file.Path;
28+
import java.util.function.Supplier;
2729

2830
import org.eclipse.core.runtime.FileLocator;
2931
import org.eclipse.core.runtime.IAdaptable;
@@ -38,6 +40,10 @@
3840
import org.eclipse.swt.graphics.ImageData;
3941
import org.eclipse.swt.graphics.ImageDataProvider;
4042
import org.eclipse.swt.graphics.ImageFileNameProvider;
43+
import org.eclipse.swt.graphics.ImageLoader;
44+
import org.eclipse.swt.internal.DPIUtil.ElementAtZoom;
45+
import org.eclipse.swt.internal.NativeImageLoader;
46+
import org.eclipse.swt.internal.image.FileFormat;
4147

4248
/**
4349
* An ImageDescriptor that gets its information from a URL. This class is not
@@ -62,16 +68,16 @@ public String getImagePath(int zoom) {
6268
if (zoom == 100) {
6369
return getFilePath(tempURL, logIOException);
6470
}
65-
URL xUrl = getxURL(tempURL, zoom);
71+
SourceAtZoom<URL> xUrl = getxURL(tempURL, zoom);
6672
if (xUrl != null) {
67-
String xResult = getFilePath(xUrl, logIOException);
73+
String xResult = getFilePath(xUrl.source(), logIOException);
6874
if (xResult != null) {
6975
return xResult;
7076
}
7177
}
72-
String xpath = FileImageDescriptor.getxPath(url, zoom);
78+
SourceAtZoom<String> xpath = FileImageDescriptor.getxPath(url, zoom);
7379
if (xpath != null) {
74-
URL xPathUrl = getURL(xpath);
80+
URL xPathUrl = getURL(xpath.source());
7581
if (xPathUrl != null) {
7682
return getFilePath(xPathUrl, logIOException);
7783
}
@@ -127,7 +133,7 @@ public boolean equals(Object o) {
127133
@Deprecated
128134
@Override
129135
public ImageData getImageData() {
130-
return getImageData(getURL(url));
136+
return getImageData(getURL(url), 100, 100);
131137
}
132138

133139
@Override
@@ -138,32 +144,31 @@ public ImageData getImageData(int zoom) {
138144
private static ImageData getImageData(String url, int zoom) {
139145
URL tempURL = getURL(url);
140146
if (tempURL != null) {
141-
if (zoom == 100) {
142-
return getImageData(tempURL);
147+
if (zoom == 100 || canLoadAtZoom(() -> getStream(tempURL), zoom)) {
148+
return getImageData(tempURL, 100, zoom);
143149
}
144-
URL xUrl = getxURL(tempURL, zoom);
150+
SourceAtZoom<URL> xUrl = getxURL(tempURL, zoom);
145151
if (xUrl != null) {
146-
ImageData xdata = getImageData(xUrl);
152+
ImageData xdata = getImageData(xUrl.source(), xUrl.zoom(), zoom);
147153
if (xdata != null) {
148154
return xdata;
149155
}
150156
}
151-
String xpath = FileImageDescriptor.getxPath(url, zoom);
157+
SourceAtZoom<String> xpath = FileImageDescriptor.getxPath(url, zoom);
152158
if (xpath != null) {
153-
URL xPathUrl = getURL(xpath);
159+
URL xPathUrl = getURL(xpath.source());
154160
if (xPathUrl != null) {
155-
return getImageData(xPathUrl);
161+
return getImageData(xPathUrl, xpath.zoom(), zoom);
156162
}
157163
}
158164
}
159165
return null;
160166
}
161167

162-
private static ImageData getImageData(URL url) {
163-
ImageData result = null;
168+
private static ImageData getImageData(URL url, int fileZoom, int targetZoom) {
164169
try (InputStream in = getStream(url)) {
165170
if (in != null) {
166-
result = new ImageData(in);
171+
return loadImageFromStream(in, fileZoom, targetZoom);
167172
}
168173
} catch (SWTException e) {
169174
if (e.code != SWT.ERROR_INVALID_IMAGE) {
@@ -173,7 +178,42 @@ private static ImageData getImageData(URL url) {
173178
} catch (IOException e) {
174179
Policy.getLog().log(Status.error(e.getLocalizedMessage(), e));
175180
}
176-
return result;
181+
return null;
182+
}
183+
184+
/**
185+
* Represents an element, such as InputStream, Path or URL, at a specific zoom
186+
* level.
187+
*
188+
* @param <T> type of the element to be presented, e.g., {@link InputStream}
189+
*/
190+
record SourceAtZoom<T>(T source, int zoom) {
191+
public SourceAtZoom {
192+
if (source == null) {
193+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
194+
}
195+
if (zoom <= 0) {
196+
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
197+
}
198+
}
199+
}
200+
201+
@SuppressWarnings("restriction")
202+
static boolean canLoadAtZoom(Supplier<InputStream> streamFactory, int zoom) {
203+
try (InputStream in = streamFactory.get()) {
204+
if (in != null) {
205+
return FileFormat.canLoadAtZoom(new ElementAtZoom<>(in, 100), zoom);
206+
}
207+
} catch (IOException e) {
208+
Policy.getLog().log(Status.error(e.getLocalizedMessage(), e));
209+
}
210+
return false;
211+
}
212+
213+
@SuppressWarnings("restriction")
214+
static ImageData loadImageFromStream(InputStream stream, int fileZoom, int targetZoom) {
215+
return NativeImageLoader.load(new ElementAtZoom<>(stream, fileZoom), new ImageLoader(), targetZoom).get(0)
216+
.element();
177217
}
178218

179219
/**
@@ -225,7 +265,7 @@ public String toString() {
225265
return "URLImageDescriptor(" + url + ")"; //$NON-NLS-1$ //$NON-NLS-2$
226266
}
227267

228-
private static URL getxURL(URL url, int zoom) {
268+
private static SourceAtZoom<URL> getxURL(URL url, int zoom) {
229269
String path = url.getPath();
230270
int dot = path.lastIndexOf('.');
231271
if (dot != -1 && (zoom == 150 || zoom == 200)) {
@@ -240,7 +280,7 @@ private static URL getxURL(URL url, int zoom) {
240280
if (url.getQuery() != null) {
241281
file += '?' + url.getQuery();
242282
}
243-
return new URL(url.getProtocol(), url.getHost(), url.getPort(), file);
283+
return new SourceAtZoom<>(new URL(url.getProtocol(), url.getHost(), url.getPort(), file), zoom);
244284
} catch (MalformedURLException e) {
245285
Policy.getLog().log(Status.error(e.getLocalizedMessage(), e));
246286
}

0 commit comments

Comments
 (0)