4

Looking through the documentation for JSVGCanvas, it seems like I might not be able to do this. However, it makes a lot of sense for this to be possible. How can I create a JSVGCanvas from a String variable instead of a File?

My idea is that I could do something like the following:

String svg = "svg data";
JFrame frame = new JFrame();
JSVGCanvas canvas = new JSVGCanvas();
canvas.setContentsFromString(svg);
frame.add(canvas);
frame.setVisible(true);

I know I could always create a temporary file and set the contents of the JSVGCanvas from the file, but I'd rather avoid that. Could I perhaps extend File and override its methods?

Note: I am using Jython, but I think that this is relevant for Java as well, hence I'm using both tags. I'd prefer that a solution be in Java, but a Jython solution would work

Justin
  • 24,288
  • 12
  • 92
  • 142

1 Answers1

5

Yes, you can:

String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
SVGDocument document = factory.createSVGDocument("", new ByteArrayInputStream(svg.getBytes("UTF-8")));

canvas.setSVGDocument(document);

This works by creating an SVGDocument via SAXSVGDocumentFactory. SAXSVGDocumentFactory has a method createSVGDocument(String, InputStream), where the string is supposed to be a URI to the file that the InputStream represents. However, we abuse that and give it an empty string, and make the InputStream a stream from our svg-data String.

Using "" might throw an exception about their being no protocol, depending on the version of Batik. If that's the case, try "file:///", that is, give it a URI that is a lie. You may want to use an actual URI; you'd need to figure out a valid one to give to Batik

Justin
  • 24,288
  • 12
  • 92
  • 142
  • On version 1.6 of Batik, this results in a "java.io.IOException: no protocol:" at org.apache.batik.dom.svg.SAXSVGDocumentFactory.createDocument() – tucuxi Aug 10 '17 at 15:10
  • 1
    @tucuxi sounds like the uri needs more info. Maybe try something like `file:///` (perhaps with a fake path after – Justin Aug 10 '17 at 15:31
  • 1
    I can confirm that using "file:///" instead of "" works fine (batik 1.6 from Maven Central) – tucuxi Aug 10 '17 at 20:16
  • on batik 1.10 it works both with "" as well as "file:///" – mx1up Sep 13 '18 at 17:31