You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by Ch...@daifukuamerica.com on 2004/07/27 19:36:09 UTC

HOWTO - rendering SVG documents to any graphics context

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