Skip to content

Commit 394250f

Browse files
committed
works pretty good but still work in progress
1 parent 1a1f0c2 commit 394250f

File tree

17 files changed

+646
-43
lines changed

17 files changed

+646
-43
lines changed

binaries/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Fragment-Host: org.eclipse.swt;bundle-version="[3.128.0,4.0.0)"
33
Bundle-Name: %fragmentName
44
Bundle-Vendor: %providerName
55
Bundle-SymbolicName: org.eclipse.swt.win32.win32.x86_64; singleton:=true
6-
Bundle-Version: 3.131.0.qualifier
6+
Bundle-Version: 4.0.0.qualifier
77
Bundle-ManifestVersion: 2
88
Bundle-Localization: fragment
99
Export-Package:

bundles/org.eclipse.swt.svg/src/org/eclipse/swt/svg/JSVGRasterizer.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,34 +72,44 @@ public class JSVGRasterizer implements SVGRasterizer {
7272

7373
@Override
7474
public ImageData rasterizeSVG(InputStream inputStream, int zoom) throws IOException {
75-
SVGDocument svgDocument = loadSVG(inputStream);
76-
if (svgDocument == null) {
77-
SWT.error(SWT.ERROR_INVALID_IMAGE);
78-
}
75+
SVGDocument svgDocument = loadAndValidateSVG(inputStream);
7976
BufferedImage rasterizedImage = renderSVG(svgDocument, zoom);
8077
return convertToSWTImageData(rasterizedImage);
8178
}
82-
83-
private SVGDocument loadSVG(InputStream inputStream) {
84-
return SVG_LOADER.load(inputStream, null, LoaderContext.createDefault());
79+
80+
@Override
81+
public ImageData rasterizeSVG(InputStream inputStream, int width, int height) throws IOException {
82+
SVGDocument svgDocument = loadAndValidateSVG(inputStream);
83+
BufferedImage rasterizedImage = renderSVG(svgDocument, width, height);
84+
return convertToSWTImageData(rasterizedImage);
85+
}
86+
87+
private SVGDocument loadAndValidateSVG(InputStream inputStream) throws IOException {
88+
SVGDocument svgDocument = SVG_LOADER.load(inputStream, null, LoaderContext.createDefault());
89+
if (svgDocument == null) {
90+
SWT.error(SWT.ERROR_INVALID_IMAGE);
91+
}
92+
return svgDocument;
8593
}
8694

8795
private BufferedImage renderSVG(SVGDocument svgDocument, int zoom) {
96+
FloatSize sourceImageSize = svgDocument.size();
8897
float scalingFactor = zoom / 100.0f;
89-
BufferedImage image = createImageBase(svgDocument, scalingFactor);
90-
Graphics2D g = configureRenderingOptions(scalingFactor, image);
98+
int targetImageWidth = calculateTargetWidth(scalingFactor, sourceImageSize);
99+
int targetImageHeight = calculateTargetHeight(scalingFactor, sourceImageSize);
100+
return renderSVG(svgDocument, targetImageWidth, targetImageHeight);
101+
}
102+
103+
private BufferedImage renderSVG(SVGDocument svgDocument, int width, int height) {
104+
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
105+
float scalingFactorX = width / svgDocument.size().width;
106+
float scalingFactorY = height / svgDocument.size().height;
107+
Graphics2D g = configureRenderingOptions(scalingFactorX, scalingFactorY, image);
91108
svgDocument.render(null, g);
92109
g.dispose();
93110
return image;
94111
}
95112

96-
private BufferedImage createImageBase(SVGDocument svgDocument, float scalingFactor) {
97-
FloatSize sourceImageSize = svgDocument.size();
98-
int targetImageWidth = calculateTargetWidth(scalingFactor, sourceImageSize);
99-
int targetImageHeight = calculateTargetHeight(scalingFactor, sourceImageSize);
100-
return new BufferedImage(targetImageWidth, targetImageHeight, BufferedImage.TYPE_INT_ARGB);
101-
}
102-
103113
private int calculateTargetWidth(float scalingFactor, FloatSize sourceImageSize) {
104114
double sourceImageWidth = sourceImageSize.getWidth();
105115
return (int) Math.round(sourceImageWidth * scalingFactor);
@@ -110,10 +120,10 @@ private int calculateTargetHeight(float scalingFactor, FloatSize sourceImageSize
110120
return (int) Math.round(sourceImageHeight * scalingFactor);
111121
}
112122

113-
private Graphics2D configureRenderingOptions(float scalingFactor, BufferedImage image) {
123+
private Graphics2D configureRenderingOptions(float scalingFactorX, float scalingFactorY, BufferedImage image) {
114124
Graphics2D g = image.createGraphics();
115125
g.setRenderingHints(RENDERING_HINTS);
116-
g.scale(scalingFactor, scalingFactor);
126+
g.scale(scalingFactorX, scalingFactorY);
117127
return g;
118128
}
119129

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,16 @@ public static ElementAtZoom<ImageData> load(String filename, int fileZoom, int t
5757
return data.get(0);
5858
}
5959

60+
public static ElementAtTargetSize<ImageData> loadByTargetSize(InputStream stream, int targetWidth, int targetHeight) {
61+
List<ElementAtTargetSize<ImageData>> data = new ImageLoader().loadByTargetSize(stream, targetWidth, targetHeight);
62+
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
63+
return data.get(0);
64+
}
65+
66+
public static ElementAtTargetSize<ImageData> loadByTargetSize(String filename, int targetWidth, int targetHeight) {
67+
List<ElementAtTargetSize<ImageData>> data = new ImageLoader().loadByTargetSize(filename, targetWidth, targetHeight);
68+
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
69+
return data.get(0);
70+
}
71+
6072
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.graphics;
1515

16+
import java.util.function.*;
17+
1618
/**
1719
* Interface to provide a callback mechanism to get information about images
1820
* when the application is moved from a low DPI monitor to a high DPI monitor.
@@ -43,4 +45,34 @@ public interface ImageDataProvider {
4345
*/
4446
ImageData getImageData (int zoom);
4547

48+
/**
49+
* @since 4.0
50+
*/
51+
default ImageData getImageData(int targetWidth, int targetHeight) {
52+
return null;
53+
}
54+
55+
/**
56+
* @since 4.0
57+
*/
58+
static ImageDataProvider fromZoom(IntFunction<ImageData> zoomFunction) {
59+
return zoomFunction::apply;
60+
}
61+
62+
/**
63+
* @since 4.0
64+
*/
65+
static ImageDataProvider fromSize(BiFunction<Integer, Integer, ImageData> sizeFunction) {
66+
return new SizeAwareImageDataProvider() {
67+
@Override
68+
public ImageData getImageData(int targetWidth, int targetHeight) {
69+
return sizeFunction.apply(targetWidth, targetHeight);
70+
}
71+
72+
@Override
73+
public ImageData getImageData(int zoom) {
74+
throw new UnsupportedOperationException();
75+
}
76+
};
77+
}
4678
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.graphics;
1515

16+
import java.util.function.*;
17+
1618
/**
1719
* Interface to provide a callback mechanism to get information about images
1820
* when the application is moved from a low DPI monitor to a high DPI monitor.
@@ -43,4 +45,34 @@ public interface ImageFileNameProvider {
4345
*/
4446
String getImagePath (int zoom);
4547

48+
/**
49+
* @since 4.0
50+
*/
51+
default String getImagePath(int targetWidth, int targetHeight) {
52+
return null;
53+
}
54+
55+
/**
56+
* @since 4.0
57+
*/
58+
static ImageFileNameProvider fromZoom(IntFunction<String> zoomFunction) {
59+
return zoomFunction::apply;
60+
}
61+
62+
/**
63+
* @since 4.0
64+
*/
65+
static ImageFileNameProvider fromSize(BiFunction<Integer, Integer, String> sizeFunction) {
66+
return new SizeAwareImageFileNameProvider() {
67+
@Override
68+
public String getImagePath(int targetWidth, int targetHeight) {
69+
return sizeFunction.apply(targetWidth, targetHeight);
70+
}
71+
72+
@Override
73+
public String getImagePath(int zoom) {
74+
throw new UnsupportedOperationException();
75+
}
76+
};
77+
}
4678
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int target
163163
return images;
164164
}
165165

166+
List<ElementAtTargetSize<ImageData>> loadByTargetSize(InputStream stream, int targetWidth, int targetHeight) {
167+
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
168+
reset();
169+
List<ElementAtTargetSize<ImageData>> images = NativeImageLoader.load(new ElementAtTargetSize<>(stream, targetWidth, targetHeight), this, targetWidth, targetHeight);
170+
data = images.stream().map(ElementAtTargetSize::element).toArray(ImageData[]::new);
171+
return images;
172+
}
173+
174+
166175
static boolean canLoadAtZoom(InputStream stream, int fileZoom, int targetZoom) {
167176
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
168177
return FileFormat.canLoadAtZoom(new ElementAtZoom<>(stream, fileZoom), targetZoom);
@@ -201,6 +210,16 @@ List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoo
201210
return null;
202211
}
203212

213+
List<ElementAtTargetSize<ImageData>> loadByTargetSize(String filename, int targetWidth, int targetHeight) {
214+
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
215+
try (InputStream stream = new FileInputStream(filename)) {
216+
return loadByTargetSize(stream, targetWidth, targetHeight);
217+
} catch (IOException e) {
218+
SWT.error(SWT.ERROR_IO, e);
219+
}
220+
return null;
221+
}
222+
204223
static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) {
205224
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
206225
try (InputStream stream = new FileInputStream(filename)) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.eclipse.swt.graphics;
2+
3+
/**
4+
* @since 4.0
5+
*/
6+
public interface SizeAwareImageDataProvider extends ImageDataProvider {
7+
@Override
8+
ImageData getImageData(int targetWidth, int targetHeight);
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.eclipse.swt.graphics;
2+
3+
/**
4+
* @since 4.0
5+
*/
6+
public interface SizeAwareImageFileNameProvider extends ImageFileNameProvider {
7+
@Override
8+
String getImagePath(int targetWidth, int targetHeight);
9+
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,36 @@ public int getGcStyle() {
175175
}
176176
}
177177

178+
//TODO make private
179+
public static ImageData autoScaleImageData (Device device, final ImageData imageData, int targetWidth, int targetHeight) {
180+
// Guards are already implemented in callers: if (deviceZoom == 100 || imageData == null || scaleFactor == 1.0f) return imageData;
181+
int width = imageData.width;
182+
int height = imageData.height;
183+
boolean useSmoothScaling = isSmoothScalingEnabled() && imageData.getTransparencyType() != SWT.TRANSPARENCY_MASK;
184+
if (useSmoothScaling) {
185+
Image original = new Image (device, (ImageDataProvider) zoom -> imageData);
186+
ImageGcDrawer drawer = new ImageGcDrawer() {
187+
@Override
188+
public void drawOn(GC gc, int imageWidth, int imageHeight) {
189+
gc.setAntialias (SWT.ON);
190+
Image.drawAtTargetSize(gc, original, width, height, targetWidth, targetHeight);
191+
};
192+
193+
@Override
194+
public int getGcStyle() {
195+
return SWT.TRANSPARENT;
196+
}
197+
};
198+
Image resultImage = new Image (device, drawer, targetWidth, targetHeight);
199+
ImageData result = resultImage.getImageData (100);
200+
original.dispose ();
201+
resultImage.dispose ();
202+
return result;
203+
} else {
204+
return imageData.scaledTo (targetWidth, targetHeight);
205+
}
206+
}
207+
178208
public static boolean isSmoothScalingEnabled() {
179209
return autoScaleMethod == AutoScaleMethod.SMOOTH;
180210
}
@@ -244,6 +274,20 @@ public record ElementAtZoom<T>(T element, int zoom) {
244274
}
245275
}
246276

277+
public record ElementAtTargetSize<T>(T element, int targetWidth, int targetHeight) {
278+
public ElementAtTargetSize {
279+
if (element == null) {
280+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
281+
}
282+
if (targetWidth <= 0 || targetHeight <= 0) {
283+
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
284+
}
285+
if (targetHeight <= 0 || targetHeight <= 0) {
286+
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
287+
}
288+
}
289+
}
290+
247291
/**
248292
* Gets ImageData that are appropriate for the specified zoom level together
249293
* with the zoom level at which the image data are. If there is an image at the
@@ -264,6 +308,18 @@ public static ElementAtZoom<ImageData> validateAndGetImageDataAtZoom(ImageDataPr
264308
return imageDataAtZoom;
265309
}
266310

311+
public static ElementAtTargetSize<ImageData> validateAndGetImageDataAtTargetSize(ImageDataProvider provider, int targetWidth, int targetHeight) {
312+
if (provider == null) {
313+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
314+
}
315+
ElementAtTargetSize<ImageData> imageDataAtTargetSize = getElementAtTargetSize((x, z) -> provider.getImageData(x, z), targetWidth, targetHeight);
316+
if (imageDataAtTargetSize == null) {
317+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
318+
": ImageDataProvider [" + provider + "] returns null ImageData at 100% zoom.");
319+
}
320+
return imageDataAtTargetSize;
321+
}
322+
267323
/**
268324
* Gets the image file path that are appropriate for the specified zoom level
269325
* together with the zoom level at which the image data are. If there is an
@@ -284,6 +340,18 @@ public static ElementAtZoom<String> validateAndGetImagePathAtZoom(ImageFileNameP
284340
return imagePathAtZoom;
285341
}
286342

343+
public static ElementAtTargetSize<String> validateAndGetImagePathAtTargetSize(ImageFileNameProvider provider, int targetWidth, int targetHeight) {
344+
if (provider == null) {
345+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
346+
}
347+
ElementAtTargetSize<String> imagePathAtTargetSize = getElementAtTargetSize((x, z) -> provider.getImagePath(x, z), targetWidth, targetHeight);
348+
if (imagePathAtTargetSize == null) {
349+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
350+
": ImageFileNameProvider [" + provider + "] returns null filename at 100% zoom.");
351+
}
352+
return imagePathAtTargetSize;
353+
}
354+
287355
private static <T> ElementAtZoom<T> getElementAtZoom(Function<Integer, T> elementForZoomProvider, int zoom) {
288356
T dataAtOriginalZoom = elementForZoomProvider.apply(zoom);
289357
if (dataAtOriginalZoom != null) {
@@ -310,6 +378,32 @@ private static <T> ElementAtZoom<T> getElementAtZoom(Function<Integer, T> elemen
310378
return null;
311379
}
312380

381+
private static <T> ElementAtTargetSize<T> getElementAtTargetSize(BiFunction<Integer, Integer, T> elementForZoomProvider, int targetWidth, int targetHeight) {
382+
T dataAtOriginalZoom = elementForZoomProvider.apply(targetWidth, targetHeight);
383+
if (dataAtOriginalZoom != null) {
384+
return new ElementAtTargetSize<>(dataAtOriginalZoom, targetWidth, targetHeight);
385+
}
386+
if (targetWidth >= 16 && targetWidth <= 24) {
387+
T dataAt150Percent = elementForZoomProvider.apply(24, 24);
388+
if (dataAt150Percent != null) {
389+
return new ElementAtTargetSize<>(dataAt150Percent, 24, 24);
390+
}
391+
}
392+
if (targetWidth > 16) {
393+
T dataAt200Percent = elementForZoomProvider.apply(32, 32);
394+
if (dataAt200Percent != null) {
395+
return new ElementAtTargetSize<>(dataAt200Percent, 32, 32);
396+
}
397+
}
398+
if (targetWidth != 16) {
399+
T dataAt100Percent = elementForZoomProvider.apply(16, 16);
400+
if (dataAt100Percent != null) {
401+
return new ElementAtTargetSize<>(dataAt100Percent, 16, 16);
402+
}
403+
}
404+
return null;
405+
}
406+
313407
public static int getNativeDeviceZoom() {
314408
return nativeDeviceZoom;
315409
}

0 commit comments

Comments
 (0)