001 /*
002 * Copyright 2002 - 2008 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: PreloaderMathML.java,v 32023847f457 2009/03/20 14:20:15 maxberger $ */
018
019 package net.sourceforge.jeuclid.xmlgraphics;
020
021 import java.awt.Graphics2D;
022 import java.awt.Image;
023 import java.awt.image.BufferedImage;
024 import java.io.IOException;
025 import java.io.InputStream;
026
027 import javax.xml.transform.Source;
028 import javax.xml.transform.dom.DOMSource;
029 import javax.xml.transform.stream.StreamSource;
030
031 import net.sourceforge.jeuclid.Constants;
032 import net.sourceforge.jeuclid.context.LayoutContextImpl;
033 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
034 import net.sourceforge.jeuclid.elements.generic.MathImpl;
035 import net.sourceforge.jeuclid.layout.JEuclidView;
036 import net.sourceforge.jeuclid.parser.Parser;
037
038 import org.apache.commons.logging.Log;
039 import org.apache.commons.logging.LogFactory;
040 import org.apache.fop.util.UnclosableInputStream;
041 import org.apache.xmlgraphics.image.loader.ImageContext;
042 import org.apache.xmlgraphics.image.loader.ImageException;
043 import org.apache.xmlgraphics.image.loader.ImageInfo;
044 import org.apache.xmlgraphics.image.loader.ImageSize;
045 import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
046 import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
047 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
048 import org.w3c.dom.Document;
049 import org.w3c.dom.Element;
050 import org.xml.sax.SAXException;
051
052 /**
053 * @version $Revision: 32023847f457 $
054 */
055 public class PreloaderMathML extends AbstractImagePreloader {
056 /**
057 * Convert from point to millipoint.
058 */
059 public static final float MPT_FACTOR = 1000.0f;
060
061 /**
062 * Logger for this class
063 */
064 private static final Log LOGGER = LogFactory
065 .getLog(PreloaderMathML.class);
066
067 /**
068 * Default Constructor.
069 */
070 public PreloaderMathML() {
071 // Empty on purpose
072 }
073
074 /** {@inheritDoc} */
075 public ImageInfo preloadImage(final String uri, final Source src,
076 final ImageContext context) throws ImageException, IOException {
077 final Document n = this.parseSource(src);
078 if (n != null) {
079 return this.createImageInfo(uri, context, n);
080 }
081
082 return null;
083 }
084
085 @SuppressWarnings("unchecked")
086 private ImageInfo createImageInfo(final String uri,
087 final ImageContext context, final Document n) {
088 final ImageInfo info = new ImageInfo(uri, Constants.MATHML_MIMETYPE);
089 final ImageSize size = new ImageSize();
090 final Image tempimage = new BufferedImage(1, 1,
091 BufferedImage.TYPE_INT_ARGB);
092 final Graphics2D tempg = (Graphics2D) tempimage.getGraphics();
093 final JEuclidView view = new JEuclidView(n, LayoutContextImpl
094 .getDefaultLayoutContext(), tempg);
095 final int descentMpt = (int) (view.getDescentHeight() * PreloaderMathML.MPT_FACTOR);
096 final int ascentMpt = (int) (view.getAscentHeight() * PreloaderMathML.MPT_FACTOR);
097
098 size.setSizeInMillipoints(
099 (int) (view.getWidth() * PreloaderMathML.MPT_FACTOR),
100 ascentMpt + descentMpt);
101 size.setBaselinePositionFromBottom(descentMpt);
102 // Set the resolution to that of the FOUserAgent
103 size.setResolution(context.getSourceResolution());
104 size.calcPixelsFromSize();
105 info.setSize(size);
106
107 // The whole image had to be loaded for this, so keep it
108 final ImageXMLDOM xmlImage = new ImageXMLDOM(info, n,
109 AbstractJEuclidElement.URI);
110 info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage);
111 return info;
112 }
113
114 private Document parseSource(final Source src) {
115 Document n = null;
116 InputStream in = null;
117 try {
118 if (src instanceof DOMSource) {
119 final DOMSource domSrc = (DOMSource) src;
120 n = (Document) domSrc.getNode();
121 } else {
122 in = new UnclosableInputStream(ImageUtil.needInputStream(src));
123 final int length = in.available();
124 in.mark(length + 1);
125 n = Parser.getInstance().parseStreamSource(
126 new StreamSource(in));
127 }
128 final Element rootNode = n.getDocumentElement();
129 if (!(AbstractJEuclidElement.URI.equals(rootNode
130 .getNamespaceURI()) || MathImpl.ELEMENT.equals(rootNode
131 .getNodeName()))) {
132 n = null;
133 }
134 } catch (final IOException e) {
135 n = null;
136 } catch (final SAXException e) {
137 n = null;
138 } catch (final IllegalArgumentException e) {
139 n = null;
140 } catch (final NullPointerException e) {
141 // Due to a bug in xmlgraphics-commons 1.3.1 which sometimes
142 // creates wrapper around null streams if files do not exist.
143 n = null;
144 }
145 try {
146 if (in != null) {
147 in.reset();
148 }
149 } catch (final IOException ioe) {
150 PreloaderMathML.LOGGER.warn("Should never happen: "
151 + ioe.getMessage());
152 } catch (final NullPointerException e) {
153 // Due to a bug in xmlgraphics-commons 1.3.1 which sometimes
154 // creates wrapper around null streams if files do not exist.
155 n = null;
156 }
157 return n;
158 }
159 }