diff --git a/binaries/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF b/binaries/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF index 72da35e9326..d369bfb5cae 100644 --- a/binaries/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF +++ b/binaries/org.eclipse.swt.win32.win32.x86_64/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Fragment-Host: org.eclipse.swt;bundle-version="[3.128.0,4.0.0)" Bundle-Name: %fragmentName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.swt.win32.win32.x86_64; singleton:=true -Bundle-Version: 3.129.0.qualifier +Bundle-Version: 4.0.0.qualifier Bundle-ManifestVersion: 2 Bundle-Localization: fragment Export-Package: diff --git a/bundles/org.eclipse.swt.svg/META-INF/MANIFEST.MF b/bundles/org.eclipse.swt.svg/META-INF/MANIFEST.MF index 82af1dad478..b1ee627f020 100644 --- a/bundles/org.eclipse.swt.svg/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.swt.svg/META-INF/MANIFEST.MF @@ -6,5 +6,6 @@ Bundle-Version: 1.0.0.qualifier Automatic-Module-Name: org.eclipse.swt.svgPlugin Bundle-RequiredExecutionEnvironment: JavaSE-17 Export-Package: org.eclipse.swt.svg -Import-Package: org.eclipse.swt.graphics +Import-Package: org.eclipse.swt, + org.eclipse.swt.graphics Bundle-ClassPath: ., libs/jsvg-1.6.1.jar diff --git a/bundles/org.eclipse.swt.svg/src/org/eclipse/swt/svg/JSVGRasterizer.java b/bundles/org.eclipse.swt.svg/src/org/eclipse/swt/svg/JSVGRasterizer.java index 6042a8d4d48..ef119f80de5 100644 --- a/bundles/org.eclipse.swt.svg/src/org/eclipse/swt/svg/JSVGRasterizer.java +++ b/bundles/org.eclipse.swt.svg/src/org/eclipse/swt/svg/JSVGRasterizer.java @@ -17,11 +17,24 @@ import java.awt.image.*; import java.io.*; import java.util.*; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + import org.eclipse.swt.graphics.SVGRasterizer; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.SVGRasterizerRegistry; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; import com.github.weisj.jsvg.*; import com.github.weisj.jsvg.geometry.size.*; @@ -55,17 +68,39 @@ public static void intializeJSVGRasterizer() { KEY_STROKE_CONTROL, VALUE_STROKE_PURE, // KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON // ); - + @Override public ImageData rasterizeSVG(InputStream stream, float scalingFactor) throws IOException { if (stream == null) { throw new IllegalArgumentException("InputStream cannot be null"); } - stream.mark(Integer.MAX_VALUE); if(svgLoader == null) { svgLoader = new SVGLoader(); } + return rasterize(stream, scalingFactor); + } + + @Override + public ImageData rasterizeDisabledSVG(InputStream stream, float scalingFactor) throws IOException { + if(svgLoader == null) { + svgLoader = new SVGLoader(); + } + InputStream disabledStream = applyDisabledLook(stream); + return rasterize(disabledStream, scalingFactor); + } + + @Override + public ImageData rasterizeGraySVG(InputStream stream, float scalingFactor) throws IOException { + if(svgLoader == null) { + svgLoader = new SVGLoader(); + } + InputStream disabledStream = applyGrayLook(stream); + return rasterize(disabledStream, scalingFactor); + } + + private ImageData rasterize(InputStream stream, float scalingFactor) throws IOException { SVGDocument svgDocument = null; + stream.mark(Integer.MAX_VALUE); InputStream nonClosingStream = new FilterInputStream(stream) { @Override public void close() throws IOException { @@ -91,6 +126,82 @@ public void close() throws IOException { return null; } + private static InputStream applyDisabledLook(InputStream svgInputStream) throws IOException { + Document svgDocument = parseSVG(svgInputStream); + addDisabledFilter(svgDocument); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + writeSVG(svgDocument, outputStream); + return new ByteArrayInputStream(outputStream.toByteArray()); + } + } + + private static InputStream applyGrayLook(InputStream svgInputStream) throws IOException { + Document svgDocument = parseSVG(svgInputStream); + addGrayFilter(svgDocument); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + writeSVG(svgDocument, outputStream); + return new ByteArrayInputStream(outputStream.toByteArray()); + } + } + + private static Document parseSVG(InputStream inputStream) throws IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + return builder.parse(inputStream); + } catch (SAXException | IOException | ParserConfigurationException e) { + throw new IOException(e.getMessage()); + } + } + + private static void addDisabledFilter(Document document) { + addFilter(document, 0.64f, 0.4f); + } + + private static void addGrayFilter(Document document) { + addFilter(document, 0.64f, 0.1f); + } + + private static void addFilter(Document document, float slope, float intercept) { + Element defs = (Element) document.getElementsByTagName("defs").item(0); + if (defs == null) { + defs = document.createElement("defs"); + document.getDocumentElement().appendChild(defs); + } + + Element filter = document.createElement("filter"); + filter.setAttribute("id", "customizedLook"); + + Element colorMatrix = document.createElement("feColorMatrix"); + colorMatrix.setAttribute("type", "saturate"); + colorMatrix.setAttribute("values", "0"); + filter.appendChild(colorMatrix); + + Element componentTransfer = document.createElement("feComponentTransfer"); + for (String channel : new String[] { "R", "G", "B" }) { + Element func = document.createElement("feFunc" + channel); + func.setAttribute("type", "linear"); + func.setAttribute("slope", Float.toString(slope)); + func.setAttribute("intercept", Float.toString(intercept)); + componentTransfer.appendChild(func); + } + filter.appendChild(componentTransfer); + defs.appendChild(filter); + document.getDocumentElement().setAttribute("filter", "url(#customizedLook)"); + } + + private static void writeSVG(Document document, OutputStream outputStream) throws IOException { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = transformerFactory.newTransformer(); + transformer.transform(new DOMSource(document), new StreamResult(outputStream)); + } catch (TransformerException e) { + throw new IOException(e.getMessage()); + } + } + private ImageData convertToSWT(BufferedImage bufferedImage) { if (bufferedImage.getColorModel() instanceof DirectColorModel) { DirectColorModel colorModel = (DirectColorModel)bufferedImage.getColorModel(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java index a0d03843db1..842c978c63a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java @@ -331,7 +331,7 @@ scanlinePad, checkData(data), 0, null, * @see ImageLoader#load(InputStream) */ public ImageData(InputStream stream) { - this(stream, 0); + this(stream, 0, SWT.IMAGE_COPY); } /** @@ -360,10 +360,10 @@ public ImageData(InputStream stream) { * * * @see ImageLoader#load(InputStream) - * @since 3.129 + * @since 4.0 */ -public ImageData(InputStream stream, int zoom) { - ImageData[] data = ImageDataLoader.load(stream, zoom); +public ImageData(InputStream stream, int zoom, int flag) { + ImageData[] data = ImageDataLoader.load(stream, zoom, flag); if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE); ImageData i = data[0]; setAllFields( @@ -409,7 +409,7 @@ public ImageData(InputStream stream, int zoom) { * */ public ImageData(String filename) { - this(filename, 0); + this(filename, 0, SWT.IMAGE_COPY); } /** @@ -435,10 +435,10 @@ public ImageData(String filename) { *
@@ -43,4 +42,17 @@ public interface ImageDataProvider {
*/
ImageData getImageData (int zoom);
+ /**
+ * @since 4.0
+ */
+ default ImageData getCustomizedImageData(int zoom, int flag) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 4.0
+ */
+ default boolean supportsRasterizationFlag(int flag) {
+ return false;
+ }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizer.java
index 46140bffe5f..ef4b8493e7d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizer.java
@@ -17,7 +17,7 @@
* Defines the interface for an SVG rasterizer, responsible for converting SVG
* data into rasterized images.
*
- * @since 3.129
+ * @since 4.0
*/
public interface SVGRasterizer {
@@ -34,6 +34,10 @@ public interface SVGRasterizer {
*/
public ImageData rasterizeSVG(InputStream stream, float scalingFactor) throws IOException;
+ public ImageData rasterizeDisabledSVG(InputStream stream, float scalingFactor) throws IOException;
+
+ public ImageData rasterizeGraySVG(InputStream stream, float scalingFactor) throws IOException;
+
/**
* Determines whether the given {@link InputStream} contains a SVG file.
*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizerRegistry.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizerRegistry.java
index 69dd080c825..7146759f970 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizerRegistry.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/SVGRasterizerRegistry.java
@@ -15,7 +15,7 @@
* A registry for managing the instance of an {@link SVGRasterizer} implementation.
* This allows for the registration and retrieval of a single rasterizer instance.
*
- * @since 3.129
+ * @since 4.0
*/
public class SVGRasterizerRegistry {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
index f6c5e7c34c3..80ca08147c4 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
@@ -235,6 +235,14 @@ public Image(Device device, Image srcImage, int flag) {
long srcImageHandle = win32_getHandle(srcImage, getZoom());
switch (flag) {
case SWT.IMAGE_COPY: {
+ ImageData data = null;
+ Image newImage = createWithSVG(device, flag);
+ if(newImage != null) {
+ data = newImage.getImageData(newImage.getZoom());
+ init(data, getZoom());
+ newImage.dispose();
+ break;
+ }
switch (type) {
case SWT.BITMAP:
/* Get the HDC for the device */
@@ -270,13 +278,29 @@ public Image(Device device, Image srcImage, int flag) {
break;
}
case SWT.IMAGE_DISABLE: {
- ImageData data = srcImage.getImageData(srcImage.getZoom());
+ ImageData data = null;
+ Image disabledImage = createWithSVG(device, flag);
+ if(disabledImage != null) {
+ data = disabledImage.getImageData(disabledImage.getZoom());
+ init(data, getZoom());
+ disabledImage.dispose();
+ break;
+ }
+ data = srcImage.getImageData(srcImage.getZoom());
ImageData newData = applyDisableImageData(data, rect.height, rect.width);
init (newData, getZoom());
break;
}
case SWT.IMAGE_GRAY: {
- ImageData data = srcImage.getImageData(srcImage.getZoom());
+ ImageData data = null;
+ Image grayImage = createWithSVG(device, flag);
+ if(grayImage != null) {
+ data = grayImage.getImageData(grayImage.getZoom());
+ init(data, getZoom());
+ grayImage.dispose();
+ break;
+ }
+ data = srcImage.getImageData(srcImage.getZoom());
ImageData newData = applyGrayImageData(data, rect.height, rect.width);
init (newData, getZoom());
break;
@@ -288,6 +312,26 @@ public Image(Device device, Image srcImage, int flag) {
this.device.registerResourceWithZoomSupport(this);
}
+private Image createWithSVG(Device device, int flag) {
+ Image customizedImage = null;
+ if (imageFileNameProvider != null) {
+ ElementAtZoom