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 Glen Simmons <gl...@gmail.com> on 2005/03/01 05:03:18 UTC

Re: Newbie: How to render an SVG into an image

OK, I guess I spoke too soon. I tried the code below in a Cocoa-Java
app and it hangs. I checked with the debugger and it's hanging down in
some Swing code that's trying to instantiate menus. This is a problem
because there are already menus. So I tried to implement the basics of
what JSVGComponent does in the loadSVGDocument() method:

		ParsedURL	aURI = new ParsedURL(theURL);
		
		theUserAgent = new UserAgentAdapter();
		theLoader = new DocumentLoader(theUserAgent);
		docLoader = new SVGDocumentLoader(aURI.toString(), theLoader);
		docLoader.addSVGDocumentLoaderListener(new SVGDocumentLoaderAdapter() {
			public void documentLoadingStarted(SVGDocumentLoaderEvent e) {
				NSSystem.log("documentLoadingStarted");
			}
			
			public void documentLoadingCompleted(SVGDocumentLoaderEvent e) {
				NSSystem.log("documentLoadingCompleted");
				SVGDocument		theDoc = e.getSVGDocument();
				BridgeContext	theBC = new BridgeContext(theUserAgent, theLoader);
				GVTTreeBuilder	treeBuilder = new GVTTreeBuilder(theDoc, theBC);
				treeBuilder.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() {
					public void gvtBuildCompleted(GVTTreeBuilderEvent evt) {
						NSSystem.log("gvtBuildCompleted");
					}
				});
				treeBuilder.start();
			}
		});
		docLoader.start();

This starts to work b/c documentLoadingStarted() gets called, but
that's as far as it gets. Also, an extra menu gets added to the
menubar, so apparently some Swing code is still getting called.

Anyone have any suggestions?

Thanks,
Glen

