123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /*
- * $Id$
- * ============================================================================
- * The Apache Software License, Version 1.1
- * ============================================================================
- *
- * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modifica-
- * tion, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The end-user documentation included with the redistribution, if any, must
- * include the following acknowledgment: "This product includes software
- * developed by the Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself, if
- * and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "FOP" and "Apache Software Foundation" must not be used to
- * endorse or promote products derived from this software without prior
- * written permission. For written permission, please contact
- * apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache", nor may
- * "Apache" appear in their name, without prior written permission of the
- * Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * ============================================================================
- *
- * This software consists of voluntary contributions made by many individuals
- * on behalf of the Apache Software Foundation and was originally created by
- * James Tauber <jtauber@jtauber.com>. For more information on the Apache
- * Software Foundation, please see <http://www.apache.org/>.
- */
- package org.apache.fop.render.svg;
-
- import org.apache.fop.apps.FOPException;
- import org.apache.fop.area.PageViewport;
- import org.apache.fop.area.Title;
- import org.apache.fop.area.inline.ForeignObject;
- import org.apache.fop.area.inline.Leader;
- import org.apache.fop.area.inline.Word;
- import org.apache.fop.svg.SVGUtilities;
- import org.apache.fop.layout.FontInfo;
- import org.apache.fop.fo.FOUserAgent;
- import org.apache.fop.fo.properties.RuleStyle;
-
- import org.w3c.dom.Node;
- import org.w3c.dom.svg.SVGSVGElement;
- import org.w3c.dom.svg.SVGDocument;
- import org.w3c.dom.Document;
- import org.w3c.dom.Element;
- import org.w3c.dom.DOMImplementation;
- import org.w3c.dom.Text;
-
- import org.apache.batik.dom.svg.SVGDOMImplementation;
- import org.apache.batik.dom.util.XMLSupport;
- import org.apache.batik.transcoder.svg2svg.SVGTranscoder;
- import org.apache.batik.transcoder.TranscoderInput;
- import org.apache.batik.transcoder.TranscoderOutput;
- import org.apache.batik.transcoder.TranscoderException;
- import org.apache.batik.dom.util.DOMUtilities;
-
- import java.awt.Color;
- import java.awt.image.BufferedImage;
- import java.awt.geom.Rectangle2D;
- import java.util.HashMap;
- import java.io.OutputStream;
- import java.io.IOException;
- import java.io.OutputStreamWriter;
-
- import org.apache.fop.render.AbstractRenderer;
- import org.apache.fop.render.XMLHandler;
- import org.apache.fop.render.RendererContext;
-
- /**
- * This is the SVG renderer.
- */
- public class SVGRenderer extends AbstractRenderer implements XMLHandler {
-
- /** SVG MIME type */
- public static final String SVG_MIME_TYPE = "image/svg+xml";
-
- /** SVG namespace */
- public static final String SVG_NAMESPACE = SVGDOMImplementation.SVG_NAMESPACE_URI;
-
- private Document svgDocument;
- private Element svgRoot;
- private Element currentPageG = null;
- private Element lastLink = null;
- private String lastViewbox = null;
-
- private Element docDefs = null;
- private Element pageDefs = null;
- private Element pagesGroup = null;
-
- // first sequence title
- private Title docTitle = null;
-
- private RendererContext context;
-
- private OutputStream ostream;
-
- private float totalWidth = 0;
- private float totalHeight = 0;
- private float sequenceWidth = 0;
- private float sequenceHeight = 0;
-
- private float pageWidth = 0;
- private float pageHeight = 0;
- private int pageNumber = 0;
-
- private HashMap fontNames = new HashMap();
- private HashMap fontStyles = new HashMap();
- private Color saveColor = null;
-
- /**
- * The current (internal) font name
- */
- private String currentFontName;
-
- /**
- * The current font size in millipoints
- */
- private int currentFontSize;
-
- /**
- * The current colour's red, green and blue component
- */
- private float currentRed = 0;
- private float currentGreen = 0;
- private float currentBlue = 0;
-
- /**
- * Creates a new SVG renderer.
- */
- public SVGRenderer() {
- context = new RendererContext(SVG_MIME_TYPE);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
- */
- public void setUserAgent(FOUserAgent agent) {
- super.setUserAgent(agent);
- userAgent.setDefaultXMLHandler(SVG_MIME_TYPE, this);
- userAgent.addXMLHandler(SVG_MIME_TYPE, SVG_NAMESPACE, this);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#setupFontInfo(FontInfo)
- */
- public void setupFontInfo(FontInfo fontInfo) {
- // create a temp Image to test font metrics on
- BufferedImage fontImage =
- new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
- org.apache.fop.render.awt.FontSetup.setup(fontInfo,
- fontImage.createGraphics());
- }
-
- /**
- * @see org.apache.fop.render.Renderer#setProducer(String)
- */
- public void setProducer(String producer) {
- }
-
- /**
- * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
- */
- public void startRenderer(OutputStream outputStream)
- throws IOException {
- ostream = outputStream;
- DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
- svgDocument = impl.createDocument(SVG_NAMESPACE, "svg", null);
- svgRoot = svgDocument.getDocumentElement();
- /*
- ProcessingInstruction pi =
- svgDocument.createProcessingInstruction("xml",
- " version=\"1.0\" encoding=\"ISO-8859-1\"");
- svgDocument.insertBefore(pi, svgRoot);
- */
-
- docDefs = svgDocument.createElementNS(SVG_NAMESPACE, "defs");
- svgRoot.appendChild(docDefs);
-
- pagesGroup = svgDocument.createElementNS(SVG_NAMESPACE, "g");
- pageDefs = svgDocument.createElementNS(SVG_NAMESPACE, "defs");
- pagesGroup.appendChild(pageDefs);
- svgRoot.appendChild(pagesGroup);
-
- }
-
- /**
- * @see org.apache.fop.render.Renderer#stopRenderer()
- */
- public void stopRenderer() throws IOException {
- totalWidth += sequenceWidth;
- if (sequenceHeight > totalHeight) {
- totalHeight = sequenceHeight;
- }
-
- svgRoot.setAttributeNS(null, "width", "" + (totalWidth + 1));
- svgRoot.setAttributeNS(null, "height", "" + (totalHeight + 1));
- //svgRoot.setAttributeNS(null, "viewBox", "0 0 " + pageWidth + " " + pageHeight);
- SVGTranscoder svgT = new SVGTranscoder();
- TranscoderInput input = new TranscoderInput(svgDocument);
- TranscoderOutput output =
- new TranscoderOutput(new OutputStreamWriter(ostream));
- try {
- svgT.transcode(input, output);
- } catch (TranscoderException e) {
- getLogger().error("could not write svg file :" + e.getMessage(), e);
- }
- ostream.flush();
- ostream = null;
-
- svgDocument = null;
- svgRoot = null;
- currentPageG = null;
- lastLink = null;
-
- totalWidth = 0;
- totalHeight = 0;
-
- pageNumber = 0;
- }
-
- /**
- * @see org.apache.fop.render.Renderer#startPageSequence(Title)
- */
- public void startPageSequence(Title seqTitle) {
- totalWidth += sequenceWidth;
- if (sequenceHeight > totalHeight) {
- totalHeight = sequenceHeight;
- }
- sequenceWidth = 0;
- sequenceHeight = 0;
- if (seqTitle != null && docTitle == null) {
- // convert first title to a string and set for svg document title
- docTitle = seqTitle;
- String str = convertTitleToString(seqTitle);
- Element svgTitle = svgDocument.createElementNS(SVG_NAMESPACE, "title");
- Text strNode = svgDocument.createTextNode(str);
- svgTitle.appendChild(strNode);
- svgRoot.insertBefore(svgTitle, svgRoot.getFirstChild());
- }
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
- */
- public void renderPage(PageViewport page) throws IOException, FOPException {
- float lastWidth = pageWidth;
- float lastHeight = pageHeight;
-
- Rectangle2D area = page.getViewArea();
- pageWidth = (float) area.getWidth() / 1000f;
- pageHeight = (float) area.getHeight() / 1000f;
-
- // if there is a link from the last page
- if (lastLink != null) {
- lastLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox("
- + totalWidth + ", "
- + sequenceHeight + ", "
- + pageWidth + ", "
- + pageHeight + "))");
- pagesGroup.appendChild(lastLink);
- }
-
- currentPageG = svgDocument.createElementNS(SVG_NAMESPACE, "svg");
- currentPageG.setAttributeNS(null, "viewbox",
- "0 0 " + (int) pageWidth + " " + (int) pageHeight);
- currentPageG.setAttributeNS(null, "width",
- "" + ((int) pageWidth + 1));
- currentPageG.setAttributeNS(null, "height",
- "" + ((int) pageHeight + 1));
- currentPageG.setAttributeNS(null, "id", "Page-" + pageNumber);
- currentPageG.setAttributeNS(null, "style", "font-family:sanserif;font-size:12");
- pageDefs.appendChild(currentPageG);
-
- if (pageWidth > sequenceWidth) {
- sequenceWidth = pageWidth;
- }
- sequenceHeight += pageHeight;
-
- Element border =
- SVGUtilities.createRect(svgDocument, 0, 0, pageWidth,
- pageHeight);
- border.setAttributeNS(null, "style", "fill:none;stroke:black");
- currentPageG.appendChild(border);
-
- // render the page contents
- super.renderPage(page);
-
- Element use = svgDocument.createElementNS(SVG_NAMESPACE, "use");
- use.setAttributeNS(null, "xlink:href", "#Page-" + pageNumber);
- use.setAttributeNS(null, "x", "" + totalWidth);
- use.setAttributeNS(null, "y", "" + (sequenceHeight - pageHeight));
- pagesGroup.appendChild(use);
-
- Element lastPageLink = svgDocument.createElementNS(SVG_NAMESPACE, "a");
- if (lastLink != null) {
- lastPageLink.setAttributeNS(null, "xlink:href", lastViewbox);
- } else {
- lastPageLink.setAttributeNS(null, "xlink:href",
- "#svgView(viewBox("
- + totalWidth + ", "
- + (sequenceHeight - pageHeight) + ", "
- + pageWidth + ", "
- + pageHeight + "))");
- }
- pagesGroup.appendChild(lastPageLink);
-
- // setup a link to the next page, only added when the
- // next page is rendered
- Element rect = SVGUtilities.createRect(svgDocument, totalWidth,
- (sequenceHeight - pageHeight), pageWidth / 2, pageHeight);
- rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden");
- lastPageLink.appendChild(rect);
-
- lastLink = svgDocument.createElementNS(SVG_NAMESPACE, "a");
- rect = SVGUtilities.createRect(svgDocument,
- totalWidth + pageWidth / 2,
- (sequenceHeight - pageHeight), pageWidth / 2, pageHeight);
- rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden");
- lastLink.appendChild(rect);
-
- lastViewbox = "#svgView(viewBox("
- + totalWidth + ", "
- + (sequenceHeight - pageHeight) + ", "
- + pageWidth + ", "
- + pageHeight + "))";
-
- pageNumber++;
-
- }
-
- /**
- * Method renderForeignObject.
- * @param fo the foreign object
- */
- public void renderForeignObject(ForeignObject fo) {
- Document doc = fo.getDocument();
- String ns = fo.getNameSpace();
- userAgent.renderXML(context, doc, ns);
- }
-
- /**
- * @see org.apache.fop.render.XMLHandler#handleXML(RendererContext, Document, String)
- */
- public void handleXML(RendererContext context, Document doc,
- String ns) throws Exception {
- if (SVG_NAMESPACE.equals(ns)) {
- if (!(doc instanceof SVGDocument)) {
- DOMImplementation impl =
- SVGDOMImplementation.getDOMImplementation();
- doc = DOMUtilities.deepCloneDocument(doc, impl);
- }
- SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
- Element view = svgDocument.createElementNS(SVG_NAMESPACE, "svg");
- Node newsvg = svgDocument.importNode(svg, true);
- //view.setAttributeNS(null, "viewBox", "0 0 ");
- view.setAttributeNS(null, "x",
- "" + currentBlockIPPosition / 1000f);
- view.setAttributeNS(null, "y", "" + currentBPPosition / 1000f);
-
- // this fixes a problem where the xmlns is repeated sometimes
- Element ele = (Element) newsvg;
- ele.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns",
- SVG_NAMESPACE);
- if (ele.hasAttributeNS(null, "xmlns")) {
- ele.removeAttributeNS(null, "xmlns");
- }
-
- view.appendChild(newsvg);
- currentPageG.appendChild(view);
- }
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderLeader(Leader)
- */
- public void renderLeader(Leader area) {
- String style = "stroke:black;stroke-width:"
- + (area.getRuleThickness() / 1000) + ";";
- switch (area.getRuleStyle()) {
- case RuleStyle.DOTTED:
- style += "stroke-dasharray:1,1";
- break;
- case RuleStyle.DASHED:
- style += "stroke-dasharray:5,1";
- break;
- case RuleStyle.SOLID:
- break;
- case RuleStyle.DOUBLE:
- break;
- case RuleStyle.GROOVE:
- break;
- case RuleStyle.RIDGE:
- break;
- }
- Element line = SVGUtilities.createLine(svgDocument,
- currentBlockIPPosition / 1000,
- (currentBPPosition + area.getOffset()
- - area.getRuleThickness() / 2) / 1000,
- (currentBlockIPPosition + area.getWidth()) / 1000,
- (currentBPPosition + area.getOffset()
- - area.getRuleThickness() / 2) / 1000);
- line.setAttributeNS(null, "style", style);
- currentPageG.appendChild(line);
-
- super.renderLeader(area);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderWord(Word)
- */
- public void renderWord(Word word) {
- Element text = SVGUtilities.createText(svgDocument,
- currentBlockIPPosition / 1000,
- (currentBPPosition + word.getOffset()) / 1000,
- word.getWord());
- currentPageG.appendChild(text);
-
- super.renderWord(word);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderCharacter(Character)
- */
- public void renderCharacter(org.apache.fop.area.inline.Character ch) {
- Element text = SVGUtilities.createText(svgDocument,
- currentBlockIPPosition / 1000,
- (currentBPPosition + ch.getOffset()) / 1000,
- "" + ch.getChar());
- currentPageG.appendChild(text);
-
- super.renderCharacter(ch);
- }
- }
|