Hello, fellow SVG enthusiasts!
Last week, I posted a question, and a couple of generous people responded. Their hints helped me to find the solution I needed. Now, in the spirit of "giving back," I would like to share what I learned.
Here is how you can render an SVG document to an arbitrary graphics context.
You may wish to do this, for example, if you would like to draw an SVG icon on a JButton, render SVG to an offscreen buffer, or display SVG on a JPanel that is *not* a JSVGCanvas.
First, you need to instantiate an SVGAbstractTranscoder. This class will read and parse the SVG document and generate the GVT tree. However, SVGAbstractTranscoder is abstract, and the GVT tree is stored in a protected member called "root", so you need to cheat a little to get at it:
public class SvgConcreteTranscoder extends SVGAbstractTranscoder
{
public GraphicsNode getGraphicsNode()
{
return root;
}
}
The rest is boiler-plate stuff. Embed this code in your class and call the method in your constructor:
// GVT tree root:
GraphicsNode mpGvtTree;
// Initialize mpGvtTree;
static void initializeGvtTree(URL ipUrl) throws Exception
{
// Create a document factory:
String vsParser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory vpFactory = new SAXSVGDocumentFactory(vsParser);
// Build the SVG document tree from the SVG source:
String vsUrl = ipUrl.toString();
SVGDocument vpDocument = vpFactory.createSVGDocument(vsUrl);
// Use a transcoder to force building the GVT tree:
SvgConcreteTranscoder vpTranscoder = new SvgConcreteTranscoder();
TranscoderInput vpInput = new TranscoderInput(vpDocument);
// Use null for the transcoder output because we're aren't actually doing any transcoding:
vpTranscoder.transcode(vpInput, null);
// Save the root of the GVT tree, discard everything else.
mpGvtTree = vpTranscoder.getGraphicsNode();
}
Pardon my Hungarian. "i" is for input, "v" is for local variables, and "m" is for field. My point here is that given the SVG document's URL, you can generate and keep the GVT tree, and discard everything else.
Notice also that I have not had to fuss with tree builder listeners and such. Everything is done synchronously, as far as I can tell, because the transcode method handles all of the asynchronous stuff.
Once armed with mpGvtTree, you can render it to any graphics context by calling its paint method with a Graphics2D. For example, your AWT paint method might look like this:
public void paint(Graphics ipG)
{
Graphics2D vpG = (Graphics2D) ipG;
do_other_painting(vpG);
mpGvtTree.paint(vpG);
}
I hope others find this information useful. Thanks a million to those who offered help. If inaccuracies are found, please share. If you have been helped from this list on another problem, please consider doing as I have and summarizing your solution.
Thanks again,
Sharky