Package org.apache.fop.render.ps

Source Code of org.apache.fop.render.ps.PSSVGHandler

/*
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: PSSVGHandler.java 332549 2005-11-11 13:44:40Z jeremias $ */

package org.apache.fop.render.ps;

// Java
import java.awt.geom.AffineTransform;
import java.io.IOException;

// DOM
/* org.w3c.dom.Document is not imported to avoid conflict with
   org.apache.fop.control.Document */
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;

// Batik
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.ViewBox;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;

// FOP
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.render.RendererContext;
import org.apache.fop.svg.SVGUserAgent;

// Commons-Logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* PostScript XML handler for SVG. Uses Apache Batik for SVG processing.
* This handler handles XML for foreign objects when rendering to PostScript.
* It renders SVG to the PostScript document using the PSGraphics2D.
* The properties from the PostScript renderer are subject to change.
*
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
* @version $Id: PSSVGHandler.java 332549 2005-11-11 13:44:40Z jeremias $
*/
public class PSSVGHandler implements XMLHandler {

    /**
     * logging instance
     */
    private Log log = LogFactory.getLog(PSSVGHandler.class);

    /**
     * The PostScript generator that is being used to drawn into.
     */
    public static final String PS_GENERATOR = "psGenerator";

    /**
     * The font information for the PostScript renderer.
     */
    public static final String PS_FONT_INFO = "psFontInfo";

    /**
     * The width of the SVG graphic.
     */
    public static final String PS_WIDTH = "width";

    /**
     * The height of the SVG graphic.
     */
    public static final String PS_HEIGHT = "height";

    /**
     * The x position that this is being drawn at.
     */
    public static final String PS_XPOS = "xpos";

    /**
     * The y position that this is being drawn at.
     */
    public static final String PS_YPOS = "ypos";

    /**
     * Create a new PostScript XML handler for use by the PostScript renderer.
     */
    public PSSVGHandler() {
    }

