/* * $Id$ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ package org.apache.fop.apps; import org.xml.sax.*; import com.jclark.xsl.sax.*; import java.io.*; // FOP import org.apache.fop.fo.XTFOTreeBuilder; import org.apache.fop.fo.XTElementMapping; import org.apache.fop.layout.AreaTree; import org.apache.fop.layout.FontInfo; import org.apache.fop.render.Renderer; import org.apache.fop.messaging.MessageHandler; // //////////////////////////////////////////////////////////////////////////////////// /** * A DocumentHandler that writes a PDF representation to an OutputStream. * * Use with James Clark's XT. Just put FOP on your class path and add * <xsl:output method="fop:org.apache.fop.apps.PDFOutputHandler" * xmlns:fop="http://www.jclark.com/xt/java"/> * to your stylesheet. Now XT will automatically call FOP. * */ public class PDFOutputHandler extends XTFOTreeBuilder implements OutputDocumentHandler { /** * the area tree that is the result of formatting the FO tree */ protected AreaTree areaTree; /** * the renderer to use to output the area tree */ protected Renderer renderer; /** * the PrintWriter to use to output the results of the renderer */ protected PrintWriter writer; /** * the stream to use to output the results of the renderer */ protected OutputStream stream; private boolean keepOpen; // //////////////////////////////////////////////////////////////////////////////////// /** */ public PDFOutputHandler() {} // //////////////////////////////////////////////////////////////////////////////////// /** */ public PDFOutputHandler(OutputStream out) { this(); this.stream = out; } // //////////////////////////////////////////////////////////////////////////////////// /** */ public DocumentHandler init(Destination dest, AttributeList atts) throws IOException { this.stream = dest.getOutputStream("application/pdf", null); this.keepOpen = dest.keepOpen(); String version = org.apache.fop.apps.Version.getVersion(); setRenderer("org.apache.fop.render.pdf.PDFRenderer", version); addElementMapping("org.apache.fop.fo.StandardElementMapping"); addElementMapping("org.apache.fop.svg.SVGElementMapping"); return this; } // //////////////////////////////////////////////////////////////////////////////////// /** * set the class name of the Renderer to use as well as the * producer string for those renderers that can make use of it */ public void setRenderer(String rendererClassName, String producer) { this.renderer = createRenderer(rendererClassName); this.renderer.setProducer(producer); } // //////////////////////////////////////////////////////////////////////////////////// /** * SAX passthrough, finish rendering the document */ public void endDocument() throws SAXException { super.endDocument(); try { doFormat(); doRender(); } catch (IOException io) { throw new SAXException(io); } catch (FOPException fop) { throw new SAXException(fop); } writer.flush(); } // //////////////////////////////////////////////////////////////////////////////////// /** * format the formatting object tree into an area tree */ public void doFormat() throws FOPException { FontInfo fontInfo = new FontInfo(); this.renderer.setupFontInfo(fontInfo); this.areaTree = new AreaTree(); this.areaTree.setFontInfo(fontInfo); format(areaTree); } // //////////////////////////////////////////////////////////////////////////////////// /** * render the area tree to the output form */ public void doRender() throws IOException, FOPException { this.renderer.render(areaTree, this.stream); } // //////////////////////////////////////////////////////////////////////////////////// /** * add the given element mapping. * * an element mapping maps element names to Java classes */ public void addElementMapping(XTElementMapping mapping) { mapping.addToBuilder(this); } // //////////////////////////////////////////////////////////////////////////////////// /** * add the element mapping with the given class name */ public void addElementMapping(String mappingClassName) { createElementMapping(mappingClassName).addToBuilder(this); } // //////////////////////////////////////////////////////////////////////////////////// /** * protected method used by addElementMapping(String) to * instantiate element mapping class */ protected XTElementMapping createElementMapping(String mappingClassName) { MessageHandler.logln("using element mapping " + mappingClassName); try { return (XTElementMapping)Class.forName(mappingClassName).newInstance(); } catch (ClassNotFoundException e) { MessageHandler.errorln("Could not find " + mappingClassName); } catch (InstantiationException e) { MessageHandler.errorln("Could not instantiate " + mappingClassName); } catch (IllegalAccessException e) { MessageHandler.errorln("Could not access " + mappingClassName); } catch (ClassCastException e) { MessageHandler.errorln(mappingClassName + " is not an element mapping"); } return null; } // //////////////////////////////////////////////////////////////////////////////////// /** * protected method used by setRenderer(String, String) to * instantiate the Renderer class */ protected Renderer createRenderer(String rendererClassName) { MessageHandler.logln("using renderer " + rendererClassName); try { return (Renderer)Class.forName(rendererClassName).newInstance(); } catch (ClassNotFoundException e) { MessageHandler.errorln("Could not find " + rendererClassName); } catch (InstantiationException e) { MessageHandler.errorln("Could not instantiate " + rendererClassName); } catch (IllegalAccessException e) { MessageHandler.errorln("Could not access " + rendererClassName); } catch (ClassCastException e) { MessageHandler.errorln(rendererClassName + " is not a renderer"); } return null; } }