/**
* ditaa - Diagrams Through Ascii Art
*
* Copyright (C) 2004-2011 Efstathios Sideris
*
* ditaa 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, either version 3 of
* the License, or (at your option) any later version.
*
* ditaa 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ditaa. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.stathissideris.ascii2image.graphics;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory;
import org.apache.batik.gvt.renderer.ImageRenderer;
import org.apache.batik.gvt.renderer.ImageRendererFactory;
import org.w3c.dom.NodeList;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGElement;
public class OffScreenSVGRenderer {
private static final boolean DEBUG = false;
public BufferedImage renderXMLToImage(String xmlContent, int width, int height) throws IOException {
return renderXMLToImage(xmlContent, width, height, false, null, null);
}
public BufferedImage renderXMLToImage(String xmlContent, int width, int height, boolean stretch, String idRegex, Color replacementColor) throws IOException {
// the following is necessary so that batik knows how to resolve URI fragments
// (#myLinearGradient). Otherwise the resolution fails and you cannot render.
String uri = "file:/fake.svg";
SAXSVGDocumentFactory df = new SAXSVGDocumentFactory("org.apache.xerces.parsers.SAXParser");
SVGDocument document = df.createSVGDocument(uri, new StringReader(xmlContent));
if(idRegex != null && replacementColor != null)
replaceFill(document, idRegex, replacementColor);
return renderToImage(document, width, height, stretch);
}
public BufferedImage renderToImage(String uri, int width, int height) throws IOException {
return renderToImage(uri, width, height, false, null, null);
}
public BufferedImage renderToImage(String uri, int width, int height, boolean stretch, String idRegex, Color replacementColor) throws IOException {
SAXSVGDocumentFactory df = new SAXSVGDocumentFactory("org.apache.xerces.parsers.SAXParser");
SVGDocument document = df.createSVGDocument(uri);
if(idRegex != null && replacementColor != null)
replaceFill(document, idRegex, replacementColor);
return renderToImage(document, width, height, stretch);
}
public BufferedImage renderToImage(SVGDocument document, int width, int height){
return renderToImage(document, width, height, false);
}
public void replaceFill(SVGDocument document, String idRegex, Color color){
String colorCode = String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
if(DEBUG) System.out.println("color code: "+colorCode);
NodeList children = document.getElementsByTagName("*");
for(int i = 0; i < children.getLength(); i++){
if(children.item(i) instanceof SVGElement){
SVGElement element = (SVGElement) children.item(i);
if(element.getId().matches(idRegex)){
if(DEBUG) System.out.println("child>>> "+element+", "+element.getId());
String style = element.getAttributeNS(null, "style");
style = style.replaceFirst("fill:#[a-zA-z0-9]+", "fill:"+colorCode);
if(DEBUG) System.out.println(style);
element.setAttributeNS(null, "style", style);
}
}
}
}
public BufferedImage renderToImage(SVGDocument document, int width, int height, boolean stretch){
ImageRendererFactory rendererFactory;
rendererFactory = new ConcreteImageRendererFactory();
ImageRenderer renderer = rendererFactory.createStaticImageRenderer();
GVTBuilder builder = new GVTBuilder();
BridgeContext ctx = new BridgeContext(new UserAgentAdapter());
ctx.setDynamicState(BridgeContext.STATIC);
GraphicsNode rootNode = builder.build(ctx, document);
renderer.setTree(rootNode);
float docWidth = (float) ctx.getDocumentSize().getWidth();
float docHeight = (float) ctx.getDocumentSize().getHeight();
float xscale = width/docWidth;
float yscale = height/docHeight;
if(!stretch){
float scale = Math.min(xscale, yscale);
xscale = scale;
yscale = scale;
}
AffineTransform px = AffineTransform.getScaleInstance(xscale, yscale);
double tx = -0 + (width/xscale - docWidth)/2;
double ty = -0 + (height/yscale - docHeight)/2;
px.translate(tx, ty);
//cgn.setViewingTransform(px);
renderer.updateOffScreen(width, height);
renderer.setTree(rootNode);
renderer.setTransform(px);
//renderer.clearOffScreen();
renderer.repaint(new Rectangle(0, 0, width, height));
return renderer.getOffScreen();
}
}