]> git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.swt/src/org/argeo/app/swt/osgi/BundleSvgTheme.java
Releasing
[gpl/argeo-suite.git] / swt / org.argeo.app.swt / src / org / argeo / app / swt / osgi / BundleSvgTheme.java
1 package org.argeo.app.swt.osgi;
2
3 import java.awt.Color;
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;
12 import java.util.Map;
13 import java.util.Objects;
14
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.argeo.cms.swt.osgi.BundleCmsSwtTheme;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.ImageData;
23 import org.eclipse.swt.widgets.Display;
24 import org.osgi.framework.BundleContext;
25
26 /** Theme which can dynamically create icons from SVG data. */
27 public class BundleSvgTheme extends BundleCmsSwtTheme {
28 private final static Logger logger = System.getLogger(BundleSvgTheme.class.getName());
29
30 private Map<String, Map<Integer, ImageData>> imageDataCache = Collections.synchronizedMap(new HashMap<>());
31
32 private Map<Integer, ImageTranscoder> transcoders = Collections.synchronizedMap(new HashMap<>());
33
34 private final static String IMAGE_CACHE_KEY = BundleSvgTheme.class.getName() + ".imageCache";
35
36 @Override
37 public Image getIcon(String name, Integer preferredSize) {
38 String path = "icons/types/svg/" + name + ".svg";
39 return createImageFromSvg(path, preferredSize);
40 }
41
42 @SuppressWarnings("unchecked")
43 protected Image createImageFromSvg(String path, Integer preferredSize) {
44 Display display = Display.getCurrent();
45 Objects.requireNonNull(display, "Not a user interface thread");
46
47 Map<String, Map<Integer, Image>> imageCache = (Map<String, Map<Integer, Image>>) display
48 .getData(IMAGE_CACHE_KEY);
49 if (imageCache == null)
50 display.setData(IMAGE_CACHE_KEY, new HashMap<String, Map<Integer, Image>>());
51 imageCache = (Map<String, Map<Integer, Image>>) display.getData(IMAGE_CACHE_KEY);
52
53 Image image = null;
54 if (imageCache.containsKey(path)) {
55 image = imageCache.get(path).get(preferredSize);
56 }
57 if (image != null)
58 return image;
59 ImageData imageData = loadFromSvg(path, preferredSize);
60 image = new Image(display, imageData);
61 if (!imageCache.containsKey(path))
62 imageCache.put(path, Collections.synchronizedMap(new HashMap<>()));
63 imageCache.get(path).put(preferredSize, image);
64 return image;
65 }
66
67 protected ImageData loadFromSvg(String path, int size) {
68 ImageData imageData = null;
69 if (imageDataCache.containsKey(path))
70 imageData = imageDataCache.get(path).get(size);
71 if (imageData != null)
72 return imageData;
73
74 ImageTranscoder transcoder = null;
75 synchronized (this) {
76 transcoder = transcoders.get(size);
77 if (transcoder == null) {
78 transcoder = new PNGTranscoder();
79 transcoder.addTranscodingHint(PNGTranscoder.KEY_WIDTH, (float) size);
80 transcoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, (float) size);
81 transcoder.addTranscodingHint(PNGTranscoder.KEY_BACKGROUND_COLOR, new Color(255, 255, 255, 0));
82 transcoders.put(size, transcoder);
83 }
84 }
85 try (InputStream in = getResourceAsStream(path); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
86 if (in == null)
87 throw new IllegalArgumentException(path + " not found");
88 TranscoderInput input = new TranscoderInput(in);
89 TranscoderOutput output = new TranscoderOutput(out);
90 transcoder.transcode(input, output);
91 try (InputStream imageIn = new ByteArrayInputStream(out.toByteArray())) {
92 imageData = new ImageData(imageIn);
93 }
94 logger.log(Level.DEBUG, () -> "Generated " + size + "x" + size + " PNG icon from " + path);
95 } catch (IOException | TranscoderException e) {
96 throw new RuntimeException("Cannot transcode SVG " + path, e);
97 }
98
99 // cache it
100 if (!imageDataCache.containsKey(path))
101 imageDataCache.put(path, Collections.synchronizedMap(new HashMap<>()));
102 imageDataCache.get(path).put(size, imageData);
103
104 return imageData;
105 }
106
107 @Override
108 public void init(BundleContext bundleContext, Map<String, String> properties) {
109 super.init(bundleContext, properties);
110
111 // preload all icons
112 // paths: for (String p : getImagesPaths()) {
113 // if (!p.endsWith(".svg"))
114 // continue paths;
115 // createImageFromSvg(p, getDefaultIconSize());
116 // }
117 }
118
119 // @Override
120 // public void destroy(BundleContext bundleContext, Map<String, String> properties) {
121 // Display display = Display.getDefault();
122 // if (display != null)
123 // for (String path : imageCache.keySet()) {
124 // for (Image image : imageCache.get(path).values()) {
125 // display.syncExec(() -> image.dispose());
126 // }
127 // }
128 // super.destroy(bundleContext, properties);
129 // }
130
131 }