Skip to content

Commit 115d633

Browse files
committed
Introduce functionality for icon disablement with SVGs
merge new API (flag parameter) into existing API ImageDataProvider functionality is ignored for now.
1 parent 8873756 commit 115d633

File tree

10 files changed

+172
-24
lines changed

10 files changed

+172
-24
lines changed

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

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,30 @@
3535
import java.awt.RenderingHints.Key;
3636
import java.awt.image.BufferedImage;
3737
import java.awt.image.DataBufferInt;
38+
import java.io.ByteArrayInputStream;
39+
import java.io.ByteArrayOutputStream;
3840
import java.io.IOException;
3941
import java.io.InputStream;
42+
import java.io.OutputStream;
4043
import java.util.Map;
4144

4245
import org.eclipse.swt.SWT;
4346
import org.eclipse.swt.graphics.ImageData;
4447
import org.eclipse.swt.graphics.PaletteData;
4548
import org.eclipse.swt.internal.image.SVGRasterizer;
4649

50+
import javax.xml.parsers.DocumentBuilder;
51+
import javax.xml.parsers.DocumentBuilderFactory;
52+
import javax.xml.parsers.ParserConfigurationException;
53+
import javax.xml.transform.Transformer;
54+
import javax.xml.transform.TransformerException;
55+
import javax.xml.transform.TransformerFactory;
56+
import javax.xml.transform.dom.DOMSource;
57+
import javax.xml.transform.stream.StreamResult;
58+
import org.w3c.dom.Document;
59+
import org.w3c.dom.Element;
60+
import org.xml.sax.SAXException;
61+
4762
import com.github.weisj.jsvg.SVGDocument;
4863
import com.github.weisj.jsvg.geometry.size.FloatSize;
4964
import com.github.weisj.jsvg.parser.LoaderContext;
@@ -71,7 +86,19 @@ public class JSVGRasterizer implements SVGRasterizer {
7186
);
7287

7388
@Override
74-
public ImageData rasterizeSVG(InputStream inputStream, int zoom) throws IOException {
89+
public ImageData rasterizeSVG(InputStream inputStream, int zoom, int flag) throws IOException {
90+
switch(flag) {
91+
case SWT.IMAGE_DISABLE:
92+
inputStream = applyDisabledLook(inputStream);
93+
break;
94+
case SWT.IMAGE_GRAY:
95+
inputStream = applyGrayLook(inputStream);
96+
break;
97+
case SWT.IMAGE_COPY:
98+
break;
99+
default:
100+
SWT.error(SWT.ERROR_INVALID_IMAGE);
101+
}
75102
SVGDocument svgDocument = loadSVG(inputStream);
76103
if (svgDocument == null) {
77104
SWT.error(SWT.ERROR_INVALID_IMAGE);
@@ -133,4 +160,80 @@ private ImageData convertToSWTImageData(BufferedImage rasterizedImage) {
133160
}
134161
return imageData;
135162
}
163+
164+
private static InputStream applyDisabledLook(InputStream svgInputStream) throws IOException {
165+
Document svgDocument = parseSVG(svgInputStream);
166+
addDisabledFilter(svgDocument);
167+
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
168+
writeSVG(svgDocument, outputStream);
169+
return new ByteArrayInputStream(outputStream.toByteArray());
170+
}
171+
}
172+
173+
private static InputStream applyGrayLook(InputStream svgInputStream) throws IOException {
174+
Document svgDocument = parseSVG(svgInputStream);
175+
addGrayFilter(svgDocument);
176+
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
177+
writeSVG(svgDocument, outputStream);
178+
return new ByteArrayInputStream(outputStream.toByteArray());
179+
}
180+
}
181+
182+
private static Document parseSVG(InputStream inputStream) throws IOException {
183+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
184+
DocumentBuilder builder;
185+
try {
186+
builder = factory.newDocumentBuilder();
187+
return builder.parse(inputStream);
188+
} catch (SAXException | IOException | ParserConfigurationException e) {
189+
throw new IOException(e.getMessage());
190+
}
191+
}
192+
193+
private static void addDisabledFilter(Document document) {
194+
addFilter(document, 0.64f, 0.4f);
195+
}
196+
197+
private static void addGrayFilter(Document document) {
198+
addFilter(document, 0.64f, 0.1f);
199+
}
200+
201+
private static void addFilter(Document document, float slope, float intercept) {
202+
Element defs = (Element) document.getElementsByTagName("defs").item(0);
203+
if (defs == null) {
204+
defs = document.createElement("defs");
205+
document.getDocumentElement().appendChild(defs);
206+
}
207+
208+
Element filter = document.createElement("filter");
209+
filter.setAttribute("id", "customizedLook");
210+
211+
Element colorMatrix = document.createElement("feColorMatrix");
212+
colorMatrix.setAttribute("type", "saturate");
213+
colorMatrix.setAttribute("values", "0");
214+
filter.appendChild(colorMatrix);
215+
216+
Element componentTransfer = document.createElement("feComponentTransfer");
217+
for (String channel : new String[] { "R", "G", "B" }) {
218+
Element func = document.createElement("feFunc" + channel);
219+
func.setAttribute("type", "linear");
220+
func.setAttribute("slope", Float.toString(slope));
221+
func.setAttribute("intercept", Float.toString(intercept));
222+
componentTransfer.appendChild(func);
223+
}
224+
filter.appendChild(componentTransfer);
225+
defs.appendChild(filter);
226+
document.getDocumentElement().setAttribute("filter", "url(#customizedLook)");
227+
}
228+
229+
private static void writeSVG(Document document, OutputStream outputStream) throws IOException {
230+
TransformerFactory transformerFactory = TransformerFactory.newInstance();
231+
Transformer transformer;
232+
try {
233+
transformer = transformerFactory.newTransformer();
234+
transformer.transform(new DOMSource(document), new StreamResult(outputStream));
235+
} catch (TransformerException e) {
236+
throw new IOException(e.getMessage());
237+
}
238+
}
136239
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ public static ImageData load(String filename) {
3737
return data[0];
3838
}
3939

