Skip to content

Commit b85ad40

Browse files
committed
disabled icon logic
disabled icon logic
1 parent c088611 commit b85ad40

File tree

24 files changed

+1854
-35
lines changed

24 files changed

+1854
-35
lines changed

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

+1-1
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.129.0.qualifier
6+
Bundle-Version: 4.0.0.qualifier
77
Bundle-ManifestVersion: 2
88
Bundle-Localization: fragment
99
Export-Package:
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
4+
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
5+
<classpathentry kind="src" path="src"/>
6+
<classpathentry kind="lib" path="libs/jsvg-1.6.1.jar"/>
7+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.win32.win32.x86_64"/>
8+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.win32.win32.aarch64"/>
9+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.gtk.linux.x86_64"/>
10+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.gtk.linux.riscv64"/>
11+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.gtk.linux.ppc64le"/>
12+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.gtk.linux.loongarch64"/>
13+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.gtk.linux.aarch64"/>
14+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.cocoa.macosx.x86_64"/>
15+
<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.swt.cocoa.macosx.aarch64"/>
16+
<classpathentry kind="output" path="bin"/>
17+
</classpath>

bundles/org.eclipse.swt.svg/.project

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>org.eclipse.swt.svg</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.jdt.core.javabuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.pde.ManifestBuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
<buildCommand>
19+
<name>org.eclipse.pde.SchemaBuilder</name>
20+
<arguments>
21+
</arguments>
22+
</buildCommand>
23+
</buildSpec>
24+
<natures>
25+
<nature>org.eclipse.pde.PluginNature</nature>
26+
<nature>org.eclipse.jdt.core.javanature</nature>
27+
</natures>
28+
</projectDescription>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
eclipse.preferences.version=1
2+
encoding/<project>=UTF-8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
3+
org.eclipse.jdt.core.compiler.compliance=17
4+
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
5+
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
6+
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7+
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
8+
org.eclipse.jdt.core.compiler.release=enabled
9+
org.eclipse.jdt.core.compiler.source=17
10+
org.eclipse.jdt.core.incompleteClasspath=warning
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Manifest-Version: 1.0
2+
Bundle-ManifestVersion: 2
3+
Bundle-Name: SvgPlugin
4+
Bundle-SymbolicName: org.eclipse.swt.svg
5+
Bundle-Version: 1.0.0.qualifier
6+
Automatic-Module-Name: org.eclipse.swt.svgPlugin
7+
Bundle-RequiredExecutionEnvironment: JavaSE-17
8+
Fragment-Host: org.eclipse.swt
9+
Export-Package: org.eclipse.swt.svg
10+
Bundle-ClassPath: ., libs/jsvg-1.6.1.jar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.eclipse.swt.svg.JSVGRasterizer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
source.. = src/
2+
output.. = bin/
3+
bin.includes = META-INF/,\
4+
.,\
5+
libs/jsvg-1.6.1.jar
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Vector Informatik GmbH and others.
3+
*
4+
* This program and the accompanying materials are made available under the terms of the Eclipse
5+
* Public License 2.0 which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors: Michael Bangas (Vector Informatik GmbH) - initial API and implementation
11+
*******************************************************************************/
12+
package org.eclipse.swt.svg;
13+
14+
import static java.awt.RenderingHints.*;
15+
16+
import java.awt.*;
17+
import java.awt.image.*;
18+
import java.io.*;
19+
import java.util.*;
20+
21+
import javax.xml.parsers.DocumentBuilder;
22+
import javax.xml.parsers.DocumentBuilderFactory;
23+
import javax.xml.parsers.ParserConfigurationException;
24+
import javax.xml.transform.Transformer;
25+
import javax.xml.transform.TransformerException;
26+
import javax.xml.transform.TransformerFactory;
27+
import javax.xml.transform.dom.DOMSource;
28+
import javax.xml.transform.stream.StreamResult;
29+
30+
import org.eclipse.swt.graphics.SVGRasterizer;
31+
import org.eclipse.swt.graphics.ImageData;
32+
import org.eclipse.swt.graphics.PaletteData;
33+
import org.eclipse.swt.graphics.RGB;
34+
import org.w3c.dom.Document;
35+
import org.w3c.dom.Element;
36+
import org.xml.sax.SAXException;
37+
38+
import com.github.weisj.jsvg.*;
39+
import com.github.weisj.jsvg.geometry.size.*;
40+
import com.github.weisj.jsvg.parser.*;
41+
42+
/**
43+
* A rasterizer implementation for converting SVG data into rasterized images.
44+
* This class implements the {@code ISVGRasterizer} interface.
45+
*
46+
* @since 1.0.0
47+
*/
48+
public class JSVGRasterizer implements SVGRasterizer {
49+
50+
private SVGLoader svgLoader;
51+
52+
private final static Map<Key, Object> RENDERING_HINTS = Map.of(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON, //
53+
KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY, //
54+
KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY, //
55+
KEY_DITHERING, VALUE_DITHER_DISABLE, //
56+
KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON, //
57+
KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC, //
58+
KEY_RENDERING, VALUE_RENDER_QUALITY, //
59+
KEY_STROKE_CONTROL, VALUE_STROKE_PURE, //
60+
KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON //
61+
);
62+
63+
@Override
64+
public ImageData rasterizeSVG(InputStream stream, float scalingFactor) throws IOException {
65+
if (stream == null) {
66+
throw new IllegalArgumentException("InputStream cannot be null");
67+
}
68+
if(svgLoader == null) {
69+
svgLoader = new SVGLoader();
70+
}
71+
return rasterize(stream, scalingFactor);
72+
}
73+
74+
@Override
75+
public ImageData rasterizeDisabledSVG(InputStream stream, float scalingFactor) throws IOException {
76+
if(svgLoader == null) {
77+
svgLoader = new SVGLoader();
78+
}
79+
InputStream disabledStream = applyDisabledLook(stream);
80+
return rasterize(disabledStream, scalingFactor);
81+
}
82+
83+
@Override
84+
public ImageData rasterizeGraySVG(InputStream stream, float scalingFactor) throws IOException {
85+
if(svgLoader == null) {
86+
svgLoader = new SVGLoader();
87+
}
88+
InputStream disabledStream = applyGrayLook(stream);
89+
return rasterize(disabledStream, scalingFactor);
90+
}
91+
92+
private ImageData rasterize(InputStream stream, float scalingFactor) throws IOException {
93+
SVGDocument svgDocument = null;
94+
stream.mark(Integer.MAX_VALUE);
95+
InputStream nonClosingStream = new FilterInputStream(stream) {
96+
@Override
97+
public void close() throws IOException {
98+
// Do nothing to prevent closing the underlying stream
99+
}
100+
};
101+
svgDocument = svgLoader.load(nonClosingStream, null, LoaderContext.createDefault());
102+
stream.reset();
103+
if (svgDocument != null) {
104+
FloatSize size = svgDocument.size();
105+
double originalWidth = size.getWidth();
106+
double originalHeight = size.getHeight();
107+
int scaledWidth = (int) Math.round(originalWidth * scalingFactor);
108+
int scaledHeight = (int) Math.round(originalHeight * scalingFactor);
109+
BufferedImage image = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
110+
Graphics2D g = image.createGraphics();
111+
g.setRenderingHints(RENDERING_HINTS);
112+
g.scale(scalingFactor, scalingFactor);
113+
svgDocument.render(null, g);
114+
g.dispose();
115+
return convertToSWT(image);
116+
}
117+
return null;
118+
}
119+
120+
private static InputStream applyDisabledLook(InputStream svgInputStream) throws IOException {
121+
Document svgDocument = parseSVG(svgInputStream);
122+
addDisabledFilter(svgDocument);
123+
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
124+
writeSVG(svgDocument, outputStream);
125+
return new ByteArrayInputStream(outputStream.toByteArray());
126+
}
127+
}
128+
129+
private static InputStream applyGrayLook(InputStream svgInputStream) throws IOException {
130+
Document svgDocument = parseSVG(svgInputStream);
131+
addGrayFilter(svgDocument);
132+
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
133+
writeSVG(svgDocument, outputStream);
134+
return new ByteArrayInputStream(outputStream.toByteArray());
135+
}
136+
}
137+
138+
private static Document parseSVG(InputStream inputStream) throws IOException {
139+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
140+
DocumentBuilder builder;
141+
try {
142+
builder = factory.newDocumentBuilder();
143+
return builder.parse(inputStream);
144+
} catch (SAXException | IOException | ParserConfigurationException e) {
145+
throw new IOException(e.getMessage());
146+
}
147+
}
148+
149+
private static void addDisabledFilter(Document document) {
150+
addFilter(document, 0.64f, 0.4f);
151+
}
152+
153+
private static void addGrayFilter(Document document) {
154+
addFilter(document, 0.64f, 0.1f);
155+
}
156+
157+
private static void addFilter(Document document, float slope, float intercept) {
158+
Element defs = (Element) document.getElementsByTagName("defs").item(0);
159+
if (defs == null) {
160+
defs = document.createElement("defs");
161+
document.getDocumentElement().appendChild(defs);
162+
}
163+
164+
Element filter = document.createElement("filter");
165+
filter.setAttribute("id", "customizedLook");
166+
167+
Element colorMatrix = document.createElement("feColorMatrix");
168+
colorMatrix.setAttribute("type", "saturate");
169+
colorMatrix.setAttribute("values", "0");
170+
filter.appendChild(colorMatrix);
171+
172+
Element componentTransfer = document.createElement("feComponentTransfer");
173+
for (String channel : new String[] { "R", "G", "B" }) {
174+
Element func = document.createElement("feFunc" + channel);
175+
func.setAttribute("type", "linear");
176+
func.setAttribute("slope", Float.toString(slope));
177+
func.setAttribute("intercept", Float.toString(intercept));
178+
componentTransfer.appendChild(func);
179+
}
180+
filter.appendChild(componentTransfer);
181+
defs.appendChild(filter);
182+
document.getDocumentElement().setAttribute("filter", "url(#customizedLook)");
183+
}
184+
185+
private static void writeSVG(Document document, OutputStream outputStream) throws IOException {
186+
TransformerFactory transformerFactory = TransformerFactory.newInstance();
187+
Transformer transformer;
188+
try {
189+
transformer = transformerFactory.newTransformer();
190+
transformer.transform(new DOMSource(document), new StreamResult(outputStream));
191+
} catch (TransformerException e) {
192+
throw new IOException(e.getMessage());
193+
}
194+
}
195+
196+
private ImageData convertToSWT(BufferedImage bufferedImage) {
197+
if (bufferedImage.getColorModel() instanceof DirectColorModel) {
198+
DirectColorModel colorModel = (DirectColorModel)bufferedImage.getColorModel();
199+
PaletteData palette = new PaletteData(
200+
colorModel.getRedMask(),
201+
colorModel.getGreenMask(),
202+
colorModel.getBlueMask());
203+
ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(),
204+
colorModel.getPixelSize(), palette);
205+
for (int y = 0; y < data.height; y++) {
206+
for (int x = 0; x < data.width; x++) {
207+
int rgb = bufferedImage.getRGB(x, y);
208+
int pixel = palette.getPixel(new RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF));
209+
data.setPixel(x, y, pixel);
210+
if (colorModel.hasAlpha()) {
211+
data.setAlpha(x, y, (rgb >> 24) & 0xFF);
212+
}
213+
}
214+
}
215+
return data;
216+
}
217+
else if (bufferedImage.getColorModel() instanceof IndexColorModel) {
218+
IndexColorModel colorModel = (IndexColorModel)bufferedImage.getColorModel();
219+
int size = colorModel.getMapSize();
220+
byte[] reds = new byte[size];
221+
byte[] greens = new byte[size];
222+
byte[] blues = new byte[size];
223+
colorModel.getReds(reds);
224+
colorModel.getGreens(greens);
225+
colorModel.getBlues(blues);
226+
RGB[] rgbs = new RGB[size];
227+
for (int i = 0; i < rgbs.length; i++) {
228+
rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF);
229+
}
230+
PaletteData palette = new PaletteData(rgbs);
231+
ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(),
232+
colorModel.getPixelSize(), palette);
233+
data.transparentPixel = colorModel.getTransparentPixel();
234+
WritableRaster raster = bufferedImage.getRaster();
235+
int[] pixelArray = new int[1];
236+
for (int y = 0; y < data.height; y++) {
237+
for (int x = 0; x < data.width; x++) {
238+
raster.getPixel(x, y, pixelArray);
239+
data.setPixel(x, y, pixelArray[0]);
240+
}
241+
}
242+
return data;
243+
}
244+
else if (bufferedImage.getColorModel() instanceof ComponentColorModel) {
245+
ComponentColorModel colorModel = (ComponentColorModel)bufferedImage.getColorModel();
246+
//ASSUMES: 3 BYTE BGR IMAGE TYPE
247+
PaletteData palette = new PaletteData(0x0000FF, 0x00FF00,0xFF0000);
248+
ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(),
249+
colorModel.getPixelSize(), palette);
250+
//This is valid because we are using a 3-byte Data model with no transparent pixels
251+
data.transparentPixel = -1;
252+
WritableRaster raster = bufferedImage.getRaster();
253+
int[] pixelArray = new int[3];
254+
for (int y = 0; y < data.height; y++) {
255+
for (int x = 0; x < data.width; x++) {
256+
raster.getPixel(x, y, pixelArray);
257+
int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2]));
258+
data.setPixel(x, y, pixel);
259+
}
260+
}
261+
return data;
262+
}
263+
return null;
264+
}
265+
266+
public boolean isSVGFile(InputStream stream) throws IOException {
267+
if (stream == null) {
268+
throw new IllegalArgumentException("InputStream cannot be null");
269+
}
270+
stream.mark(Integer.MAX_VALUE);
271+
try {
272+
int firstByte = stream.read();
273+
return firstByte == '<';
274+
} finally {
275+
stream.reset();
276+
}
277+
}
278+
}

0 commit comments

Comments
 (0)