Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I export a JavaFX node to an SVG image?

In other words, I'm trying to do something with JavaFX like what Batik allows you to do with Swing.

I want to be able to capture the appearance of an arbitrary node in my JavaFX UI, much like Node.snapshot() does, except that I need my image in a vector format like SVG, not a raster image. (And inserting a raster snapshot of my node into an SVG image is not good enough; it needs to be a proper, scalable vector image.)

This is a long-term project, so I'm even willing to go as far as implementing my own GraphicsContext, or whatever the equivalent is in JavaFX's retained mode API.

Does anyone know if there is a way to do this? Is what I'm hoping to do even possible in JavaFX?

like image 417
Xanatos Avatar asked Sep 25 '12 15:09

Xanatos


1 Answers

I started to write a JavaFx Node to SVG converter which "extends" the ShapeConverter from Gerrit Grunwald which only converts Shape geometries:

https://github.com/stefaneidelloth/JavaFxNodeToSvg

... and stopped it after a certain amount of frustration.

Please feel free to improve it, add features and fix bugs.

The converter works for simple Node examples but fails for advanced examples like a Chart. My failed converter might serve you as a starting point. The current state is illustrated by the following figures. The left side shows the original JavaFx node and the right side shows the resulting svg output.

Simple node example (works): enter image description here

Chart example (does not work): enter image description here

The corresponging svg files are available here:

https://github.com/stefaneidelloth/JavaFxNodeToSvg/tree/master/output

Some further notes

In addition to the positioning problems that are illustrated by the Chart example above, some further issues have to be considered:

JavaFx provides more css functionality than the SVG standard elements. For example a (rectangular) JavaFx Region can have individual line styles for each of the four border lines. Such a Region can not simply be converted to a SVG rect. Instead, the four border lines of the Region need to be drawn individually. Furthermore, each end of such a border line can have two individual edge radii: a vertical radius and a horizontal radius. In order to convert the "four" border lines to corresponding SVG lines ... it might be necessary to further split the border line: draw two rounded parts and a straight part for each of the four border lines. Therefore, in some cases there might be 12 SVG path elements to draw the border of a single JavaFx Region. In addition, the background fill of the Region can have different radii than the border of the Region. Drawing the background of the Region might requires some more SVG elements. Therefore, even the conversion of a "rectangular Region" can get quite complex.

Please also note that JavaFx nodes might be animated. For example the opacity of a line is 0 at the beginning and fades to another value after a few milliseconds.

FadeTransition ft = new FadeTransition(Duration.millis(250), borderline);
                    ft.setToValue(0);                       
                    ft.play();

Therefore it only makes sense to convert Nodes where animations are disabled or to wait until the Nodes are in a stable state.

I would be very happy if the conversion of JavaFx Charts works one day, so that I can use JavaFx plotting with SVG export in one of my projects.

I decided to stop the development of the converter for the time being and to investigate the plotting and SVG export with JavaScript libraries (d3) instead. If that strategy turns out to be even worse, I might come back to the JavaFxNodeToSvgConverter.

Edit The plotting with d3.js works very well and I decided not to use JavaFx for the purpose of plotting/svg creation. https://github.com/stefaneidelloth/javafx-d3

like image 81
Stefan Avatar answered Oct 16 '22 09:10

Stefan