A couple days ago a coworker and I were working on JGraphX and Apache Batik to generate SVG graph for a defined workflow in our application.
During the implementation we came across a issue that our framework need width, height and viewbox parameters to show SVG file in browser.
Default Batik SVG generator is not adding these three attributes into the root element, I did Google to search a solution for this not unable to find complete solution.
I got couple of ideas to make it work. As a result I thought of writing this as a blog so this solution can be used by others as well.
Generate SVG Graph Image
public void generateSVGGraphImage(mxGraph graph) throws IOException {
//Get the Graph component from the mxGraph to create an image out of this Graph
mxGraphComponent graphComponent = new mxGraphComponent(graph);
//Create an instance of org.w3c.dom.Document
String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();
Document document = domImpl.createDocument(svgNS, "svg", null);
// Create an instance of the SVG Generator
SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
// Reuse our embedded base64-encoded image data.
GenericImageHandler ihandler = new CachedImageHandlerBase64Encoder();
ctx.setGenericImageHandler(ihandler);
//Create SVG graphics2d Generator similar to the Graphich2d
SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);
//First draw Graph to the SVGGrapgics2D object using graphcomponent objects draw method
graphComponent.getGraphControl().drawGraph(svgGenerator, true);
//Once every thing is drawn on graphics find root element and update this by adding additional values for the required fields.
Element root = svgGenerator.getRoot();
root.setAttributeNS(null, "width", graphComponent.getGraphControl().getPreferredSize().width + "");
root.setAttributeNS(null, "height", graphComponent.getGraphControl().getPreferredSize().height + "");
root.setAttributeNS(null, "viewBox", "0 0 " + graphComponent.getGraphControl().getPreferredSize().width + " " + graphComponent.getGraphControl().getPreferredSize().height);
// Print to the SVG Graphics2D object
boolean useCSS = true; // we want to use CSS style attributes
Writer out = new FileWriter(new File("resources/graph.svg"));
try {
svgGenerator.stream(root, out, useCSS, false);
} catch (SVGGraphics2DIOException e) {
e.printStackTrace();
}
}
Make sure that root element attribute value addition is done at the end, because it creates a root element if this is not available or skips other graph components during writing.