/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2009, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.renderer.svg;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.util.Map.Entry;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.TranscodingHints.Key;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGDocument;
import org.xml.sax.XMLReader;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class SvgUtils {
private SvgUtils(){}
public static Image read(final Document svgdom, final Dimension dim) throws TranscoderException, IOException{
return read(svgdom,dim,null);
}
public static Image read(final InputStream stream, final Dimension dim) throws TranscoderException, IOException{
return read(stream,dim,null);
}
public static Image read(final Reader svgfile, final Dimension dim) throws TranscoderException, IOException{
return read(svgfile,dim,null);
}
public static Image read(final String svgfile, final Dimension dim) throws TranscoderException, IOException{
return read(svgfile,dim,null);
}
public static Image read(final XMLReader svgfile, final Dimension dim) throws TranscoderException, IOException{
return read(svgfile,dim,null);
}
public static Image read(final Document svgdom, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
final TranscoderInput in = new TranscoderInput(svgdom);
return read(in, dim, hints);
}
public static Image read(final InputStream stream, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
final TranscoderInput in = new TranscoderInput(stream);
return read(in, dim, hints);
}
public static Image read(final Reader svgfile, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
final TranscoderInput in = new TranscoderInput(svgfile);
return read(in, dim, hints);
}
public static Image read(final String svgfile, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
final TranscoderInput in = new TranscoderInput(svgfile);
return read(in, dim, hints);
}
public static Image read(final XMLReader svgfile, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
final TranscoderInput in = new TranscoderInput(svgfile);
return read(in, dim, hints);
}
public static Image read(final TranscoderInput in, final Dimension dim, final RenderingHints hints) throws TranscoderException, IOException{
if(dim.height <=0 || dim.width <=0){
throw new IllegalArgumentException("Height and width must be superior to 0");
}
final BufferedImageTranscoder svgTranscoder = new BufferedImageTranscoder();
TranscoderOutput out = new TranscoderOutput();
if(hints != null){
for(Entry<Object,Object> entry : hints.entrySet()){
final Object key = entry.getKey();
if(key instanceof TranscodingHints.Key){
svgTranscoder.addTranscodingHint((Key) key,entry.getValue());
}
}
}
svgTranscoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, Float.valueOf(dim.height));
svgTranscoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, Float.valueOf(dim.width));
svgTranscoder.transcode(in, out);
return svgTranscoder.getBufferedImage();
}
public static void render(final URI in, final Point2D dim, final Graphics2D g, final RenderingHints hints) throws TranscoderException, IOException{
if(dim.getY() <=0 || dim.getX() <=0){
throw new IllegalArgumentException("Height and width must be superior to 0");
}
final String parser = XMLResourceDescriptor.getXMLParserClassName();
final SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
final SVGDocument doc = (SVGDocument)factory.createDocument(in.toString());
final RenderableSVG svg = new RenderableSVG(doc);
svg.paint(g, dim);
}
/**
* @see http://wiki.apache.org/xmlgraphics-batik/DynamicSvgOffscreen
*/
private static class RenderableSVG {
private final GraphicsNode node;
private Rectangle2D bounds;
public RenderableSVG(final SVGDocument doc) {
final UserAgent userAgent = new UserAgentAdapter();
final DocumentLoader loader = new DocumentLoader(userAgent);
final BridgeContext ctx = new BridgeContext(userAgent, loader);
ctx.setDynamic(true);
final GVTBuilder builder = new GVTBuilder();
this.node = builder.build(ctx, doc);
final float docWidth = (float)ctx.getDocumentSize().getWidth();
final float docHeight = (float)ctx.getDocumentSize().getHeight();
bounds = new Rectangle2D.Float(0, 0, docWidth, docHeight);
if (bounds == null){
bounds = node.getBounds();
}
}
public void paint(final Graphics2D g, final Point2D dim) {
final double scaleX = dim.getX() / bounds.getWidth();
final double scaleY = dim.getY() / bounds.getHeight();
g.scale(scaleX, scaleY);
try {
node.paint(g);
} finally {
g.scale(1/scaleX, 1/scaleY);
}
}
}
}