/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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: AbstractGenericSVGHandler.java 1664570 2015-03-06 09:41:07Z lbernardo $ */

package org.apache.fop.render;

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

import org.w3c.dom.Document;

import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DefaultFontFamilyResolver;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.gvt.GraphicsNode;

import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
import org.apache.fop.render.RendererContext.RendererContextWrapper;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;

Generic XML handler for SVG. Uses Apache Batik for SVG processing and simply paints to a Graphics2DAdapter and thus ultimatively to Graphics2D interface that is presented.

To use this class, subclass it and implement the missing methods (supportsRenderer, for example).

/** * Generic XML handler for SVG. Uses Apache Batik for SVG processing and simply paints to * a Graphics2DAdapter and thus ultimatively to Graphics2D interface that is presented. * <p> * To use this class, subclass it and implement the missing methods (supportsRenderer, for example). */
public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererContextConstants {
{@inheritDoc}
/** {@inheritDoc} */
public void handleXML(RendererContext context, Document doc, String ns) throws Exception { if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { renderSVGDocument(context, doc); } }
Creates a graphics 2D image painter implementation
Params:
  • root – the batik graphics node root
  • ctx – the batik bridge context
  • imageSize – the image size
Returns:a new graphics 2D image painter implementation
/** * Creates a graphics 2D image painter implementation * * @param root the batik graphics node root * @param ctx the batik bridge context * @param imageSize the image size * @return a new graphics 2D image painter implementation */
protected Graphics2DImagePainter createGraphics2DImagePainter( GraphicsNode root, BridgeContext ctx, Dimension imageSize) { return new Graphics2DImagePainterImpl(root, ctx, imageSize); }
Builds the GVT root.
Params:
  • userAgent – the user agent
  • ctx – the batik bridge context
  • doc – the document
Returns:a built GVT root tree
/** * Builds the GVT root. * * @param userAgent the user agent * @param ctx the batik bridge context * @param doc the document * @return a built GVT root tree */
protected GraphicsNode buildGraphicsNode( FOUserAgent userAgent, BridgeContext ctx, Document doc) { GVTBuilder builder = new GVTBuilder(); final GraphicsNode root; try { root = builder.build(ctx, doc); } catch (Exception e) { EventBroadcaster eventBroadcaster = userAgent.getEventBroadcaster(); SVGEventProducer eventProducer = SVGEventProducer.Provider.get(eventBroadcaster); final String uri = getDocumentURI(doc); eventProducer.svgNotBuilt(this, e, uri); return null; } return root; }
Returns the image size
Params:
  • wrappedContext – renderer context wrapper
Returns:the image size
/** * Returns the image size * @param wrappedContext renderer context wrapper * * @return the image size */
protected Dimension getImageSize(RendererContextWrapper wrappedContext) { final int width = wrappedContext.getWidth(); final int height = wrappedContext.getHeight(); return new Dimension(width, height); }
Render the SVG document.
Params:
  • rendererContext – the renderer context
  • doc – the SVG document
Throws:
  • IOException – In case of an I/O error while painting the image
/** * Render the SVG document. * * @param rendererContext the renderer context * @param doc the SVG document * @throws IOException In case of an I/O error while painting the image */
protected void renderSVGDocument(final RendererContext rendererContext, final Document doc) throws IOException { updateRendererContext(rendererContext); //Prepare FOUserAgent userAgent = rendererContext.getUserAgent(); SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, DefaultFontFamilyResolver.SINGLETON, new AffineTransform()); //Create Batik BridgeContext final BridgeContext bridgeContext = new BridgeContext(svgUserAgent); //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine) //to it. Document clonedDoc = BatikUtil.cloneSVGDocument(doc); //Build the GVT tree final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, clonedDoc); // Create Graphics2DImagePainter final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext( rendererContext); Dimension imageSize = getImageSize(wrappedContext); final Graphics2DImagePainter painter = createGraphics2DImagePainter( root, bridgeContext, imageSize); //Let the painter paint the SVG on the Graphics2D instance Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter(); //Paint the image final int x = wrappedContext.getCurrentXPosition(); final int y = wrappedContext.getCurrentYPosition(); final int width = wrappedContext.getWidth(); final int height = wrappedContext.getHeight(); g2dAdapter.paintImage(painter, rendererContext, x, y, width, height); }
Gets the document URI from a Document instance if possible.
Params:
  • doc – the Document
Returns:the URI or null
/** * Gets the document URI from a Document instance if possible. * * @param doc the Document * @return the URI or null */
protected String getDocumentURI(Document doc) { String docURI = null; if (doc instanceof AbstractDocument) { AbstractDocument level3Doc = (AbstractDocument)doc; docURI = level3Doc.getDocumentURI(); } return docURI; }
Override this method to update the renderer context if it needs special settings for certain conditions.
Params:
  • context – the renderer context
/** * Override this method to update the renderer context if it needs special settings for * certain conditions. * * @param context the renderer context */
protected void updateRendererContext(RendererContext context) { //nop }
{@inheritDoc}
/** {@inheritDoc} */
public String getNamespace() { return SVGDOMImplementation.SVG_NAMESPACE_URI; } }