    /** @see org.apache.fop.render.XMLHandler */
    public void handleXML(RendererContext context,
                org.w3c.dom.Document doc, String ns) throws Exception {
        PSInfo psi = getPSInfo(context);

        if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
            SVGHandler svghandler = new SVGHandler();
            svghandler.renderSVGDocument(context, doc, psi);
        } else {
            //nop
        }
    }

    /**
     * Get the pdf information from the render context.
     *
     * @param context the renderer context
     * @return the pdf information retrieved from the context
     */
    public static PSInfo getPSInfo(RendererContext context) {
        PSInfo psi = new PSInfo();
        psi.psGenerator = (PSGenerator)context.getProperty(PS_GENERATOR);
        psi.fontInfo = (org.apache.fop.fonts.FontInfo) context.getProperty(PS_FONT_INFO);
        psi.width = ((Integer)context.getProperty(PS_WIDTH)).intValue();
        psi.height = ((Integer)context.getProperty(PS_HEIGHT)).intValue();
        psi.currentXPosition = ((Integer)context.getProperty(PS_XPOS)).intValue();
        psi.currentYPosition = ((Integer)context.getProperty(PS_YPOS)).intValue();
        return psi;
    }

    /**
     * PostScript information structure for drawing the XML document.
     */
    public static class PSInfo {

        /** see PS_GENERATOR */
        private PSGenerator psGenerator;
        /** see PS_FONT_INFO */
        private org.apache.fop.fonts.FontInfo fontInfo;
        /** see PS_PAGE_WIDTH */
        private int width;
        /** see PS_PAGE_HEIGHT */
        private int height;
        /** see PS_XPOS */
        private int currentXPosition;
        /** see PS_YPOS */
        private int currentYPosition;
        /**
         * Returns the PSGenerator.
         * @return PSGenerator
         */
        public PSGenerator getPSGenerator() {
            return psGenerator;
        }

        /**
         * Sets the PSGenerator.
         * @param psGenerator The PSGenerator to set
         */
        public void setPsGenerator(PSGenerator psGenerator) {
            this.psGenerator = psGenerator;
        }

        /**
         * Returns the fontInfo.
         * @return FontInfo
         */
        public FontInfo getFontInfo() {
            return fontInfo;
        }

        /**
         * Sets the fontInfo.
         * @param fontInfo The fontInfo to set
         */
        public void setFontInfo(FontInfo fontInfo) {
            this.fontInfo = fontInfo;
        }

        /**
         * Returns the currentXPosition.
         * @return int
         */
        public int getCurrentXPosition() {
            return currentXPosition;
        }

        /**
         * Sets the currentXPosition.
         * @param currentXPosition The currentXPosition to set
         */
        public void setCurrentXPosition(int currentXPosition) {
            this.currentXPosition = currentXPosition;
        }

        /**
         * Returns the currentYPosition.
         * @return int
         */
        public int getCurrentYPosition() {
            return currentYPosition;
        }

        /**
         * Sets the currentYPosition.
         * @param currentYPosition The currentYPosition to set
         */
        public void setCurrentYPosition(int currentYPosition) {
            this.currentYPosition = currentYPosition;
        }

        /**
         * Returns the width.
         * @return int
         */
        public int getWidth() {
            return width;
        }

        /**
         * Sets the width.
         * @param width The pageWidth to set
         */
        public void setWidth(int width) {
            this.width = width;
        }

        /**
         * Returns the height.
         * @return int
         */
        public int getHeight() {
            return height;
        }

        /**
         * Sets the height.
         * @param height The height to set
         */
        public void setHeight(int height) {
            this.height = height;
        }

    }

    /**
     * This method is placed in an inner class so that we don't get class
     * loading errors if batik is not present.
     */
    protected class SVGHandler {
        /**
         * Render the svg document.
         * @param context the renderer context
         * @param doc the svg document
         * @param psInfo the pdf information of the current context
         */
        protected void renderSVGDocument(RendererContext context,
                org.w3c.dom.Document doc, PSInfo psInfo) {
            int xOffset = psInfo.currentXPosition;
            int yOffset = psInfo.currentYPosition;
            PSGenerator gen = psInfo.psGenerator;

            SVGUserAgent ua
                 = new SVGUserAgent(
                    context.getUserAgent().getPixelUnitToMillimeter(),
                    new AffineTransform());

            GVTBuilder builder = new GVTBuilder();
            BridgeContext ctx = new BridgeContext(ua);
            PSTextPainter textPainter = new PSTextPainter(psInfo.getFontInfo());
            ctx.setTextPainter(textPainter);           
            PSTextElementBridge tBridge = new PSTextElementBridge(textPainter);
            ctx.putBridge(tBridge);

            //PSAElementBridge aBridge = new PSAElementBridge();
            // to get the correct transform we need to use the PDFState
            AffineTransform transform = gen.getCurrentState().getTransform();
            transform.translate(xOffset / 1000f, yOffset / 1000f);
            //aBridge.setCurrentTransform(transform);
            //ctx.putBridge(aBridge);

            GraphicsNode root;
            try {
                root = builder.build(ctx, doc);
            } catch (Exception e) {
                log.error("SVG graphic could not be built: "
                                       + e.getMessage(), e);
                return;
            }
            // get the 'width' and 'height' attributes of the SVG document
            float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
            float h = (float)ctx.getDocumentSize().getHeight() * 1000f;

            float sx = psInfo.getWidth() / (float)w;
            float sy = psInfo.getHeight() / (float)h;

            ctx = null;
            builder = null;

            try {
                gen.commentln("%FOPBeginSVG");
                gen.saveGraphicsState();
                /*
                 * Clip to the svg area.
                 * Note: To have the svg overlay (under) a text area then use
                 * an fo:block-container
                 */
                gen.writeln("newpath");
                gen.defineRect(xOffset / 1000f, yOffset / 1000f,
                        psInfo.getWidth() / 1000f, psInfo.getWidth() / 1000f);
                //TODO Is the above correct? Twice getWidth??????????????
                gen.writeln("clip");
               
                // transform so that the coordinates (0,0) is from the top left
                // and positive is down and to the right. (0,0) is where the
                // viewBox puts it.
                gen.concatMatrix(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f);

                SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
                AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
                        psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f);
                if (false && !at.isIdentity()) {
                    double[] vals = new double[6];
                    at.getMatrix(vals);
                    gen.concatMatrix(vals);
                }

                final boolean textAsShapes = false;
                PSGraphics2D graphics = new PSGraphics2D(textAsShapes, gen);
                graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext());
                transform = new AffineTransform();
                // scale to viewbox
                transform.translate(xOffset, yOffset);
                gen.getCurrentState().concatMatrix(transform);
                try {
                    root.paint(graphics);
                } catch (Exception e) {
                    log.error("SVG graphic could not be rendered: "
                                           + e.getMessage(), e);
                }

                gen.restoreGraphicsState();
                gen.commentln("%FOPEndSVG");
            } catch (IOException ioe) {
                log.error("SVG graphic could not be rendered: "
                                       + ioe.getMessage(), ioe);
            }
        }
    }

    /** @see org.apache.fop.render.XMLHandler#getMimeType() */
    public String getMimeType() {
        return PSRenderer.MIME_TYPE;
    }

    /** @see org.apache.fop.render.XMLHandler#getNamespace() */
    public String getNamespace() {
        return SVGDOMImplementation.SVG_NAMESPACE_URI;
    }
   
}
TOP

Related Classes of org.apache.fop.render.ps.PSSVGHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.