40-
public static ElementAtZoom<ImageData> load(InputStream stream, int fileZoom, int targetZoom) {
41-
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(stream, fileZoom, targetZoom);
40+
public static ElementAtZoom<ImageData> load(InputStream stream, int fileZoom, int targetZoom, int flag) {
41+
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(stream, fileZoom, targetZoom, flag);
4242
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
4343
return data.get(0);
4444
}
4545

46-
public static ElementAtZoom<ImageData> load(String filename, int fileZoom, int targetZoom) {
47-
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(filename, fileZoom, targetZoom);
46+
public static ElementAtZoom<ImageData> load(String filename, int fileZoom, int targetZoom, int flag) {
47+
List<ElementAtZoom<ImageData>> data = new ImageLoader().load(filename, fileZoom, targetZoom, flag);
4848
if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE);
4949
return data.get(0);
5050
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,17 @@ public interface ImageDataProvider {
4343
*/
4444
ImageData getImageData (int zoom);
4545

46+
// /**
47+
// * @since 4.0
48+
// */
49+
// default ImageData getCustomizedImageData(int zoom, int flag) {
50+
// throw new UnsupportedOperationException();
51+
// }
52+
//
53+
// /**
54+
// * @since 4.0
55+
// */
56+
// default boolean supportsRasterizationFlag(int flag) {
57+
// return false;
58+
// }
4659
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,14 @@ void reset() {
150150
* </ul>
151151
*/
152152
public ImageData[] load(InputStream stream) {
153-
load(stream, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM);
153+
load(stream, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM, SWT.IMAGE_COPY);
154154
return data;
155155
}
156156

157-
List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int targetZoom) {
157+
List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int targetZoom, int flag) {
158158
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
159159
reset();
160-
List<ElementAtZoom<ImageData>> images = InternalImageLoader.load(stream, this, fileZoom, targetZoom);
160+
List<ElementAtZoom<ImageData>> images = InternalImageLoader.load(stream, this, fileZoom, targetZoom, flag);
161161
data = images.stream().map(ElementAtZoom::element).toArray(ImageData[]::new);
162162
return images;
163163
}
@@ -181,14 +181,14 @@ List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int target
181181
* </ul>
182182
*/
183183
public ImageData[] load(String filename) {
184-
load(filename, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM);
184+
load(filename, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM, SWT.IMAGE_COPY);
185185
return data;
186186
}
187187

188-
List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoom) {
188+
List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoom, int flag) {
189189
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
190190
try (InputStream stream = new FileInputStream(filename)) {
191-
return load(stream, fileZoom, targetZoom);
191+
return load(stream, fileZoom, targetZoom, flag);
192192
} catch (IOException e) {
193193
SWT.error(SWT.ERROR_IO, e);
194194
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static abstract class StaticImageFileFormat extends FileFormat {
8282
abstract ImageData[] loadFromByteStream();
8383

8484
@Override
85-
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom) {
85+
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom, int flag) {
8686
return Arrays.stream(loadFromByteStream()).map(d -> new ElementAtZoom<>(d, fileZoom)).toList();
8787
}
8888
}
@@ -102,16 +102,16 @@ List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom)
102102
* Format that do not implement {@link StaticImageFileFormat} MUST return
103103
* {@link ImageData} with the specified {@code targetZoom}.
104104
*/
105-
abstract List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom);
105+
abstract List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom, int flag);
106106

