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 371548310efa 2010/08/09 21:15:33 max $ */
018
019 package net.sourceforge.jeuclid.xmlgraphics;
020
021 import java.io.IOException;
022 import java.io.InputStream;
023
024 import javax.xml.transform.Source;
025 import javax.xml.transform.dom.DOMSource;
026 import javax.xml.transform.stream.StreamSource;
027
028 import net.sourceforge.jeuclid.Constants;
029 import net.sourceforge.jeuclid.context.LayoutContextImpl;
030 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
031 import net.sourceforge.jeuclid.elements.generic.MathImpl;
032 import net.sourceforge.jeuclid.layout.JEuclidView;
033 import net.sourceforge.jeuclid.parser.Parser;
034
035 import org.apache.commons.logging.Log;
036 import org.apache.commons.logging.LogFactory;
037 import org.apache.fop.util.UnclosableInputStream;
038 import org.apache.xmlgraphics.image.loader.ImageContext;
039 import org.apache.xmlgraphics.image.loader.ImageException;
040 import org.apache.xmlgraphics.image.loader.ImageInfo;
041 import org.apache.xmlgraphics.image.loader.ImageSize;
042 import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
043 import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
044 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
045 import org.w3c.dom.Document;
046 import org.w3c.dom.Element;
047 import org.xml.sax.SAXException;
048
049 /**
050 * @version $Revision: 371548310efa $
051 */
052 public class PreloaderMathML extends AbstractImagePreloader {
053 /**
054 * Convert from point to millipoint.
055 */
056 public static final float MPT_FACTOR = 1000.0f;
057
058 /**
059 * Logger for this class
060 */
061 private static final Log LOGGER = LogFactory
062 .getLog(PreloaderMathML.class);
063
064 /**
065 * Default Constructor.
066 */
067 public PreloaderMathML() {
068 // Empty on purpose
069 }
070
071 /** {@inheritDoc} */
072 public ImageInfo preloadImage(final String uri, final Source src,
073 final ImageContext context) throws ImageException, IOException {
074 final Document n = this.parseSource(src);
075 if (n != null) {
076 return this.createImageInfo(uri, context, n);
077 }
078
079 return null;
080 }
081
082 @SuppressWarnings("unchecked")
083 private ImageInfo createImageInfo(final String uri,
084 final ImageContext context, final Document n) {
085 final ImageInfo info = new ImageInfo(uri, Constants.MATHML_MIMETYPE);
086 final ImageSize size = new ImageSize();
087 final JEuclidView view = new JEuclidView(n, LayoutContextImpl
088 .getDefaultLayoutContext(), null);
089 final int descentMpt = (int) (view.getDescentHeight() * PreloaderMathML.MPT_FACTOR);
090 final int ascentMpt = (int) (view.getAscentHeight() * PreloaderMathML.MPT_FACTOR);
091
092 size.setSizeInMillipoints(
093 (int) (view.getWidth() * PreloaderMathML.MPT_FACTOR),
094 ascentMpt + descentMpt);
095 size.setBaselinePositionFromBottom(descentMpt);
096 // Set the resolution to that of the FOUserAgent
097 size.setResolution(context.getSourceResolution());
098 size.calcPixelsFromSize();
099 info.setSize(size);
100
101 // The whole image had to be loaded for this, so keep it
102 final ImageXMLDOM xmlImage = new ImageXMLDOM(info, n,
103 AbstractJEuclidElement.URI);
104 info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage);
105 return info;
106 }
107
108 private Document parseSource(final Source src) {
109 Document n = null;
110 InputStream in = null;
111 try {
112 if (src instanceof DOMSource) {
113 final DOMSource domSrc = (DOMSource) src;
114 n = (Document) domSrc.getNode();
115 } else {
116 in = new UnclosableInputStream(ImageUtil.needInputStream(src));
117 final int length = in.available();
118 in.mark(length + 1);
119 n = Parser.getInstance().parseStreamSource(
120 new StreamSource(in));
121 }
122 final Element rootNode = n.getDocumentElement();
123 if (!(AbstractJEuclidElement.URI.equals(rootNode
124 .getNamespaceURI()) || MathImpl.ELEMENT.equals(rootNode
125 .getNodeName()))) {
126 n = null;
127 }
128 } catch (final IOException e) {
129 n = null;
130 } catch (final SAXException e) {
131 n = null;
132 } catch (final IllegalArgumentException e) {
133 n = null;
134 } catch (final NullPointerException e) {
135 // Due to a bug in xmlgraphics-commons 1.3.1 which sometimes
136 // creates wrapper around null streams if files do not exist.
137 n = null;
138 }
139 try {
140 if (in != null) {
141 in.reset();
142 }
143 } catch (final IOException ioe) {
144 PreloaderMathML.LOGGER.warn("Should never happen: "
145 + ioe.getMessage());
146 } catch (final NullPointerException e) {
147 // Due to a bug in xmlgraphics-commons 1.3.1 which sometimes
148 // creates wrapper around null streams if files do not exist.
149 n = null;
150 }
151 return n;
152 }
153 }