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    }