107107
/**
108108
* Read the specified input stream, and return the
109109
* device independent image array represented by the stream.
110110
*/
111-
public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, int fileZoom, int targetZoom) {
111+
public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, int fileZoom, int targetZoom, int flag) {
112112
try {
113113
inputStream = stream;
114-
return loadFromByteStream(fileZoom, targetZoom);
114+
return loadFromByteStream(fileZoom, targetZoom, flag);
115115
} catch (Exception e) {
116116
if (e instanceof IOException) {
117117
SWT.error(SWT.ERROR_IO, e);
@@ -126,14 +126,14 @@ public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, i
126126
* Read the specified input stream using the specified loader, and
127127
* return the device independent image array represented by the stream.
128128
*/
129-
public static List<ElementAtZoom<ImageData>> load(InputStream is, ImageLoader loader, int fileZoom, int targetZoom) {
129+
public static List<ElementAtZoom<ImageData>> load(InputStream is, ImageLoader loader, int fileZoom, int targetZoom, int flag) {
130130
LEDataInputStream stream = new LEDataInputStream(is);
131131
FileFormat fileFormat = determineFileFormat(stream).orElseGet(() -> {
132132
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
133133
return null;
134134
});
135135
fileFormat.loader = loader;
136-
return fileFormat.loadFromStream(stream, fileZoom, targetZoom);
136+
return fileFormat.loadFromStream(stream, fileZoom, targetZoom, flag);
137137
}
138138

139139
/**

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/SVGFileFormat.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ boolean isFileFormat(LEDataInputStream stream) throws IOException {
4343
}
4444

4545
@Override
46-
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom) {
46+
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom, int flag) {
4747
if (RASTERIZER == null) {
4848
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT, null, " [No SVG rasterizer found]");
4949
}
5050
if (targetZoom <= 0) {
5151
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, " [Cannot rasterize SVG for zoom <= 0]");
5252
}
5353
try {
54-
ImageData rasterizedImageData = RASTERIZER.rasterizeSVG(inputStream, 100 * targetZoom / fileZoom);
54+
ImageData rasterizedImageData = RASTERIZER.rasterizeSVG(inputStream, 100 * targetZoom / fileZoom, flag);
5555
return List.of(new ElementAtZoom<>(rasterizedImageData, targetZoom));
5656
} catch (IOException e) {
5757
SWT.error(SWT.ERROR_INVALID_IMAGE, e);

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/SVGRasterizer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ public interface SVGRasterizer {
3131
* @return the {@link ImageData} for the rasterized image, or {@code null} if
3232
* the input is not a valid SVG file or cannot be processed.
3333
*/
34-
public ImageData rasterizeSVG(InputStream stream, int zoom) throws IOException;
34+
public ImageData rasterizeSVG(InputStream stream, int zoom, int flag) throws IOException;
3535
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ ImageData loadIcon(int[] iconHeader) {
133133
StaticImageFileFormat png = new PNGFileFormat();
134134
if (png.isFileFormat(inputStream)) {
135135
png.loader = this.loader;
136-
return png.loadFromStream(inputStream, DEFAULT_ZOOM, DEFAULT_ZOOM).get(0).element();
136+
return png.loadFromStream(inputStream, DEFAULT_ZOOM, DEFAULT_ZOOM, SWT.IMAGE_COPY).get(0).element();
137137
}
138138
} catch (Exception e) {
139139
}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ public Image(Device device, Image srcImage, int flag) {
247247
long srcImageHandle = win32_getHandle(srcImage, getZoom());
248248
switch (flag) {
249249
case SWT.IMAGE_COPY: {
250+
if(createWithSVG(device, flag)) {
251+
break;
252+
}
250253
switch (type) {
251254
case SWT.BITMAP:
252255
/* Get the HDC for the device */
@@ -282,12 +285,18 @@ public Image(Device device, Image srcImage, int flag) {
282285
break;
283286
}
284287
case SWT.IMAGE_DISABLE: {
288+
if(createWithSVG(device, flag)) {
289+
break;
290+
}
285291
ImageData data = srcImage.getImageData(srcImage.getZoom());
286292
ImageData newData = applyDisableImageData(data, rect.height, rect.width);
287293
init (newData, getZoom());
288294
break;
289295
}
290296
case SWT.IMAGE_GRAY: {
297+
if(createWithSVG(device, flag)) {
298+
break;
299+
}
291300
ImageData data = srcImage.getImageData(srcImage.getZoom());
292301
ImageData newData = applyGrayImageData(data, rect.height, rect.width);
293302
init (newData, getZoom());
@@ -300,6 +309,29 @@ public Image(Device device, Image srcImage, int flag) {
300309
this.device.registerResourceWithZoomSupport(this);
301310
}
302311

312+
private boolean createWithSVG(Device device, int flag) {
313+
if (imageProvider instanceof DynamicImageProviderWrapper dynamicImageProvider) {
314+
if (dynamicImageProvider.getProvider() instanceof ImageFileNameProvider imageFileNameProvider) {
315+
ElementAtZoom<String> fileName = DPIUtil.validateAndGetImagePathAtZoom(imageFileNameProvider, getZoom());
316+
// if (fileName.element().endsWith(".svg")) {
317+
ElementAtZoom<ImageData> imageData = ImageDataLoader.load(fileName.element(), fileName.zoom(), getZoom(),
318+
flag);
319+
init(imageData.element(), getZoom());
320+
return true;
321+
// }
322+
}
323+
// else if (imageProvider.getProvider() instanceof ImageDataProvider imageDataProvider) {
324+
// if (imageDataProvider.supportsRasterizationFlag(flag)) {
325+
// ImageData data = imageDataProvider.getCustomizedImageData(getZoom(), flag);
326+
// ElementAtZoom<ImageData> imageData = new ElementAtZoom<>(data, getZoom());
327+
// init(imageData.element(), getZoom());
328+
// return true;
329+
// }
330+
// }
331+
}
332+
return false;
333+
}
334+
303335
/**
304336
* Constructs an empty instance of this class with the
305337
* width and height of the specified rectangle. The result
@@ -2221,7 +2253,7 @@ ImageData getImageData(int zoom) {
22212253

22222254
ElementAtZoom<ImageData> imageDataAtZoom;
22232255
if (nativeInitializedImage == null) {
2224-
imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom);
2256+
imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom, SWT.IMAGE_COPY);
22252257
} else {
22262258
imageDataAtZoom = new ElementAtZoom<>(nativeInitializedImage.getImageData(), fileForZoom.zoom());
22272259
destroyHandleForZoom(zoom);

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/InternalImageLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
class InternalImageLoader {
2323

24-
static List<ElementAtZoom<ImageData>> load(InputStream stream, ImageLoader imageLoader, int fileZoom, int targetZoom) {
25-
return FileFormat.load(stream, imageLoader, fileZoom, targetZoom);
24+
static List<ElementAtZoom<ImageData>> load(InputStream stream, ImageLoader imageLoader, int fileZoom, int targetZoom, int flag) {
25+
return FileFormat.load(stream, imageLoader, fileZoom, targetZoom, flag);
2626
}
2727

2828
static void save(OutputStream stream, int format, ImageLoader imageLoader) {

0 commit comments

Comments
 (0)