1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.converter;
20
21 import java.awt.Color;
22 import java.awt.Dimension;
23 import java.awt.Graphics2D;
24 import java.awt.Image;
25 import java.awt.image.BufferedImage;
26 import java.io.BufferedOutputStream;
27 import java.io.File;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31
32 import javax.xml.parsers.ParserConfigurationException;
33
34 import net.sourceforge.jeuclid.LayoutContext;
35 import net.sourceforge.jeuclid.MathMLParserSupport;
36 import net.sourceforge.jeuclid.MutableLayoutContext;
37 import net.sourceforge.jeuclid.context.LayoutContextImpl;
38 import net.sourceforge.jeuclid.converter.ConverterPlugin.DocumentWithDimension;
39 import net.sourceforge.jeuclid.layout.JEuclidView;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Node;
45 import org.xml.sax.SAXException;
46
47
48
49
50
51
52 public final class Converter {
53
54
55
56
57 public static final String TYPE_SVG = "image/svg+xml";
58
59
60
61
62 public static final String EXTENSION_SVG = "svg";
63
64 private static final String UNSUPPORTED_OUTPUT_TYPE = "Unsupported output type: ";
65
66 private static final int MAX_RGB_VALUE = 255;
67
68 private static final class SingletonHolder {
69 private static final Converter INSTANCE = new Converter();
70
71 private SingletonHolder() {
72 }
73 }
74
75
76
77
78 private static final Log LOGGER = LogFactory.getLog(Converter.class);
79
80
81
82
83 protected Converter() {
84
85 }
86
87
88
89
90
91
92 public static Converter getInstance() {
93 return Converter.SingletonHolder.INSTANCE;
94 }
95
96
97
98
99
100 @Deprecated
101 public static Converter getConverter() {
102 return Converter.getInstance();
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public Dimension convert(final File inFile, final File outFile,
119 final String outFileType) throws IOException {
120 final MutableLayoutContext params = new LayoutContextImpl(
121 LayoutContextImpl.getDefaultLayoutContext());
122 return this.convert(inFile, outFile, outFileType, params);
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public Dimension convert(final File inFile, final File outFile,
141 final String outFileType, final LayoutContext params)
142 throws IOException {
143 Document doc;
144 try {
145 doc = MathMLParserSupport.parseFile(inFile);
146 return this.convert(doc, outFile, outFileType, params);
147 } catch (final SAXException e) {
148 Converter.LOGGER.error("Failed to parse file:" + inFile, e);
149 return null;
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 public Dimension convert(final Node doc, final File outFile,
172 final String outFileType, final LayoutContext params)
173 throws IOException {
174
175 final OutputStream outStream = new BufferedOutputStream(
176 new FileOutputStream(outFile));
177 final Dimension result = this.convert(doc, outStream, outFileType,
178 params);
179 if (result == null) {
180 if (!outFile.delete()) {
181 Converter.LOGGER.debug("Could not delete " + outFile);
182 }
183 } else {
184
185 try {
186 outStream.close();
187 } catch (final IOException e) {
188 Converter.LOGGER.debug(e);
189 }
190 }
191 return result;
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 public DocumentWithDimension convert(final Node doc,
211 final String outFileType, final LayoutContext params) {
212 final ConverterPlugin plugin = ConverterRegistry.getInstance()
213 .getConverter(outFileType);
214 DocumentWithDimension result = null;
215 if (plugin != null) {
216 result = plugin.convert(doc, params);
217 }
218 if (result == null) {
219 Converter.LOGGER.fatal(Converter.UNSUPPORTED_OUTPUT_TYPE
220 + outFileType);
221 }
222 return result;
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 public Dimension convert(final Node doc, final OutputStream outStream,
244 final String outFileType, final LayoutContext params)
245 throws IOException {
246 final ConverterPlugin plugin = ConverterRegistry.getInstance()
247 .getConverter(outFileType);
248 Dimension result = null;
249 if (plugin == null) {
250 Converter.LOGGER.fatal(Converter.UNSUPPORTED_OUTPUT_TYPE
251 + outFileType);
252 } else {
253 try {
254 result = plugin.convert(doc, params, outStream);
255 } catch (final IOException ex) {
256 Converter.LOGGER.fatal("Failed to process: " + ex.getMessage(),
257 ex);
258 }
259 }
260 return result;
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 public Dimension convert(final String docString,
280 final OutputStream outStream, final String outFileType,
281 final LayoutContext params) throws IOException {
282
283 Dimension result = null;
284
285 try {
286 final Document doc = MathMLParserSupport.parseString(docString);
287 result = this.convert(doc, outStream, outFileType, params);
288 } catch (final SAXException e) {
289 Converter.LOGGER.error("SAXException converting:" + docString, e);
290 result = null;
291 } catch (final ParserConfigurationException e) {
292 Converter.LOGGER.error("ParserConfigurationException converting:"
293 + docString, e);
294 result = null;
295 }
296
297 return result;
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311 public BufferedImage render(final Node node, final LayoutContext context)
312 throws IOException {
313 return this.render(node, context, BufferedImage.TYPE_INT_ARGB);
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 public BufferedImage render(final Node node, final LayoutContext context,
330 final int imageType) throws IOException {
331 final Image tempimage = new BufferedImage(1, 1, imageType);
332 final Graphics2D tempg = (Graphics2D) tempimage.getGraphics();
333
334 final JEuclidView view = new JEuclidView(node, context, tempg);
335
336 final int width = Math.max(1, (int) Math.ceil(view.getWidth()));
337 final int ascent = (int) Math.ceil(view.getAscentHeight());
338 final int height = Math.max(1, (int) Math.ceil(view.getDescentHeight())
339 + ascent);
340
341 final BufferedImage image = new BufferedImage(width, height, imageType);
342 final Graphics2D g = image.createGraphics();
343
344 final Color background;
345 if (image.getColorModel().hasAlpha()) {
346 background = new Color(Converter.MAX_RGB_VALUE,
347 Converter.MAX_RGB_VALUE, Converter.MAX_RGB_VALUE, 0);
348 } else {
349 background = Color.WHITE;
350 }
351 g.setColor(background);
352 g.fillRect(0, 0, width, height);
353 g.setColor(Color.black);
354
355 view.draw(g, 0, ascent);
356 return image;
357 }
358 }