1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.app.foprep;
20
21 import java.awt.Dimension;
22 import java.io.IOException;
23
24 import javax.xml.parsers.ParserConfigurationException;
25 import javax.xml.transform.Result;
26 import javax.xml.transform.Source;
27 import javax.xml.transform.Transformer;
28 import javax.xml.transform.TransformerException;
29 import javax.xml.transform.TransformerFactory;
30 import javax.xml.transform.dom.DOMResult;
31 import javax.xml.transform.dom.DOMSource;
32
33 import net.sourceforge.jeuclid.DOMBuilder;
34 import net.sourceforge.jeuclid.MathBase;
35 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
36 import net.sourceforge.jeuclid.elements.generic.MathImpl;
37 import net.sourceforge.jeuclid.parser.Parser;
38
39 import org.apache.batik.dom.GenericDOMImplementation;
40 import org.apache.batik.svggen.SVGGeneratorContext;
41 import org.apache.batik.svggen.SVGGraphics2D;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.w3c.dom.DOMImplementation;
45 import org.w3c.dom.Document;
46 import org.w3c.dom.Element;
47 import org.w3c.dom.Node;
48 import org.w3c.dom.NodeList;
49 import org.xml.sax.SAXException;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public final class Processor {
66
67 private static Processor processor;
68
69
70
71
72 private static final Log LOGGER = LogFactory.getLog(Processor.class);
73
74 private final Transformer transformer;
75
76 private Processor() throws TransformerException {
77 this.transformer = TransformerFactory.newInstance().newTransformer();
78 }
79
80
81
82
83
84
85
86
87
88 public static synchronized Processor getProcessor()
89 throws TransformerException {
90 if (Processor.processor == null) {
91 Processor.processor = new Processor();
92 }
93 return Processor.processor;
94 }
95
96
97
98
99
100
101
102
103
104
105
106 public void process(final Source inputSource, final Result result)
107 throws TransformerException {
108 Processor.LOGGER.info("Processing " + inputSource + " to " + result);
109 try {
110 final Node doc = Parser.getParser().parse(inputSource);
111
112 this.processSubtree(doc);
113
114 final DOMSource source = new DOMSource(doc);
115
116 this.transformer.transform(source, result);
117
118 } catch (final IOException e) {
119 throw new TransformerException("IOException", e);
120 } catch (final SAXException e) {
121 throw new TransformerException("SAXException", e);
122 } catch (final ParserConfigurationException e) {
123 throw new TransformerException("ParserConfigurationException", e);
124 }
125 }
126
127 private void processSubtree(final Node node) {
128 if (AbstractJEuclidElement.URI.equals(node.getNamespaceURI())
129 && MathImpl.ELEMENT.equals(node.getLocalName())) {
130
131 final MathBase mathBase = new MathBase(MathBase
132 .getDefaultParameters());
133 new DOMBuilder(node, mathBase);
134
135 final SVGGraphics2D svgGenerator = this
136 .createSVGGenerator(mathBase);
137 mathBase.paint(svgGenerator);
138 final float descender = mathBase.getDescender(svgGenerator);
139
140 final Node parent = node.getParentNode();
141 if ("http://www.w3.org/1999/XSL/Format".equals(parent
142 .getNamespaceURI())
143 && "instream-foreign-object"
144 .equals(parent.getLocalName())) {
145 final Element pElement = (Element) parent;
146 pElement.setAttribute("baseline-shift", -descender + "pt");
147 }
148 this.safeReplaceChild(parent, node, svgGenerator.getRoot());
149 } else {
150 this.processChildren(node);
151 }
152 }
153
154 private SVGGraphics2D createSVGGenerator(final MathBase mathBase) {
155 final DOMImplementation domImpl = GenericDOMImplementation
156 .getDOMImplementation();
157
158 final Document document = domImpl.createDocument(null,
159 net.sourceforge.jeuclid.Converter.EXTENSION_SVG, null);
160 final SVGGeneratorContext svgContext = SVGGeneratorContext
161 .createDefault(document);
162 svgContext.setComment("Converted from MathML using JEuclid");
163 final SVGGraphics2D svgGenerator = new SVGGraphics2D(svgContext, true);
164
165 final Dimension size = new Dimension((int) Math.ceil(mathBase
166 .getWidth(svgGenerator)), (int) Math.ceil(mathBase
167 .getHeight(svgGenerator)));
168 svgGenerator.setSVGCanvasSize(size);
169 return svgGenerator;
170 }
171
172 private void safeReplaceChild(final Node parent, final Node oldChild,
173 final Node newChild) {
174 try {
175 final DOMSource source = new DOMSource(newChild);
176 final DOMResult result = new DOMResult(parent);
177
178 this.transformer.transform(source, result);
179 } catch (final TransformerException e) {
180 Processor.LOGGER.warn("TranformerException: " + e.getMessage());
181 }
182 parent.removeChild(oldChild);
183 }
184
185 private void processChildren(final Node node) {
186 final NodeList childList = node.getChildNodes();
187 if (childList != null) {
188 for (int i = 0; i < childList.getLength(); i++) {
189 final Node child = childList.item(i);
190 this.processSubtree(child);
191 }
192 }
193 }
194
195 }