1 package org
.argeo
.cms
.swt
.osgi
;
4 import java
.io
.ByteArrayInputStream
;
5 import java
.io
.ByteArrayOutputStream
;
6 import java
.io
.IOException
;
7 import java
.io
.InputStream
;
8 import java
.lang
.System
.Logger
;
9 import java
.lang
.System
.Logger
.Level
;
10 import java
.util
.Collections
;
11 import java
.util
.HashMap
;
13 import java
.util
.Objects
;
15 import org
.apache
.batik
.transcoder
.TranscoderException
;
16 import org
.apache
.batik
.transcoder
.TranscoderInput
;
17 import org
.apache
.batik
.transcoder
.TranscoderOutput
;
18 import org
.apache
.batik
.transcoder
.image
.ImageTranscoder
;
19 import org
.apache
.batik
.transcoder
.image
.PNGTranscoder
;
20 import org
.eclipse
.swt
.graphics
.Image
;
21 import org
.eclipse
.swt
.graphics
.ImageData
;
22 import org
.eclipse
.swt
.widgets
.Display
;
23 import org
.osgi
.framework
.BundleContext
;
25 /** Theme which can dynamically create icons from SVG data. */
26 public class BundleSvgTheme
extends BundleCmsSwtTheme
{
27 private final static Logger logger
= System
.getLogger(BundleSvgTheme
.class.getName());
29 private Map
<String
, Map
<Integer
, ImageData
>> imageDataCache
= Collections
.synchronizedMap(new HashMap
<>());
31 private Map
<Integer
, ImageTranscoder
> transcoders
= Collections
.synchronizedMap(new HashMap
<>());
33 private final static String IMAGE_CACHE_KEY
= BundleSvgTheme
.class.getName() + ".imageCache";
36 public Image
getIcon(String name
, Integer preferredSize
) {
37 String path
= "icons/types/svg/" + name
+ ".svg";
38 return createImageFromSvg(path
, preferredSize
);
41 @SuppressWarnings("unchecked")
42 protected Image
createImageFromSvg(String path
, Integer preferredSize
) {
43 Display display
= Display
.getCurrent();
44 Objects
.requireNonNull(display
, "Not a user interface thread");
46 Map
<String
, Map
<Integer
, Image
>> imageCache
= (Map
<String
, Map
<Integer
, Image
>>) display
47 .getData(IMAGE_CACHE_KEY
);
48 if (imageCache
== null)
49 display
.setData(IMAGE_CACHE_KEY
, new HashMap
<String
, Map
<Integer
, Image
>>());
50 imageCache
= (Map
<String
, Map
<Integer
, Image
>>) display
.getData(IMAGE_CACHE_KEY
);
53 if (imageCache
.containsKey(path
)) {
54 image
= imageCache
.get(path
).get(preferredSize
);
58 ImageData imageData
= loadFromSvg(path
, preferredSize
);
59 image
= new Image(display
, imageData
);
60 if (!imageCache
.containsKey(path
))
61 imageCache
.put(path
, Collections
.synchronizedMap(new HashMap
<>()));
62 imageCache
.get(path
).put(preferredSize
, image
);
66 protected ImageData
loadFromSvg(String path
, int size
) {
67 ImageData imageData
= null;
68 if (imageDataCache
.containsKey(path
))
69 imageData
= imageDataCache
.get(path
).get(size
);
70 if (imageData
!= null)
73 ImageTranscoder transcoder
= null;
75 transcoder
= transcoders
.get(size
);
76 if (transcoder
== null) {
77 transcoder
= new PNGTranscoder();
78 transcoder
.addTranscodingHint(PNGTranscoder
.KEY_WIDTH
, (float) size
);
79 transcoder
.addTranscodingHint(PNGTranscoder
.KEY_HEIGHT
, (float) size
);
80 transcoder
.addTranscodingHint(PNGTranscoder
.KEY_BACKGROUND_COLOR
, new Color(255, 255, 255, 0));
81 transcoders
.put(size
, transcoder
);
84 try (InputStream in
= getResourceAsStream(path
); ByteArrayOutputStream out
= new ByteArrayOutputStream();) {
86 throw new IllegalArgumentException(path
+ " not found");
87 TranscoderInput input
= new TranscoderInput(in
);
88 TranscoderOutput output
= new TranscoderOutput(out
);
89 transcoder
.transcode(input
, output
);
90 try (InputStream imageIn
= new ByteArrayInputStream(out
.toByteArray())) {
91 imageData
= new ImageData(imageIn
);
93 logger
.log(Level
.DEBUG
, () -> "Generated " + size
+ "x" + size
+ " PNG icon from " + path
);
94 } catch (IOException
| TranscoderException e
) {
95 throw new RuntimeException("Cannot transcode SVG " + path
, e
);
99 if (!imageDataCache
.containsKey(path
))
100 imageDataCache
.put(path
, Collections
.synchronizedMap(new HashMap
<>()));
101 imageDataCache
.get(path
).put(size
, imageData
);
107 public void init(BundleContext bundleContext
, Map
<String
, String
> properties
) {
108 super.init(bundleContext
, properties
);
111 // paths: for (String p : getImagesPaths()) {
112 // if (!p.endsWith(".svg"))
114 // createImageFromSvg(p, getDefaultIconSize());
119 // public void destroy(BundleContext bundleContext, Map<String, String> properties) {
120 // Display display = Display.getDefault();
121 // if (display != null)
122 // for (String path : imageCache.keySet()) {
123 // for (Image image : imageCache.get(path).values()) {
124 // display.syncExec(() -> image.dispose());
127 // super.destroy(bundleContext, properties);