On Fri, 25 Feb 2005 13:57:14 -0600, Glen Simmons <gl...@gmail.com> wrote:
> Wow, thanks. This is exactly what I need.
> 
> Glen
> 
> 
> On Fri, 25 Feb 2005 14:47:45 -0500, Andres Toussaint
> <an...@onemileup.com> wrote:
> > The best option is to render the image in a JSVGComponent, and once it
> > is available, encode it as a PNG.
> >
> > The basic idea is to intercept the gvtRenderingCompleted event to
> > recover the BufferedImage, and then encode this image to something your
> > Cocoa App can handle, like a PNG.
> >
> > If your source is from a URL, simply take the JSVGCanvas tutorial on
> > the Batik page as a guideline and change the JSVGCanvas to a
> > JSVGComponent, also, you do not need a Swing component, nor do you need
> > to add the JSVGComponent to any window for it to render the image. And
> > once the gvtRenderingCompleted is called you can recover your image.
> >
> > I use this method for a JavaClient WebObjects app in Macintosh
> > (although i only show the BufferedImage in a Swing component, and add
> > the PNG back to my SVG as a thumbnail), so i am sure that it works on
> > Max OS X.
> >
> >  From a previous mail, that did not made it into the archives:
> >
> > Basically, you need to create a JSVGComponent (you do not need a
> > JSVGCanvas since you are displaying in a AWT) and add the build and
> > render listeners, so you are notified when the data is ready to be
> > fetched. The important one is GVTRenderListener. When the image is
> > fully rendered into a BufferedImage, a GVTRenderingCompleted is
> > triggered and you can fetch the image directly from the Event.
> >
> > Once the listeners are in place, you need to load the document to your
> > JSVGComponent, you can do so from a String (probably recuperated from a
> > Database), from the filesystem, or from a prebuild org.w3c.dom.Document
> > object. Once you assign the document to the JSVGComponent, simply wait
> > until the event is triggered, and that is it.
> >
> > Here is an abstract on how to do it.
> >
> > ---------------Start of code
> > svg = new JSVGComponent();
> >              svg.addSVGDocumentLoaderListener(new
> > SVGDocumentLoaderAdapter() {
> >                  public void
> > documentLoadingStarted(SVGDocumentLoaderEvent e) {
> >                  }
> >                  public void
> > documentLoadingCompleted(SVGDocumentLoaderEvent e) {
> >                     //System.out.println("SaveAsDXF-ExportCache
> > succesfully loaded");
> >                  }
> >              });
> >              svg.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() {
> >                  public void gvtBuildStarted(GVTTreeBuilderEvent e) {
> >
> > //System.out.println("SaveAsDXF-ExportCache-GVTBuilder Starting.....");
> >                  }
> >                  public void gvtBuildCompleted(GVTTreeBuilderEvent
> > event) {
> >
> > //////////////// If you want access to the G2D elements (generalPath,
> > shapes, rectangles2D, you can
> > //////////////// get the GVTTree in this place and walk through it. The
> > GVTTree has all your SVG
> > //////////////// converted into Graphics2D objects.
> >
> >                 }
> >         });
> >
> > svg.addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
> >              public void gvtRenderingPrepare(GVTTreeRendererEvent e) {
> >              }
> >              public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
> > ////////////////////////////////////
> > ////////////////////////////////////
> > // In here you can access your image, once the JSVGComponent has loaded
> > // the XMl and parsed it as SVG and into Graphics2D objects, and finally
> > // painted them into a BufferedImage.
> > ////////////////////////////////////
> >
> >                                 BufferedImage e.getImage();
> >
> >              }
> >          });
> >
> > //////////////////////////////////// And now, to load your XML into the
> > JSVGComponent you need something like this:
> > //////////////////////////////////// Please note that this example has
> > it that the XML is already in memory in a String.
> > //////////////////////////////////// But you can have a FileReader to
> > read from the filesystem also.
> > /////////////Or you can simply call the
> > jsvgComponent.loadSVGDocument(String URL);
> > try {
> >                         String parser = XMLResourceDescriptor.getXMLParserClassName();
> >                         SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
> > //////////data is the XML that defines the SVG. Usually a string.
> >                         Document doc = f.createSVGDocument(null, new
> > java.io.StringReader((String)data));
> >
> > ////////////"svg" is the JSVGComponent object.
> >                         svg.setDocument(doc);
> >
> >                 } catch (IOException ex) {
> >                         System.out.println("Error de svg."+ex);
> >                 }
> >
> > //-------------------------end of code
> >
> > Also, code form a mail by Thomas de Wesse, also lost in oblivion, to
> > encode the BufferedImame into a PNG:
> >   Encode it as a PNG and include it in the xlink:href using
> > the data protocol.  This is what the code below does (very
> > indirectly).
> >
> >      The code to do this more directly (take from
> > batik.svggen.ImageHandlerBase64Encoder) is something like:
> >
> >      public static final String DATA_PROTOCOL_PNG_PREFIX =
> >         "data:image/png;base64,";
> >
> >          ByteArrayOutputStream os = new ByteArrayOutputStream();
> >          Base64EncoderStream b64Encoder = new Base64EncoderStream(os);
> >
> >          ImageEncoder encoder = new PNGImageEncoder(b64Encoder, null);
> >          encoder.encode(buf);
> >
> >          // Close the b64 encoder stream (terminates b64 streams).
> >          b64Encoder.close();
> >
> >         String encodedPNGString =  DATA_PROTOCOL_PNG_PREFIX + os.toString();
> > ----------------End of code to encode as PNG
> >
> > On Feb 25, 2005, at 2:04 PM, Glen Simmons wrote:
> >
> > > I'm just getting started with Batik (and also with Java, somewhat) and
> > > can't quite figure out where to start. I need to render an SVG and get
> > > an image that I can display in the UI of my app. This is a Mac OS X
> > > Cocoa app, so the JSVGCanvas component is not an option. Calling other
> > > Java code is no problem, though.
> >
> > > From the architecture overview
> > > (http://xml.apache.org/batik/architecture.html), it appears that I
> > > need to drop down to the Renderer module. But I can't figure out how
> > > to load an SVG file into it and get it to render. Is there some sample
> > > code that shows how to do this?
> > >
> > > Thanks,
> > > Glen Simmons
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
> > > For additional commands, e-mail: batik-users-help@xml.apache.org
> > >
> > >
> >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org


Re: Newbie: How to render an SVG into an image

Posted by Thomas DeWeese <Th...@Kodak.com>.
Glen Simmons wrote:
> On Tue, 01 Mar 2005 07:09:16 -0500, Thomas DeWeese
> <Th...@kodak.com> wrote:
> 
>> I would look carefully at the stack trace that is creating 
>> menus to try and figure out who is trying to create them.
> 
> 
> Here's the stack trace when calling JSVGComponent.loadSVGDocument:
> JavaBug> bt
>    0: com.apple.mrj.application.SystemMenu.createAppleMenu()  line -1
[...]
>   10: java.awt.Toolkit.getEventQueue()  line 1145
>   11: java.awt.EventQueue.isDispatchThread()  line 434
>   12: org.apache.batik.swing.svg.JSVGComponent$BridgeUserAgentWrapper.getXMLParserClassName()

    Very helpful.  I would try running the JDK in 'headless' mode.

> No custom anything. And I would have to disagree that the problem is
> somewhere else in my code since the code that I pasted was pretty much
> all of the code in the app. From the above backtrace, I'm thinking
> it's a Mac AWT implementation / Batik interaction problem, but I'm not
> sure what to do about it.

    The menu creation was a red herring (note that Batik is really not
creating the menu, doing anything with AWT would appear to cause this).
I'm a little curious why this locks up your application, but anyways
I am hoping that you can run the JDK in headless mode and avoid this
issue.  If not you will have to find a way to get the Java AWT toolkit
to play nicely with your application (after all, the drawing in Batik
is done using AWT/Java2D so if you can't boot the toolkit you won't
be able to draw anything).


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org


Re: Newbie: How to render an SVG into an image

Posted by Glen Simmons <gl...@gmail.com>.
On Tue, 01 Mar 2005 07:09:16 -0500, Thomas DeWeese
<Th...@kodak.com> wrote:
> Glen Simmons wrote:
> > OK, I guess I spoke too soon. I tried the code below in a Cocoa-Java
> > app and it hangs. I checked with the debugger and it's hanging down in
> > some Swing code that's trying to instantiate menus. This is a problem
> > because there are already menus.
> 
>    The JSVGComponent does _not_ create menu's, the JSVGViewerFrame
> (from the svgbrowser/squiggle application) does create menus but
> you aren't using that.  I would look carefully at the stack trace
> that is creating menus to try and figure out who is trying to
> create them.

Here's the stack trace when calling JSVGComponent.loadSVGDocument:
JavaBug> bt
   0: com.apple.mrj.application.SystemMenu.createAppleMenu()  line -1
   1: com.apple.mrj.application.SystemMenu.addAppleMenu()  line 73
   2: com.apple.buckyball.app.Application.setUpStandalone()  line 72
   3: com.apple.buckyball.app.Application.createStandalone()  line 61
   4: com.apple.mrj.internal.awt.publicpeers.VToolkit.<init>()  line 281
   5: java.lang.Class.newInstance0()  line -1
   6: java.lang.Class.newInstance()  line 232
   7: java.awt.Toolkit$2.run()  line 519
   8: java.security.AccessController.doPrivileged()  line -1
   9: java.awt.Toolkit.getDefaultToolkit()  line 498
  10: java.awt.Toolkit.getEventQueue()  line 1145
  11: java.awt.EventQueue.isDispatchThread()  line 434
  12: org.apache.batik.swing.svg.JSVGComponent$BridgeUserAgentWrapper.getXMLParserClassName()
 line -2
  13: org.apache.batik.bridge.DocumentLoader.<init>()  line -2
  14: org.apache.batik.swing.svg.JSVGComponent$1.run()  line -2
  15: org.apache.batik.swing.svg.JSVGComponent.stopThenRun()  line -2
  16: org.apache.batik.swing.svg.JSVGComponent.loadSVGDocument()  line -2
  17: Controller.loadAction()  line 85

It hangs here forever. Apparently the AWT implementation on Mac OS X
does some odd things, b/c I don't know why
java.awt.EventQueue.isDispatchThread() should lead to trying to add
menus, but it does.

> 
> So I tried to implement the basics of
> > what JSVGComponent does in the loadSVGDocument() method:
> 
>     This code looks about right to me.
> 
> > This starts to work b/c documentLoadingStarted() gets called, but
> > that's as far as it gets. Also, an extra menu gets added to the
> > menubar, so apparently some Swing code is still getting called.
> >
> > Anyone have any suggestions?
> 
>     I don't think it is Batik calling the Swing code.  In fact
> at the point you reach (document load) nothing having anything
> to do with Java2D/AWT has been called by Batik, it's all just
> XML Parsing and DOM Document construction.  Not until you start
> the GVT builder does it do anything real with AWT/Swing stuff.
> 
>     I strongly suspect the problem is somewhere else in your code.
> Does your system use any custom DOM elements with our
> DOMImplementation?

No custom anything. And I would have to disagree that the problem is
somewhere else in my code since the code that I pasted was pretty much
all of the code in the app. From the above backtrace, I'm thinking
it's a Mac AWT implementation / Batik interaction problem, but I'm not
sure what to do about it.

Thanks,
Glen

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org


Re: Newbie: How to render an SVG into an image

Posted by Thomas DeWeese <Th...@Kodak.com>.
Glen Simmons wrote:
> OK, I guess I spoke too soon. I tried the code below in a Cocoa-Java
> app and it hangs. I checked with the debugger and it's hanging down in
> some Swing code that's trying to instantiate menus. This is a problem
> because there are already menus. 

   The JSVGComponent does _not_ create menu's, the JSVGViewerFrame
(from the svgbrowser/squiggle application) does create menus but
you aren't using that.  I would look carefully at the stack trace
that is creating menus to try and figure out who is trying to
create them.

So I tried to implement the basics of
> what JSVGComponent does in the loadSVGDocument() method:

    This code looks about right to me.

> This starts to work b/c documentLoadingStarted() gets called, but
> that's as far as it gets. Also, an extra menu gets added to the
> menubar, so apparently some Swing code is still getting called.
> 
> Anyone have any suggestions?

    I don't think it is Batik calling the Swing code.  In fact
at the point you reach (document load) nothing having anything
to do with Java2D/AWT has been called by Batik, it's all just
XML Parsing and DOM Document construction.  Not until you start
the GVT builder does it do anything real with AWT/Swing stuff.

    I strongly suspect the problem is somewhere else in your code.
Does your system use any custom DOM elements with our
DOMImplementation?

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-users-help@xml.apache.org