Skip to content

Commit 42af30d

Browse files
committed
works pretty good but still work in progress
1 parent 51fed8e commit 42af30d

File tree

17 files changed

+709
-46
lines changed

17 files changed

+709
-46
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
@@ -315,6 +315,36 @@ public int getGcStyle() {
315315
}
316316
}
317317

318+
//TODO make private
319+
public static ImageData autoScaleImageData (Device device, final ImageData imageData, int targetWidth, int targetHeight) {
320+
// Guards are already implemented in callers: if (deviceZoom == 100 || imageData == null || scaleFactor == 1.0f) return imageData;
321+
int width = imageData.width;
322+
int height = imageData.height;
323+
boolean useSmoothScaling = isSmoothScalingEnabled() && imageData.getTransparencyType() != SWT.TRANSPARENCY_MASK;
324+
if (useSmoothScaling) {
325+
Image original = new Image (device, (ImageDataProvider) zoom -> imageData);
326+
ImageGcDrawer drawer = new ImageGcDrawer() {
327+
@Override
328+
public void drawOn(GC gc, int imageWidth, int imageHeight) {
329+
gc.setAntialias (SWT.ON);
330+
Image.drawAtTargetSize(gc, original, width, height, targetWidth, targetHeight);
331+
};
332+
333+
@Override
334+
public int getGcStyle() {
335+
return SWT.TRANSPARENT;
336+
}
337+
};
338+
Image resultImage = new Image (device, drawer, targetWidth, targetHeight);
339+
ImageData result = resultImage.getImageData (100);
340+
original.dispose ();
341+
resultImage.dispose ();
342+
return result;
343+
} else {
344+
return imageData.scaledTo (targetWidth, targetHeight);
345+
}
346+
}
347+
318348
public static boolean isSmoothScalingEnabled() {
319349
return autoScaleMethod == AutoScaleMethod.SMOOTH;
320350
}
@@ -525,6 +555,20 @@ public record ElementAtZoom<T>(T element, int zoom) {
525555
}
526556
}
527557

558+
public record ElementAtTargetSize<T>(T element, int targetWidth, int targetHeight) {
559+
public ElementAtTargetSize {
560+
if (element == null) {
561+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
562+
}
563+
if (targetWidth <= 0 || targetHeight <= 0) {
564+
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
565+
}
566+
if (targetHeight <= 0 || targetHeight <= 0) {
567+
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
568+
}
569+
}
570+
}
571+
528572
/**
529573
* Gets ImageData that are appropriate for the specified zoom level together
530574
* with the zoom level at which the image data are. If there is an image at the
@@ -545,6 +589,18 @@ public static ElementAtZoom<ImageData> validateAndGetImageDataAtZoom(ImageDataPr
545589
return imageDataAtZoom;
546590
}
547591

592+
public static ElementAtTargetSize<ImageData> validateAndGetImageDataAtTargetSize(ImageDataProvider provider, int targetWidth, int targetHeight) {
593+
if (provider == null) {
594+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
595+
}
596+
ElementAtTargetSize<ImageData> imageDataAtTargetSize = getElementAtTargetSize((x, z) -> provider.getImageData(x, z), targetWidth, targetHeight);
597+
if (imageDataAtTargetSize == null) {
598+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
599+
": ImageDataProvider [" + provider + "] returns null ImageData at 100% zoom.");
600+
}
601+
return imageDataAtTargetSize;
602+
}
603+
548604
/**
549605
* Gets the image file path that are appropriate for the specified zoom level
550606
* together with the zoom level at which the image data are. If there is an
@@ -565,6 +621,18 @@ public static ElementAtZoom<String> validateAndGetImagePathAtZoom(ImageFileNameP
565621
return imagePathAtZoom;
566622
}
567623

624+
public static ElementAtTargetSize<String> validateAndGetImagePathAtTargetSize(ImageFileNameProvider provider, int targetWidth, int targetHeight) {
625+
if (provider == null) {
626+
SWT.error(SWT.ERROR_NULL_ARGUMENT);
627+
}
628+
ElementAtTargetSize<String> imagePathAtTargetSize = getElementAtTargetSize((x, z) -> provider.getImagePath(x, z), targetWidth, targetHeight);
629+
if (imagePathAtTargetSize == null) {
630+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
631+
": ImageFileNameProvider [" + provider + "] returns null filename at 100% zoom.");
632+
}
633+
return imagePathAtTargetSize;
634+
}
635+
568636
private static <T> ElementAtZoom<T> getElementAtZoom(Function<Integer, T> elementForZoomProvider, int zoom) {
569637
T dataAtOriginalZoom = elementForZoomProvider.apply(zoom);
570638
if (dataAtOriginalZoom != null) {
@@ -591,6 +659,32 @@ private static <T> ElementAtZoom<T> getElementAtZoom(Function<Integer, T> elemen
591659
return null;
592660
}
593661

662+
private static <T> ElementAtTargetSize<T> getElementAtTargetSize(BiFunction<Integer, Integer, T> elementForZoomProvider, int targetWidth, int targetHeight) {
663+
T dataAtOriginalZoom = elementForZoomProvider.apply(targetWidth, targetHeight);
664+
if (dataAtOriginalZoom != null) {
665+
return new ElementAtTargetSize<>(dataAtOriginalZoom, targetWidth, targetHeight);
666+
}
667+
if (targetWidth >= 16 && targetWidth <= 24) {
668+
T dataAt150Percent = elementForZoomProvider.apply(24, 24);
669+
if (dataAt150Percent != null) {
670+
return new ElementAtTargetSize<>(dataAt150Percent, 24, 24);
671+
}
672+
}
673+
if (targetWidth > 16) {
674+
T dataAt200Percent = elementForZoomProvider.apply(32, 32);
675+
if (dataAt200Percent != null) {
676+
return new ElementAtTargetSize<>(dataAt200Percent, 32, 32);
677+
}
678+
}
679+
if (targetWidth != 16) {
680+
T dataAt100Percent = elementForZoomProvider.apply(16, 16);
681+
if (dataAt100Percent != null) {
682+
return new ElementAtTargetSize<>(dataAt100Percent, 16, 16);
683+
}
684+
}
685+
return null;
686+
}
687+
594688
public static int getNativeDeviceZoom() {
595689
return nativeDeviceZoom;
596690
}

0 commit comments

Comments
 (0)