]> git.argeo.org Git - lgpl/argeo-commons.git/blob - osgi/BundleSvgTheme.java
Prepare next development cycle
[lgpl/argeo-commons.git] / osgi / BundleSvgTheme.java
1 package org.argeo.cms.swt.osgi;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.lang.System.Logger;
8 import java.lang.System.Logger.Level;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.Map;
12
13 import org.apache.batik.transcoder.TranscoderException;
14 import org.apache.batik.transcoder.TranscoderInput;
15 import org.apache.batik.transcoder.TranscoderOutput;
16 import org.apache.batik.transcoder.image.ImageTranscoder;
17 import org.apache.batik.transcoder.image.PNGTranscoder;
18 import org.eclipse.swt.graphics.Image;
19 import org.eclipse.swt.graphics.ImageData;
20 import org.eclipse.swt.widgets.Display;
21 import org.osgi.framework.BundleContext;
22
23 /** Theme which can dynamically create icons from SVG data. */
24 public class BundleSvgTheme extends BundleCmsSwtTheme {
25 private final static Logger logger = System.getLogger(BundleSvgTheme.class.getName());
26
27 private Map<String, Map<Integer, Image>> imageCache = Collections.synchronizedMap(new HashMap<>());
28
29 private Map<Integer, ImageTranscoder> transcoders = Collections.synchronizedMap(new HashMap<>());
30
31 @Override
32 public Image getIcon(String name, Integer preferredSize) {
33 String path = "icons/types/svg/" + name + ".svg";
34 return createImageFromSvg(path, preferredSize);
35 }
36
37 protected Image createImageFromSvg(String path, Integer preferredSize) {
38 Image image = null;
39 if (imageCache.containsKey(path)) {
40 image = imageCache.get(path).get(preferredSize);
41 }
42 if (image != null)
43 return image;
44 ImageData imageData = loadFromSvg(path, preferredSize);
45 image = new Image(Display.getDefault(), imageData);
46 if (!imageCache.containsKey(path))
47 imageCache.put(path, Collections.synchronizedMap(new HashMap<>()));
48 imageCache.get(path).put(preferredSize, image);
49 return image;
50 }
51
52 protected ImageData loadFromSvg(String path, int size) {
53 ImageTranscoder transcoder = null;
54 synchronized (this) {
55 transcoder = transcoders.get(size);
56 if (transcoder == null) {
57 transcoder = new PNGTranscoder();
58 transcoder.addTranscodingHint(PNGTranscoder.KEY_WIDTH, (float) size);
59 transcoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, (float) size);
60 transcoders.put(size, transcoder);
61 }
62 }
63 ImageData imageData;
64 try (InputStream in = getResourceAsStream(path); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
65 if (in == null)
66 throw new IllegalArgumentException(path + " not found");
67 TranscoderInput input = new TranscoderInput(in);
68 TranscoderOutput output = new TranscoderOutput(out);
69 transcoder.transcode(input, output);
70 try (InputStream imageIn = new ByteArrayInputStream(out.toByteArray())) {
71 imageData = new ImageData(imageIn);
72 }
73 logger.log(Level.DEBUG, () -> "Generated " + size + "x" + size + " PNG icon from " + path);
74 } catch (IOException | TranscoderException e) {
75 throw new RuntimeException("Cannot transcode SVG " + path, e);
76 }
77
78 return imageData;
79 }
80
81 @Override
82 public void init(BundleContext bundleContext, Map<String, String> properties) {
83 super.init(bundleContext, properties);
84
85 // preload all icons
86 // paths: for (String p : getImagesPaths()) {
87 // if (!p.endsWith(".svg"))
88 // continue paths;
89 // createImageFromSvg(p, getDefaultIconSize());
90 // }
91 }
92
93 @Override
94 public void destroy(BundleContext bundleContext, Map<String, String> properties) {
95 Display display = Display.getDefault();
96 if (display != null)
97 for (String path : imageCache.keySet()) {
98 for (Image image : imageCache.get(path).values()) {
99 display.syncExec(() -> image.dispose());
100 }
101 }
102 super.destroy(bundleContext, properties);
103 }
104
105 }