diff -Naur inkscape2/build.xml inkscape/build.xml
--- inkscape2/build.xml	2009-02-12 10:40:07.000000000 +0100
+++ inkscape/build.xml	2009-02-10 10:35:02.000000000 +0100
@@ -489,7 +489,7 @@
            -lssl -lcrypto
            ${pcl.lcms}
            ${pcl.gsl}
-           -lpng -ljpeg.dll -ltiff.dll -lpopt ${devlibs}/lib/zdll.lib
+           -lpng -ljpeg.dll -ltiff.dll -lpopt -lzip ${devlibs}/lib/zdll.lib
            -lgc
            -lws2_32 -lintl -lgdi32 -lcomdlg32 -lm
            -lgomp -lpthreadGC2
@@ -543,7 +543,7 @@
            -lssl -lcrypto
            ${pcl.lcms}
            ${pcl.gsl}
-           -lpng -ljpeg.dll -ltiff.dll -lpopt ${devlibs}/lib/zdll.lib
+           -lpng -ljpeg.dll -ltiff.dll -lpopt -lzip ${devlibs}/lib/zdll.lib
            -lgc
            -lws2_32 -lintl -lgdi32 -lcomdlg32 -lm
            -lgomp -lpthreadGC2
@@ -594,7 +594,7 @@
            -lssl -lcrypto
            ${pcl.lcms}
            ${pcl.gsl}
-           -lpng -ljpeg.dll -ltiff.dll -lpopt ${devlibs}/lib/zdll.lib
+           -lpng -ljpeg.dll -ltiff.dll -lpopt -lzip ${devlibs}/lib/zdll.lib
            -lgc
            -lws2_32 -lintl -lgdi32 -lcomdlg32 -lm
            -lgomp -lpthreadGC2
diff -Naur inkscape2/inkscape.spec.in inkscape/inkscape.spec.in
--- inkscape2/inkscape.spec.in	2009-02-12 10:40:07.000000000 +0100
+++ inkscape/inkscape.spec.in	2009-02-10 10:35:03.000000000 +0100
@@ -39,6 +39,7 @@
 BuildRequires:  perl-XML-Parser
 BuildRequires:  pkgconfig
 BuildRequires:  python-devel
+BuildRequires:  libzip-devel
 Requires(post):   desktop-file-utils
 Requires(postun): desktop-file-utils
 
diff -Naur inkscape2/po/POTFILES.in inkscape/po/POTFILES.in
--- inkscape2/po/POTFILES.in	2009-02-12 10:40:06.000000000 +0100
+++ inkscape/po/POTFILES.in	2009-02-10 10:35:03.000000000 +0100
@@ -91,6 +91,7 @@
 src/extension/internal/gdkpixbuf-input.cpp
 src/extension/internal/gimpgrad.cpp
 src/extension/internal/grid.cpp
+src/extension/internal/javafx-fxz.cpp
 src/extension/internal/javafx-out.cpp
 src/extension/internal/latex-pstricks.cpp
 src/extension/internal/latex-pstricks-out.cpp
diff -Naur inkscape2/src/extension/init.cpp inkscape/src/extension/init.cpp
--- inkscape2/src/extension/init.cpp	2009-02-12 10:39:35.000000000 +0100
+++ inkscape/src/extension/init.cpp	2009-02-10 10:35:03.000000000 +0100
@@ -42,6 +42,7 @@
 # include "internal/pdf-input-cairo.h"
 #endif
 #include "internal/pov-out.h"
+#include "internal/javafx-fxz.h"
 #include "internal/javafx-out.h"
 #include "internal/odf.h"
 #include "internal/latex-pstricks-out.h"
@@ -176,6 +177,7 @@
     Internal::EmfWin32::init();
 #endif
     Internal::PovOutput::init();
+    Internal::JavaFXZ::init();
     Internal::JavaFXOutput::init();
     Internal::OdfOutput::init();
     Internal::PrintLatex::init();
diff -Naur inkscape2/src/extension/internal/CMakeLists.txt inkscape/src/extension/internal/CMakeLists.txt
--- inkscape2/src/extension/internal/CMakeLists.txt	2009-02-12 10:39:35.000000000 +0100
+++ inkscape/src/extension/internal/CMakeLists.txt	2009-02-10 10:35:03.000000000 +0100
@@ -23,6 +23,7 @@
 pdf-input-cairo.cpp
 pov-out.cpp
 javafx-out.cpp
+javafx-fxz.cpp
 svg.cpp
 svgz.cpp
 wpg-input.cpp
diff -Naur inkscape2/src/extension/internal/javafx-fxz.cpp inkscape/src/extension/internal/javafx-fxz.cpp
--- inkscape2/src/extension/internal/javafx-fxz.cpp	1970-01-01 01:00:00.000000000 +0100
+++ inkscape/src/extension/internal/javafx-fxz.cpp	2009-02-12 00:27:17.000000000 +0100
@@ -0,0 +1,1480 @@
+/*
+ * JavaFX 1.0 plugin for Inkscape as a free extension to JavaFX Production Suite
+ *
+ * The output is JavaFX 1.0 Content File (.fxz) and can be viewed by netbeans with
+ * FXD viewer plugin installed.
+ *  
+ *  For information on JavaFX Production Suite, see:
+ *      http://javafx.com/docs/gettingstarted/production_suite/
+ *
+ *  For information on the JavaFX file format, see:
+ *      https://openjfx.dev.java.net/
+ *      
+ * Based on the work of authors:
+ * 
+ *   Bob Jamison <ishmal@inkscape.org>
+ *   Silveira Neto <silveiraneto@gmail.com>
+ *   Jim Clarke <Jim.Clarke@sun.com>
+ *
+ * Copyright (C) 2008 Authors
+ *
+ * Updates:
+ *   15 Jan 2009  by Sergey Esenov <serguei.essenov@desy.de>
+ *      - Added support for JavaFX Production Suite (.fxz) 
+ *        based on external 'libzip' library: http://www.nih.at/libzip
+ *      - Added support for gradients, simple texts, images (external and embedded).
+ *        Images are saved in ZIP archive together with content file
+ *
+ *   01 Feb 2009 by Sergey Esenov <serguei.essenov@desy.de>
+ *      - Added support for 'cycleMethod' (spreadMethod in inkscape) in gradients
+ *      - Changed gradient description policy: gradients in relational coordinates and
+ *        usage "proportional: true" where it is possible
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef PANGO_ENABLE_BACKEND
+#define PANGO_ENABLE_BACKEND
+#endif
+
+#ifndef PANGO_ENABLE_ENGINE
+#define PANGO_ENABLE_ENGINE
+#endif
+
+#include <inkscape.h>
+#include <inkscape-version.h>
+#include <interface.h>
+#include <sp-root.h>
+#include <sp-defs.h>
+#include <sp-path.h>
+#include <sp-rect.h>
+#include <sp-ellipse.h>
+#include <sp-linear-gradient.h>
+#include <sp-radial-gradient.h>
+#include <sp-item-transform.h>
+#include <sp-gaussian-blur.h>
+#include <sp-filter.h>
+#include <sp-image.h>
+#include <sp-text.h>
+#include <gradient-chemistry.h>
+#include <text-editing.h>
+#include <sp-clippath.h>
+#include <style.h>
+#include <display/curve.h>
+#include <display/canvas-bpath.h>
+#include <svg/svg.h>
+
+#include <pango/pangofc-font.h>
+
+#include <libnr/nr-macros.h>
+#include <libnrtype/font-instance.h>
+
+#include <extension/system.h>
+#include <2geom/pathvector.h>
+#include <2geom/rect.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
+#include <2geom/coord.h>
+#include "helper/geom.h"
+#include "helper/geom-curves.h"
+#include <io/sys.h>
+
+#include <string>
+#include <stdio.h>
+#include <stdarg.h>
+#include <zip.h>           // external libzip1 library: http://www.nih.at/libzip
+#include "javafx-fxz.h"
+
+#ifdef WIN32
+#include <glib.h>
+#include <windows.h>
+#endif
+
+namespace Inkscape
+{
+namespace Extension
+{
+namespace Internal
+{
+
+static int  ntabs = 0;
+static char indent[1024];
+static bool definitions = false;
+
+//###################################################################################
+// The following snippet was based on b64.c from http://base64.sourceforge.net/b64.c
+//###################################################################################
+static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+static void decodeblock( unsigned char in[4], unsigned char out[3] )
+{   
+    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
+    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
+    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
+}
+
+static int base64decode( char const *infile, int intlen, char *outfile )
+{
+    bool done = false;
+    unsigned char in[4], out[3], v;
+    int i, len, size = 0, pos = 0;
+
+    while( !done ) {
+        for( len = 0, i = 0; i < 4 && !done; i++ ) {
+            v = 0;
+            while( !done && v == 0 ) {
+                v = (unsigned char) infile[pos++];
+                if (pos == intlen)
+                    done = true;
+                v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
+                if( v ) {
+                    v = (unsigned char) ((v == '$') ? 0 : v - 61);
+                }
+            }
+            if( !done ) {
+                len++;
+                if( v ) {
+                    in[ i ] = (unsigned char) (v - 1);
+                }
+            }
+            else {
+                in[i] = 0;
+            }
+        }
+        if( len ) {
+            decodeblock( in, out );
+            for( i = 0; i < len - 1; i++ ) {
+                outfile[size++] = out[i];
+            }
+        }
+    }
+    return size;
+}
+
+
+//########################################################################
+//# M E S S A G E S
+//########################################################################
+
+static void err(const char *fmt, ...)
+{
+    va_list args;
+    g_log(NULL,  G_LOG_LEVEL_WARNING, "javafx-fxz err: ");
+    va_start(args, fmt);
+    g_logv(NULL, G_LOG_LEVEL_WARNING, fmt, args);
+    va_end(args);
+    g_log(NULL,  G_LOG_LEVEL_WARNING, "\n");
+}
+
+
+//########################################################################
+//# U T I L I T Y
+//########################################################################
+
+/**
+ * Got this method from Bulia, and modified it a bit.  It basically
+ * starts with this style, gets its SPObject parent, walks up the object
+ * tree and finds all of the opacities and multiplies them.
+ *
+ * We use this for our "flat" object output.  If the code is modified
+ * to reflect a tree of <groups>, then this will be unneccessary.
+ */
+static double effective_opacity(const SPStyle *style)
+{
+    double val = 1.0;
+    for (SPObject const *obj = style->object; obj ; obj = obj->parent)
+    {
+        style = SP_OBJECT_STYLE(obj);
+        if (style)
+            val *= SP_SCALE24_TO_FLOAT(style->opacity.value);
+    }
+    return val;
+}
+
+/**
+ * Comment the file in zip archive
+ */
+static void zipfile_comment(ZipFile &zf, char const *filename, char const *comment)
+{
+    // put a comment for 'filename' 
+    struct zip_stat st;
+    zip_stat_init(&st);
+    zip_stat(zf, filename, 0, &st);   // index is st.index
+    zip_set_file_comment(zf, st.index, comment, strlen(comment));
+}
+
+/**
+ * Get the extension suffix from the end of a file name
+ */
+static Glib::ustring getExtension(const Glib::ustring &fname)
+{
+    Glib::ustring ext;
+
+    std::string::size_type pos = fname.rfind('.');
+    if (pos == fname.npos)
+        {
+        ext = "";
+        }
+    else
+        {
+        ext = fname.substr(pos);
+        }
+    return ext;
+}
+
+
+//########################################################################
+//# OUTPUT FORMATTING
+//########################################################################
+
+
+
+/**
+ * Format an rgba() string
+ */
+static JavaFXZ::String rgba(guint32 rgba)
+{
+    unsigned int r = SP_RGBA32_R_U(rgba);
+    unsigned int g = SP_RGBA32_G_U(rgba);
+    unsigned int b = SP_RGBA32_B_U(rgba);
+    unsigned int a = SP_RGBA32_A_U(rgba);
+    char buf[80];
+    snprintf(buf, 79, "Color.rgb(0x%02x, 0x%02x, 0x%02x, %.3f)", r, g, b, (double)a/256.0);
+    JavaFXZ::String s = buf;
+    return s;
+}
+
+
+/**
+ * Format an rgba() string for a color and a 0.0-1.0 alpha
+ */
+static JavaFXZ::String rgba(SPColor color, gdouble alpha)
+{
+    return rgba(color.toRGBA32(alpha));
+}
+
+
+/**
+ * Replace illegal characters for JavaFX for a underscore.
+ */
+static JavaFXZ::String sanatize(const JavaFXZ::String &badstr){
+    JavaFXZ::String good(badstr);
+    for (unsigned int pos = 0; pos < badstr.length(); ++pos )
+        if((badstr.at(pos)=='-')||(badstr.at(pos)==' '))
+            good.replace(pos, 1, "_");
+    return good;
+}
+
+
+/**
+ *  Output data to the buffer, printf()-style
+ */
+void JavaFXZ::out(const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    gchar *output = g_strdup_vprintf(fmt, args);
+    va_end(args);
+    outbuf.append(output);
+    g_free(output);
+}
+
+/**
+ * Output the file header
+ */
+bool JavaFXZ::doHeader(SPDocument *doc)
+{
+    time_t tim = time(NULL);
+    out("/*\n");
+    out(" * Generated by JavaFX plugin for Inkscape (http://www.inkscape.org)\n");
+    out(" * Created on %s",   ctime(&tim));
+    out(" * INKSCAPE Version: %s\n", Inkscape::version_string);
+    out(" * ###################################################################\n");
+    out(" * # NOTES:\n");
+    out(" * # ============\n");
+    out(" * # JavaFX information can be found at\n");
+    out(" * # https://openjfx.dev.java.net\n");
+    out(" * #\n");
+    out(" * # If you have any problems with this output, please see the\n");
+    out(" * # Inkscape project at http://www.inkscape.org, or visit\n");
+    out(" * # the #inkscape channel on irc.freenode.net . \n");
+    out(" * #\n");
+    out(" * ###################################################################\n");
+    out(" */\n//@version 1.0\n");
+
+    return true;
+}
+
+
+/**
+ *  Output the file footer
+ */
+bool JavaFXZ::doTail()
+{
+    //out("/* ###################################################################\n");
+    //out(" * # E N D   C L A S S    %s\n", name.c_str());
+    //out(" * ###################################################################\n");
+    //out(" */\n\n");
+    out("\n");
+    return true;
+}
+
+
+/**
+ *  Output gradient information to the buffer
+ */
+bool JavaFXZ::processGradient(SPGradient *grad)
+{
+    if (!grad)
+        return true;
+
+    Glib::ustring cycle = "";
+    SPGradientSpread spread = sp_gradient_get_spread(grad);
+    switch (spread) {
+        case SP_GRADIENT_SPREAD_REFLECT:
+            cycle = "cycleMethod: CycleMethod.REFLECT";
+            break;
+        case SP_GRADIENT_SPREAD_REPEAT:
+            cycle = "cycleMethod: CycleMethod.REPEAT";
+            break;
+        default:
+            break;
+    }
+
+    Geom::Matrix  gt   = grad->gradientTransform;
+    Geom::OptRect bbox = currentItem->getBounds(Geom::identity());
+
+    if (SP_IS_LINEARGRADIENT(grad))
+    {
+        double sX,sY,eX,eY;
+        SPLinearGradient *g = SP_LINEARGRADIENT(grad);
+        Geom::Point p1(g->x1.computed, g->y1.computed);
+        Geom::Point p2(g->x2.computed, g->y2.computed);
+        //--- position of gradient vector in user space (JavaFX -> proportional: false) 
+        Geom::Point p1t = p1 * gt ;
+        Geom::Point p2t = p2 * gt;
+        
+        out("%s        LinearGradient {\n", indent);
+/*        out("%s //No transform startX: %.5f, startY: %.5f, endX: %.5f, endY: %.5f\n",
+            indent,p1t[0],p1t[1],p2t[0],p2t[1]);*/
+        if (cycle.size() > 0)
+            out("%s            %s\n", indent, cycle.c_str());
+
+        if (0) // set 'if (bbox)' if LinerGradient bug is fixed
+        {
+            double w  = bbox->dimensions()[Geom::X];
+            double h  = bbox->dimensions()[Geom::Y];
+            double x0 = bbox->min()[Geom::X];
+            double y0 = bbox->min()[Geom::Y];
+            //out("%s //BBox x0: %.5f, y0: %.5f, w: %.5f, h: %.5f\n",indent,x0,y0,w,h);
+            Geom::Point q1(p1t[Geom::X] - x0, p1t[Geom::Y] - y0);
+            Geom::Point q2(p2t[Geom::X] - x0, p2t[Geom::Y] - y0);
+            sX = q1[Geom::X] / w;
+            sY = q1[Geom::Y] / h;
+            eX = q2[Geom::X] / w;
+            eY = q2[Geom::Y] / h;
+            out("%s            startX: %.8f, startY: %.8f, endX: %.8f, endY: %.8f\n",indent,sX,sY,eX,eY);
+            out("%s            proportional: true\n", indent);
+        } else {
+            sX = p1t[0];
+            sY = p1t[1];
+            eX = p2t[0];
+            eY = p2t[1];
+            out("%s            startX: %.5f, startY: %.5f, endX: %.5f, endY: %.5f\n",indent,sX,sY,eX,eY);
+            out("%s            proportional: false\n", indent);
+        }
+
+        std::vector<SPGradientStop> stops = g->vector.stops;
+        if (stops.size() > 0)
+        {
+            out("%s            stops: [\n", indent);
+            for (unsigned int i = 0 ; i<stops.size() ; i++)
+            {
+                SPGradientStop stop = stops[i];
+                out("%s                Stop { offset: %.3f, color: %s },\n",indent,stop.offset,rgba(stop.color, stop.opacity).c_str());
+            }
+            out("%s            ]\n", indent);
+        }
+        out("%s        }\n", indent);
+    }
+    else if (SP_IS_RADIALGRADIENT(grad))
+    {
+        SPRadialGradient *g = SP_RADIALGRADIENT(grad);
+        Geom::Matrix mc = Geom::Matrix(Geom::Translate(g->cx.value, g->cy.value)) * gt;
+        Geom::Matrix mf = Geom::Matrix(Geom::Translate(g->fx.value, g->fy.value)) * gt;
+        Geom::Matrix mr = Geom::Matrix(Geom::Scale(g->r.value, g->r.value)) * gt;
+        Geom::Point pc = mc.translation();
+        Geom::Point pf = mf.translation();
+        double centerX = pc[0];
+        double centerY = pc[1];
+        double focusX  = pf[0];
+        double focusY  = pf[1];
+        double radiusX = mr.expansionX();
+        double radiusY = mr.expansionY();
+
+        out("%s        RadialGradient {\n", indent);
+        if (cycle.size() > 0)
+            out("%s            %s\n", indent, cycle.c_str());
+        if (bbox)
+        {
+            Geom::Coord w = bbox->dimensions()[Geom::X];
+            Geom::Coord h = bbox->dimensions()[Geom::Y];
+            Geom::Point c = bbox->midpoint();          
+            out("%s            //BBox width: %.5f, height: %.5f, cX: %.5f, cY: %.5f\n",indent,w,h,c[0],c[1]);
+            double cX = (centerX - (c[0] - w/2)) / w;
+            double cY = (centerY - (c[1] - h/2)) / h;
+            double fX = (focusX  - (c[0] - w/2)) / w;
+            double fY = (focusY  - (c[1] - h/2)) / h;
+            double rX = radiusX / w;
+            double rY = radiusY / h;
+            out("%s            proportional: true\n", indent);
+            // use arithmetic mean value as temporary solution until "transforms:" will be implemented in RadialGradient 
+            out("%s            centerX: %.5f, centerY: %.5f, focusX: %.5f, focusY: %.5f, radius: %.5f //radiusX: %.5f, radiusY: %.5f\n",
+                indent,cX,cY,fX,fY,(rX+rY)/2.0,rX,rY);
+        }
+        else
+        {
+            //out("%s            //BBox NULL\n",indent);
+            if (SP_GRADIENT_UNITS(grad) == SP_GRADIENT_UNITS_USERSPACEONUSE)
+                out("%s            proportional: false\n", indent);
+            out("%s            centerX: %.5f, centerY: %.5f, focusX: %.5f, focusY: %.5f, radius: %.5f //radiusX: %.5f, radiusY: %.5f\n",
+                indent,centerX,centerY,focusX,focusY,(radiusX+radiusY)/2.0,radiusX,radiusY);
+        }
+
+        std::vector<SPGradientStop> stops = g->vector.stops;
+        if (stops.size() > 0)
+        {
+            out("%s            stops: [\n", indent);
+            for (unsigned int i = 0 ; i<stops.size() ; i++)
+            {
+                SPGradientStop stop = stops[i];
+                out("%s                Stop { offset: %.3f, color: %s },\n", indent, stop.offset, rgba(stop.color, stop.opacity).c_str());
+            }
+            out("%s            ]\n", indent);
+        }
+        out("%s        }\n", indent);
+    }
+    else
+    {
+        err("Unsupported gradient type\n");
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ *  Output filter information to the buffer
+ */
+bool JavaFXZ::processFilter(SPFilter *filter)
+{
+    for (SPObject *child = filter->firstChild() ; child ; child = child->next)
+    {
+        if (!processEffect(child))
+            return false;
+    }
+    return true;
+}
+
+/**
+ *  Output clip-path information to the buffer
+ */
+bool JavaFXZ::processClipPath(SPClipPath *clip)
+{
+    for (SPObject *child = clip->firstChild(); child; child = child->next)
+    {
+        if ( !generateClip(child) )
+            return false;
+    }
+    return true;
+}
+
+/**
+ *  Output a clip attribute
+ */
+bool JavaFXZ::doClipPath(SPClipPathReference *ref)
+{
+    if (!ref)
+        return true;
+    if (ref->getObject() && ref->getURI()) {
+        Glib::ustring uri = ref->getURI()->toString();
+        if (uri.size() > 0 && uri[0]=='#')
+            uri = uri.substr(1);
+        SPClipPath *clip = clippaths[sanatize(uri)];
+        if (clip) {
+            if (!processClipPath(clip))
+                return false;
+        }
+    }
+    return true;
+}
+ 
+/**
+ *  Output an element's style attribute
+ */
+bool JavaFXZ::doStyle(SPStyle *style)
+{
+    if (!style)
+        return true;
+
+    out("%s    opacity: %.3f\n", indent, effective_opacity(style));
+
+    /**
+     * Fill
+     */
+    SPIPaint fill = style->fill;
+    if (fill.isColor())
+    {
+        // see color.h for how to parse SPColor
+        out("%s    fill: %s\n", indent, rgba(fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value)).c_str());
+    }
+    else if (fill.isPaintserver()) {
+        if (fill.value.href && fill.value.href->getURI() ) {
+            Glib::ustring uri = fill.value.href->getURI()->toString();
+            /* trim the anchor '#' from the front */
+            if (uri.size() > 0 && uri[0]=='#')
+                uri = uri.substr(1);
+            SPGradient *grad = gradients[sanatize(uri)];
+            if (!grad)
+                out("%s    fill: null\n", indent);
+            else {
+                out("%s    fill:\n", indent);
+                if (!processGradient(grad))
+                    return false;
+            }
+        }
+    }
+    else if (fill.isNoneSet())
+        out("%s    fill: null\n", indent);
+
+    /**
+     * Filter
+     */
+    SPIFilter filter = style->filter;
+    if (filter.set) {
+        if (filter.href && filter.href->getURI()) {
+            String uri = filter.href->getURI()->toString();
+            if (uri.size() > 0 && uri[0]=='#')
+                uri = uri.substr(1);
+            SPFilter *filter = effects[sanatize(uri)];
+            if (!processFilter(filter))
+                return false;
+        }
+    }
+
+    /**
+     * Stroke
+     */
+    /**
+     *NOTE:  Things in style we can use following limitations of JavaFX Data format:
+     * SPIPaint stroke;
+     * SPILength stroke_width;
+     * SPIFloat stroke_miterlimit;
+     * SPIScale24 stroke_opacity;
+     */
+    if (!style->stroke.isNone() && style->stroke_opacity.value > 0)
+    {
+        SPIPaint stroke = style->stroke;
+        out("%s    stroke: %s\n", indent, rgba(stroke.value.color, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)).c_str());
+        double strokewidth = style->stroke_width.computed;
+        out("%s    strokeWidth     : %.3f\n", indent, strokewidth);
+        out("%s    strokeMiterLimit: %.3f\n", indent, style->stroke_miterlimit.value);
+    }
+    else if (style->stroke.isNone())
+        out("%s    stroke: null\n", indent);
+
+    return true;
+}
+
+
+/**
+ *  Output rectangle to buffer
+ */
+bool JavaFXZ::doRect(SPRect *item, const Glib::ustring &jfxid)
+{
+    out("%sRectangle {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+    
+    if ( !doStyle(SP_OBJECT_STYLE(item)) )
+        return false;
+
+    out("%s    x: %.3f, y: %.3f, height: %.3f, width: %.3f, arcHeight: %.3f, arcWidth: %.3f\n",
+        indent, item->x.computed, item->y.computed, item->height.computed, item->width.computed,
+        2.0 * item->ry.computed, 2.0 * item->rx.computed);
+
+    if (item->clip_ref) {
+        if ( !doClipPath(item->clip_ref) )
+            return false;
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(item));
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+/**
+ *  Output circle to buffer
+ */
+bool JavaFXZ::doCircle(SPGenericEllipse *item, const Glib::ustring &jfxid)
+{
+    out("%sCircle {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+
+    if ( !doStyle(SP_OBJECT_STYLE(item)) )
+        return false;
+
+    out("%s    centerX: %.3f, centerY: %.3f, radius: %.3f\n",
+        indent, item->cx.computed, item->cy.computed, item->rx.computed);
+
+    if (item->clip_ref) {
+        if ( !doClipPath(item->clip_ref) )
+            return false;
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(item)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+/**
+ *  Output ellipse to buffer
+ */
+bool JavaFXZ::doEllipse(SPGenericEllipse *item, const Glib::ustring &jfxid)
+{
+    out("%sEllipse {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+
+    if ( !doStyle(SP_OBJECT_STYLE(item)) )
+        return false;
+
+    out("%s    centerX: %.3f, centerY: %.3f, radiusX: %.3f, radiusY: %.3f\n",
+        indent, item->cx.computed, item->cy.computed, item->rx.computed, item->ry.computed);
+
+    if (item->clip_ref) {
+        if ( !doClipPath(item->clip_ref) )
+            return false;
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(item));
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+/**
+ *  Output the curve data to buffer
+ */
+bool JavaFXZ::doCurve(SPItem *item, const Glib::ustring &jfxid)
+{
+    using Geom::X;
+    using Geom::Y;
+
+    SPShape *shape = SP_SHAPE(item);
+    SPCurve *curve = shape->curve;
+    if (curve->is_empty())
+        return true;
+
+    out("%sSVGPath {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+
+    gchar const *d = sp_object_getAttribute(item, "d", NULL);
+    out("%s    content: \"%s\"\n", indent, d);
+    out("%s    fillRule: FillRule.NON_ZERO\n", indent);
+
+    if ( !doStyle(SP_OBJECT_STYLE(item)) )
+        return false;
+
+    if (item->clip_ref) {
+        if ( !doClipPath(item->clip_ref) )
+            return false;
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(item));
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+bool JavaFXZ::doImage(ZipFile &zf, SPImage *image, const Glib::ustring &jfxid)
+{
+    out("%sImageView {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+    out("%s    x: %s, y: %s, width: %s, height: %s\n", indent,
+                sp_object_getAttribute(image, "x", NULL),
+                sp_object_getAttribute(image, "y", NULL),
+                sp_object_getAttribute(image, "width",  NULL),
+                sp_object_getAttribute(image, "height", NULL));
+
+    char const   *data_string = "data:image/";
+    char const   *refstr = sp_object_getAttribute(image, "xlink:href", NULL);
+    Glib::ustring href   = refstr;
+   
+    if (data_string == href.substr(0,strlen(data_string)))
+    {
+        std::string::size_type pos = href.find("/") + 1;
+        Glib::ustring       suffix = href.substr(pos, 3);
+
+        // Check that embedded image is base64 encoded one
+        pos = href.find(";");
+        if ( href.substr(pos+1, 6) == "base64" )
+        {
+            // Build canonical name for image in zip archive
+            char buf[256];
+            snprintf(buf, sizeof(buf), "Pictures/image%u.%s",
+                    static_cast<unsigned int>(imageTable.size()), suffix.c_str());
+            Glib::ustring newName = buf;
+            Glib::ustring oldName = newName.substr(newName.find("/") + 1);
+            imageTable[oldName] = newName;
+
+            // find position of encoded image and decode
+            pos = href.find(",") + 1;
+            int  encoded_size = strlen(refstr + pos); 
+            char *decoded_image = new char[encoded_size]; // allocate the same size 
+            int image_size = base64decode(refstr + pos, encoded_size, decoded_image);
+
+            ZipEntry *ze = zip_source_buffer(zf, decoded_image, image_size, 0);
+            if (ze) {
+                zip_add(zf, newName.c_str(), ze);
+                zipfile_comment(zf, newName.c_str(), "Extracted embedded image");
+            }
+            // to garantee our changes being saved into archive ...
+            zip_close(zf);
+            delete[] decoded_image;
+            Glib::ustring pathName = documentUri.getNativePath();
+            int err = 0;
+            zf = zip_open(pathName.c_str(), 0, &err);
+
+            out("%s    image: Image {url: \"{__DIR__}%s\"}\n",indent,imageTable[oldName].c_str());
+        }
+        else
+        {
+            char message[256];
+            sprintf(message,"Unsupported format of embedded image '%s' in JavaFX 1.0 ('null' image substituted)\n"
+                            "Hint: use \"Effects->Images->Extract One Image...\" first!", jfxid.c_str());
+            sp_ui_error_dialog(message);
+            out("%s    image: Image {url: null}\n", indent);
+        }
+    } 
+    else
+    {
+        Glib::ustring oldName = href;
+        Glib::ustring ext = getExtension(oldName);
+        if (ext == ".jpeg")
+            ext = ".jpg";
+        // if the (old) name not found, rename it
+        if (imageTable.find(oldName) == imageTable.end())
+        {
+            // Build canonical name for image in zip archive
+            char buf[256];
+            snprintf(buf, sizeof(buf), "Pictures/image%u%s",
+                    static_cast<unsigned int>(imageTable.size()), ext.c_str());
+            Glib::ustring newName = buf;
+            imageTable[oldName] = newName;
+            Glib::ustring comment = "old name was: ";
+            comment.append(oldName);
+            URI oldUri(oldName);
+            //g_message("oldpath:%s", oldUri.getNativePath().c_str());
+            //# if relative to the documentURI, get proper path
+            URI resUri = documentUri.resolve(oldUri);
+            Glib::ustring pathName = resUri.getNativePath();
+            //g_message("native path:%s", pathName.c_str());
+            ZipEntry *ze = zip_source_file(zf, pathName.c_str(), 0, -1);
+            if (ze) {
+                zip_add(zf, newName.c_str(), ze);
+                zipfile_comment(zf, newName.c_str(), comment.c_str());
+            }                
+        }              
+        out("%s    image: Image {url: \"{__DIR__}%s\"}\n", indent, imageTable[oldName].c_str());
+    }
+
+    if (image->clip_ref) {
+        if ( !doClipPath(image->clip_ref) )
+            return false;
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(image));
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+bool JavaFXZ::doText(ZipFile &zf, SPText *text, const Glib::ustring &jfxid)
+{
+    out("%sText {\n", indent);
+    if (jfxid.substr(0,4) == "jfx:")
+        out("%s    id: \"%s\"\n", indent, jfxid.substr(4).c_str());
+
+    //------------------------------------------------- get common style info
+    SPStyle  *style = SP_OBJECT_STYLE(text);
+    if ( !doStyle(style) )
+        return false;
+   //------------------------------------------- get Text specific style info
+    if (style->text_decoration.set) {
+        if (style->text_decoration.overline)
+            out("%s    overline: true\n", indent);
+        if (style->text_decoration.underline)
+            out("%s    underline: true\n", indent);
+        if (style->text_decoration.line_through)
+            out("%s    strikethrough: true\n", indent);
+    }
+    if (style->text_align.set) {
+        if (style->text_align.value == SP_CSS_TEXT_ALIGN_LEFT ||
+                    style->text_align.value == SP_CSS_TEXT_ALIGN_START) 
+            out("%s    textAlignment: TextAlignment.LEFT\n", indent);
+        else if (style->text_align.value == SP_CSS_TEXT_ALIGN_RIGHT ||
+                    style->text_align.value == SP_CSS_TEXT_ALIGN_END)
+            out("%s    textAlignment: TextAlignment.RIGHT\n", indent);
+        else if (style->text_align.value == SP_CSS_TEXT_ALIGN_CENTER)
+            out("%s    textAlignment: TextAlignment.CENTER\n", indent);
+        else if (style->text_align.value == SP_CSS_TEXT_ALIGN_JUSTIFY)
+            out("%s    textAlignment: TextAlignment.JUSTIFY\n", indent); 
+    }
+
+    //****************************** EXPERIMENTAL ********************
+    Glib::ustring fontfile = "";
+    font_instance * font = font_factory::Default()->FaceFromStyle(style);
+    if (font) {
+        if (fontfile == "") {
+            FcChar8 *fname = NULL;
+            PangoFont *pf = font->pFont;
+            if (PANGO_IS_FC_FONT(pf)) {
+                PangoFcFont *pfc = PANGO_FC_FONT(pf);
+                if (pfc)
+                    FcPatternGetString(pfc->font_pattern, FC_FILE, 0, &fname);
+                if (fname)
+                    fontfile.append(reinterpret_cast<char*>(fname));
+            }
+        }
+#ifdef WIN32
+        if (fontfile == "") {
+            // The filename related to above font_instance maybe retrieved from the
+            // value "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts"
+            HKEY key = NULL;
+            Glib::ustring spec = "";
+            WCHAR *lpValueName = NULL;
+            if (style->text->font_specification.set) {
+                spec.append(style->text->font_specification.value);
+                spec.append(" (TrueType)");     // add (TrueType), (VGA res), (all res), ... 
+                lpValueName = (WCHAR*)g_utf8_to_utf16(spec.c_str(), -1, NULL, NULL, NULL);
+            }
+            if (lpValueName && RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
+                0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
+            {
+                WCHAR utf16filename[_MAX_PATH];
+                DWORD value_type;
+                DWORD data_size = sizeof(utf16filename);
+                if (RegQueryValueExW(key, lpValueName, NULL, &value_type,
+                        (BYTE*)utf16filename, &data_size) == ERROR_SUCCESS)
+                {
+                    g_assert(value_type == REG_SZ);
+                    gchar *utf8filename = g_utf16_to_utf8((const gunichar2*)utf16filename,
+                                                            -1, NULL, NULL, NULL);
+                    if (utf8filename)
+                    {
+                        fontfile = "C:\\WINDOWS\\Fonts\\";
+                        if (utf8filename[1] == ':')
+                            fontfile = Glib::ustring(utf8filename);
+                        else
+                            fontfile.append(Glib::ustring(utf8filename));
+                        g_free(utf8filename);
+                    }
+                }
+                RegCloseKey(key);
+            }
+        }
+#endif
+        font->Unref();
+        font = NULL;
+    }
+    //****************************** END OF EXP   ********************
+
+    //--------------------------------------------- set Font.font(....)
+    char fontstr[256];
+    if ( fontfile.size() == 0 || !style->text->font_family.set    ||
+         strcmp(style->text->font_family.value, "Arial") == 0     ||
+         strcmp(style->text->font_family.value, "Sans Serif") == 0 ||
+         strcmp(style->text->font_family.value, "Times New Roman") == 0 )
+    {
+        snprintf(fontstr, 256, "%s    font: Font.font(", indent);
+        if (style->text->font_family.set)
+            snprintf(fontstr+strlen(fontstr), 256,"\"%s\", ", style->text->font_family.value);
+        else
+            snprintf(fontstr+strlen(fontstr), 256,"null, ");
+
+        if (style->font_weight.set && style->font_weight.value >= SP_CSS_FONT_WEIGHT_BOLD)
+            snprintf(fontstr+strlen(fontstr), 256, "FontWeight.BOLD, ");
+        else
+            snprintf(fontstr+strlen(fontstr), 256, "FontWeight.REGULAR, ");
+
+        if (style->font_style.set && style->font_style.value == SP_CSS_FONT_STYLE_ITALIC)
+            snprintf(fontstr+strlen(fontstr), 256, "FontPosture.ITALIC, ");
+        else
+            snprintf(fontstr+strlen(fontstr), 256, "FontPosture.REGULAR, ");
+
+        if (style->font_size.set) {
+            snprintf(fontstr+strlen(fontstr), 256, "%.3f)", style->font_size.computed);
+            out("%s\n", fontstr);
+        }
+    } else {
+        bool found = false;
+        //---------------------------- check if we have already this fontfile
+        std::vector<Glib::ustring>::const_iterator it;
+        for (it = fontVector.begin(); it != fontVector.end(); ++it) {
+            if (*it == fontfile) {
+                found = true;
+            }
+        }
+        Glib::ustring newName = "Fonts/";
+        newName.append(Glib::path_get_basename(fontfile));
+        if (!found) {
+            //------------------------- put fontfile into archive
+            URI font_uri(fontfile);
+            URI resUri = documentUri.resolve(font_uri);
+            Glib::ustring pathName = resUri.getNativePath();
+            g_message("%s //native path:%s, item name:%s", indent, pathName.c_str(), newName.c_str());
+            ZipEntry *ze = zip_source_file(zf, pathName.c_str(), 0, -1);
+            if (ze) {
+                zip_add(zf, newName.c_str(), ze);
+                zipfile_comment(zf, newName.c_str(), "Embedded font" );
+                //------------------------- put new fontfile into vector
+                fontVector.push_back(fontfile);
+                found = true;
+           }
+        }
+        if (style->font_size.set && found) {
+            out("%s    font: Font.fontFromURL(\"{__DIR__}%s\", %.3f)\n",
+                indent,newName.c_str(),style->font_size.computed);
+        }
+    }
+    //Inkscape::XML::Node *node = SP_OBJECT(text)->repr;
+    char const *posX = sp_object_getAttribute(text, "x", NULL);
+    char const *posY = sp_object_getAttribute(text, "y", NULL);
+    if (posX && posY)
+        out("%s    x: %s, y: %s\n", indent, posX, posY);
+    else {
+        if (posX)
+            out("%s    x: %s\n", indent, posX);
+        if (posY)
+            out("%s    y: %s\n", indent, posY);
+    }
+    Inkscape::Text::Layout const *layout = te_get_layout(text);
+    Glib::ustring content = sp_te_get_string_multiline(text, layout->begin(), layout->end());
+    out("%s    content: \"%s\"\n", indent, content.c_str());
+
+    if (text->clip_ref) {
+        if ( !doClipPath(text->clip_ref) )
+            return false;
+    }
+
+    // build transformation matrix:
+    Geom::Matrix const tm(sp_item_i2doc_affine(text)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if (!tm.isIdentity()) {
+        out("%s    transforms: [",indent);
+        if (tm.isTranslation())
+            out("Transform.translate(%.3f,%.3f)",tm[4],tm[5]);
+        else
+            out("Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)",tm[0],tm[1],tm[2],tm[3],tm[4],tm[5]);
+        out("]\n");
+    }
+
+    if (strlen(indent) > 0)
+        out("%s},\n",indent);
+    else
+        out("}\n");
+    return true;
+}
+
+
+/**
+ *  Output the tree data to buffer
+ */
+bool JavaFXZ::processEffect(SPObject *obj)
+{
+    if (SP_IS_GAUSSIANBLUR(obj)) {
+        SPGaussianBlur *blur = SP_GAUSSIANBLUR(obj);
+        double radius = 2.0 * blur->stdDeviation.getNumber();
+        if (radius >= 64.0)
+            radius = 64.0;
+        if (radius <= 1.0)
+            radius = 1.0;
+        out("%s    effect: GaussianBlur { radius : %.3f }\n", indent, radius);
+    }
+
+    for (SPObject *child = obj->firstChild() ; child ; child = child->next)
+    {
+		if (!processEffect(child))
+		    return false;
+    }
+
+    return true;
+}
+
+/**
+ *  Output the path data to buffer
+ */
+bool JavaFXZ::generateClip(SPObject *obj)
+{
+    bool ret = true;
+    gchar orig_indent[4096];
+    Glib::ustring id;
+    gchar const *cid = sp_object_getAttribute(obj, "id", NULL);
+    
+    if (!cid)
+        return true;
+
+    // Convert SVG id to "valid" JavaFX id
+    id  = sanatize(cid);
+
+    strcpy(orig_indent, indent);   // save original indent
+    sprintf(indent+strlen(indent), "        ");   //add two indentation shifts
+
+    SPItem *item = SP_ITEM(obj);
+
+    if (SP_IS_RECT(item)) {
+        out("%s    clip:\n",orig_indent);
+        SPRect *rect = SP_RECT(item);
+        if ( !doRect(rect, id) )
+            ret = false;
+        goto finish;
+    }
+    if (SP_IS_GENERICELLIPSE(item)) {
+        SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item);
+        //------------------------------- if path is not closed
+        if ( !ellipse->closed )
+            goto svgpath;
+        if ( (ellipse->start + 3.14159265358979323846 - ellipse->end) > 1e-8 )
+            goto svgpath;
+        out("%s    clip:\n",orig_indent);
+        if ( (ellipse->rx.computed - ellipse->ry.computed) < 1e-8 ) {
+            if ( !doCircle(ellipse, id) )
+                ret = false;
+            goto finish;
+        }
+        if (!doEllipse(ellipse, id))
+            ret = false;
+        goto finish;
+    }
+
+svgpath:
+    out("%s    clip:\n",orig_indent);
+    if (!doCurve(item, id))
+        ret = false;
+
+finish:
+    strcpy(indent, orig_indent);
+    return true;
+}
+
+
+//########################################################################
+//# M A I N    O U T P U T
+//########################################################################
+
+
+
+/**
+ *  Set values back to initial state
+ */
+void JavaFXZ::reset()
+{
+    // In case of pointers, unreference first and then clear
+    std::map<Glib::ustring, SPGradientPtr>::iterator ig;
+    for (ig = gradients.begin(); ig != gradients.end(); ig++) {
+        ig->second = NULL;
+    }
+    gradients.clear();
+
+    std::map<Glib::ustring, SPFilterPtr>::iterator ie;
+    for (ie = effects.begin(); ie != effects.end(); ie++) {
+        ie->second = NULL;
+    }
+    effects.clear();
+
+    std::map<Glib::ustring, SPClipPathPtr>::iterator ic;
+    for (ic = clippaths.begin(); ic != clippaths.end(); ic++) {
+        ic->second = NULL;  // unref
+    }
+    clippaths.clear();
+
+    imageTable.clear();
+    fontVector.clear();
+    name.clear();
+    outbuf.clear();
+}
+
+
+/**
+ *  Output the tree data to buffer
+ */
+bool JavaFXZ::traverseTree(ZipFile &zf, Inkscape::XML::Node *node)
+{
+    /**
+     * Check the type of node and process
+     */
+    int i;
+    Glib::ustring id;
+    SPObject *obj = NULL;
+    Glib::ustring nodeName = node->name();
+    char const *cid = node->attribute("id");
+    bool rc = true;
+
+    indent[0] = '\0';
+    for (i = 0; i<ntabs; i++)
+        strcat(indent,"    ");
+
+    if (!cid)
+        goto recursion;
+
+    // Convert SVG id to "valid" JavaFX id
+    id  = sanatize(cid);
+
+    // Get object by node
+    obj = SP_ACTIVE_DOCUMENT->getObjectByRepr(node);
+    if (!obj)
+        goto recursion;
+
+    do {
+        if (SP_IS_GROUP(obj)) {
+            //out("%s//    OBJECT id: %s is GROUP\n", indent, cid);
+            out("%sGroup {\n", indent);
+            if (strncmp(obj->id, "jfx:", 4) == 0)
+                out("%s    id: \"%s\"\n", indent, obj->id + 4);
+            ntabs++;
+            strcat(indent,"    ");
+            out("%scontent: [\n", indent);
+            break; 
+        }
+        if (SP_IS_IMAGE(obj)) {
+            //out("%s//    OBJECT id: %s is IMAGE\n", indent, cid);
+            SPImage *image = SP_IMAGE(obj);
+            if (!doImage(zf, image, id)) {
+                rc = false;
+                goto finish;
+            }
+            break;
+        }
+        if (SP_IS_TEXT(obj)) {
+            //out("%s//    OBJECT id: %s is TEXT\n", indent, cid);
+            SPText *text = SP_TEXT(obj);
+            if (!doText(zf, text, id)) {
+                rc = false;
+                goto finish;
+            }
+            break;
+        }
+        if (SP_IS_GRADIENT(obj)) {
+            //out("%s//    OBJECT id: %s is GRADIENT\n", indent, cid);
+            SPGradient *grad = SP_GRADIENT(obj);
+            gradients[id] = grad;
+            break;
+        }
+        if (SP_IS_FILTER(obj)) {
+            //out("%s//    OBJECT id: %s is FILTER\n", indent, cid);
+            SPFilter *filter = SP_FILTER(obj);
+            effects[id] = filter;
+            break;
+        }
+        if (SP_IS_CLIPPATH(obj)) {
+            //out("%s//    OBJECT id: %s is CLIPPATH\n", indent, cid);
+            SPClipPath *clip = SP_CLIPPATH(obj);
+            clippaths[id] = clip;
+            break;
+        }       
+        if (SP_IS_SHAPE(obj)) {
+            if (definitions)
+                break;          // ignore in case of '<defs>'  
+            //out("%s//    OBJECT id: %s is SHAPE\n", indent, cid);
+            //SPShape *shape = SP_SHAPE(obj);
+            currentItem = SP_ITEM(obj);
+            if (SP_IS_RECT(obj)) {
+                //out("%s//    OBJECT id: %s is RECTANGLE\n", indent, cid);
+                SPRect *item = SP_RECT(obj);
+                if (!doRect(item, id)) {
+                    rc = false;
+                    goto finish;
+                }
+                break;
+            }
+            else if (SP_IS_GENERICELLIPSE(obj)) {
+                //out("%s//    OBJECT id: %s is GENERICELLIPSE\n", indent, cid);
+                SPGenericEllipse *ellipse = SP_GENERICELLIPSE(obj);
+                if ( !ellipse->closed )
+                    goto svgpath;
+                if ( (ellipse->start + 3.14159265358979323846 - ellipse->end) > 1e-8 )
+                    goto svgpath;
+                if ( (ellipse->rx.computed - ellipse->ry.computed) < 1e-8 ) {
+                    if (!doCircle(ellipse, id)) {
+                        rc = false;
+                        goto finish;
+                    }
+                    break;
+                }
+                if (!doEllipse(ellipse, id)) {
+                    rc = false;
+                    goto finish;
+                }
+                break;
+            }
+
+   svgpath:
+            if (definitions)
+                break;
+            //out("%s//    OBJECT id: %s is ITEM\n", indent, cid);
+            SPItem *item = SP_ITEM(obj);
+            currentItem = item;
+            if (!doCurve(item, id)) {
+                rc = false;
+                goto finish;
+            }
+            break;     
+        }
+        
+        /*
+        if (SP_IS_ITEM(obj)) {
+            out("%s//    OBJECT id: %s is ITEM and NOT a SHAPE\n", indent, cid);
+            break;
+        }
+        else
+            out("%s//    OBJECT id: %s is NOT ITEM\n", indent, cid);
+        */
+    } while(0);
+
+
+recursion:
+    if (SP_IS_DEFS(obj))
+        definitions = true;
+    else
+        ntabs++;    
+
+    for (Inkscape::XML::Node *child = node->firstChild(); child; child = child->next())
+    {
+        if (!traverseTree(zf, child)) {
+            rc = false;
+            break;
+        }
+    }
+
+    if (SP_IS_DEFS(obj))
+        definitions = false;
+    else
+        ntabs--;
+    indent[4 * ntabs] = '\0';
+    
+
+    if (SP_IS_GROUP(obj))
+    {
+        out("%s]\n", indent);
+        ntabs--;
+        indent[4 * ntabs] = '\0';
+    }
+
+    if (  SP_IS_GROUP(obj) )
+    {
+        if (ntabs)
+            out("%s},\n", indent);
+        else
+            out("}\n");
+    }
+
+finish:
+    return rc;
+}
+
+
+/**
+ * Saves the <paths> of an Inkscape SVG file as JavaFX spline definitions
+ */
+bool JavaFXZ::saveDocument(SPDocument *doc, gchar const *uri)
+{
+    reset();
+
+    Glib::ustring dirname = Glib::path_get_dirname(uri);
+    name = Glib::path_get_basename(uri);
+
+    int pos = name.find('.');
+    if (pos > 0)
+        name = name.substr(0, pos);
+
+    //g_message("native file:%s, name %s, dirname %s\n", uri, name.c_str(), dirname.c_str());
+    unlink(uri);
+    documentUri = URI(uri);
+    ZipFile zf;
+    int err = 0;
+    zf = zip_open(uri, ZIP_CREATE | ZIP_EXCL, &err);
+    // TODO:  Here we need to handle error code
+
+    ntabs = 0;
+    definitions = false;
+    if (!traverseTree(zf, doc->rroot))
+        return false;
+
+    String curveBuf = outbuf;
+    outbuf.clear();
+
+    if (!doHeader(doc))
+        return false;
+
+    outbuf.append(curveBuf);
+
+    if (!doTail())
+        return false;
+
+    ZipEntry *ze = zip_source_buffer(zf, outbuf.c_str(), outbuf.size(), 0);
+    if (ze) {
+        zip_add(zf, "content.fxd", ze);
+        zipfile_comment(zf,"content.fxd","JavaFX Data file");
+    }
+    zip_close(zf);
+
+    return true;
+}
+
+
+//########################################################################
+//# EXTENSION API
+//########################################################################
+
+#include "clear-n_.h"
+
+/**
+ * API call to save document
+*/
+void
+JavaFXZ::save(Inkscape::Extension::Output */*mod*/,
+                        SPDocument *doc, gchar const *uri)
+{
+    if (!saveDocument(doc, uri))
+    {
+        g_warning("Could not save JavaFX file '%s'", uri);
+    }
+}
+
+
+
+/**
+ * Make sure that we are in the database
+ */
+bool JavaFXZ::check (Inkscape::Extension::Extension */*module*/)
+{
+    /* We don't need a Key
+    if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_JFX))
+        return FALSE;
+    */
+
+    return true;
+}
+
+
+
+/**
+ * This is the definition of JavaFX output.  This function just
+ * calls the extension system with the memory allocated XML that
+ * describes the data.
+*/
+void
+JavaFXZ::init()
+{
+    Inkscape::Extension::build_from_mem(
+        "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
+            "<name>" N_("FXD/FXZ Output") "</name>\n"
+            "<id>org.inkscape.output.fxd</id>\n"
+            "<output>\n"
+                "<extension>.fxz</extension>\n"
+                "<mimetype>text/x-javafx-content</mimetype>\n"
+                "<filetypename>" N_("JavaFX Content (*.fxz)") "</filetypename>\n"
+                "<filetypetooltip>" N_("JavaFX FXD/FXZ Content File") "</filetypetooltip>\n"
+            "</output>\n"
+        "</inkscape-extension>",
+        new JavaFXZ());
+}
+
+
+
+
+}  // namespace Internal
+}  // namespace Extension
+}  // namespace Inkscape
+
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff -Naur inkscape2/src/extension/internal/javafx-fxz.h inkscape/src/extension/internal/javafx-fxz.h
--- inkscape2/src/extension/internal/javafx-fxz.h	1970-01-01 01:00:00.000000000 +0100
+++ inkscape/src/extension/internal/javafx-fxz.h	2009-02-10 10:35:03.000000000 +0100
@@ -0,0 +1,178 @@
+/*
+ * JavaFX 1.0 plugin for Inkscape as a free extension to JavaFX Production Suite.
+ *
+ * The output is JavaFX 1.0 Content File (.fxz) and can be viewed by netbeans with
+ * FXD viewer plugin installed.
+ *  
+ *  For information on JavaFX Production Suite, see:
+ *      http://javafx.com/docs/gettingstarted/production_suite/
+ *
+ *  For information on the JavaFX file format, see:
+ *      https://openjfx.dev.java.net/
+ *      
+ * Based on the work of authors:
+ * 
+ *   Bob Jamison <ishmal@inkscape.org>
+ *   Silveira Neto <silveiraneto@gmail.com>
+ *   Jim Clarke <Jim.Clarke@sun.com>
+ *
+ * Copyright (C) 2008 Authors
+ *
+ * Updates:
+ *
+ *   Jan 2009 by Sergey Esenov <serguei.essenov@desy.de>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef EXTENSION_INTERNAL_JAVAFX_FXZ_H
+#define EXTENSION_INTERNAL_JAVAFX_FXZ_H
+
+#include <dom/dom.h>
+#include <dom/io/stringstream.h>
+#include <dom/uri.h>
+
+#include <glib.h>
+#include "extension/implementation/implementation.h"
+#include <document.h>
+#include <sp-gradient.h>
+#include <sp-filter.h>
+#include <sp-gaussian-blur.h>
+#include <sp-rect.h>
+#include <sp-ellipse.h>
+#include <sp-image.h>
+#include <sp-text.h>
+#include <sp-clippath.h>
+
+#include <string>
+#include <map>
+#include <vector>
+#include <zip.h>
+
+namespace Inkscape
+{
+namespace Extension
+{
+namespace Internal
+{
+
+// Use the same structures as in odf.h
+
+typedef org::w3c::dom::URI URI;
+typedef org::w3c::dom::io::Writer Writer;
+//========================= libzip1 based implementation
+typedef struct zip * ZipFile;
+typedef struct zip_source ZipEntry;
+
+
+/**
+ * Output the current SVG document in JavaFX content format.
+ * 
+ * For information, @see:  
+ * https://openjfx.dev.java.net/
+ */ 
+class JavaFXZ : public Inkscape::Extension::Implementation::Implementation
+{
+public:
+
+    typedef Glib::ustring String;
+    typedef SPGradient*   SPGradientPtr;
+    typedef SPFilter*     SPFilterPtr;
+    typedef SPClipPath*   SPClipPathPtr;
+
+    /**
+     * Check whether we can actually output using this module
+     */
+    virtual bool check (Inkscape::Extension::Extension * module);
+
+    /**
+     * API call to perform the output to a file
+     */
+    virtual void save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri);
+
+    /**
+     * Inkscape runtime startup call.
+     */
+    static void init(void);
+	
+    /**
+     * Reset variables to initial state
+     */
+    void reset();
+	
+private:
+
+    URI documentUri;
+
+    std::map<Glib::ustring, SPGradientPtr> gradients;     // Gradient table
+    std::map<Glib::ustring, SPFilterPtr>   effects;       // Filter effect's table
+    std::map<Glib::ustring, SPClipPathPtr> clippaths;     // Clip path's table
+    std::map<Glib::ustring, Glib::ustring> imageTable;    // Images renaming table
+    std::vector<Glib::ustring> fontVector;                // file names of used fonts besides ...
+                                                          // ... Arial, SansSerif, Times Roman
+    SPItem *currentItem;     // Internal variable for keeping current item
+
+    //output class name
+    Glib::ustring name;
+    //For formatted output
+    Glib::ustring outbuf;   //main output buffer
+
+
+    /**
+     * Format text to our output buffer
+     */
+    void out(const char *fmt, ...) G_GNUC_PRINTF(2,3);
+
+    /**
+     * Output the file header
+     */
+    bool doHeader(SPDocument *doc);
+
+    /**
+     *  Output gradient information to the buffer
+     */
+    bool processGradient(SPGradient *grad);
+
+    /**
+     *  Output filter information to the buffer
+     */
+    bool processFilter(SPFilter *filter);
+
+    /**
+     *  Output clip-path information to the buffer
+     */
+    bool processClipPath(SPClipPath *clip);
+    bool doClipPath(SPClipPathReference *ref);
+
+    /**
+     *  Output an element's style attribute
+     */
+    bool doStyle(SPStyle *style);
+
+    /**
+     * Output the SVG document's curve data as JavaFX geometry types
+     */
+    bool doRect(SPRect *item, const Glib::ustring &id);
+    bool doCircle(SPGenericEllipse *item, const Glib::ustring& id);
+    bool doEllipse(SPGenericEllipse *item, const Glib::ustring& id);
+    bool doCurve(SPItem *item, const Glib::ustring& id);
+    bool doImage(ZipFile &zf, SPImage *image,    const String &id);
+    bool doText(ZipFile &zf, SPText *text,       const String &id);
+
+    bool processEffect(SPObject *obj);
+    bool generateClip(SPObject *obj);
+    bool traverseTree(ZipFile &zf, Inkscape::XML::Node *node);
+
+    /**
+     * Output the file footer
+     */
+    bool doTail();
+
+    bool saveDocument(SPDocument *doc, const gchar *uri);
+};
+
+}  // namespace Internal
+}  // namespace Extension
+}  // namespace Inkscape
+#endif /* EXTENSION_INTERNAL_JAVAFX_FXZ_H */
+
diff -Naur inkscape2/src/extension/internal/javafx-out.cpp inkscape/src/extension/internal/javafx-out.cpp
--- inkscape2/src/extension/internal/javafx-out.cpp	2009-02-12 10:39:35.000000000 +0100
+++ inkscape/src/extension/internal/javafx-out.cpp	2009-02-10 10:35:03.000000000 +0100
@@ -11,6 +11,9 @@
  *
  * Copyright (C) 2008 Authors
  *
+ * Updated 07 Jan 2009 by Sergey Esenov <sergey.esenov@gmail.com>
+ *   - Added support for gradients, texts, images.
+ *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
@@ -18,12 +21,20 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include "javafx-out.h"
 #include <inkscape.h>
 #include <inkscape-version.h>
+#include <interface.h>
+#include <sp-root.h>
 #include <sp-path.h>
+#include <sp-rect.h>
+#include <sp-ellipse.h>
 #include <sp-linear-gradient.h>
 #include <sp-radial-gradient.h>
+#include <sp-gaussian-blur.h>
+#include <sp-filter.h>
+#include <sp-image.h>
+#include <sp-text.h>
+#include <text-editing.h>
 #include <style.h>
 #include <display/curve.h>
 #include <display/canvas-bpath.h>
@@ -42,6 +53,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 
+#include "javafx-out.h"
 
 namespace Inkscape
 {
@@ -51,7 +63,8 @@
 {
 
 
-
+//# Shorthand notation
+typedef org::w3c::dom::DOMString DOMString;
 
 //########################################################################
 //# M E S S A G E S
@@ -84,11 +97,11 @@
 {
     double val = 1.0;
     for (SPObject const *obj = style->object; obj ; obj = obj->parent)
-        {
+    {
         style = SP_OBJECT_STYLE(obj);
         if (style)
             val *= SP_SCALE24_TO_FLOAT(style->opacity.value);
-        }
+    }
     return val;
 }
 
@@ -192,7 +205,7 @@
  */
 static JavaFXOutput::String sanatize(const JavaFXOutput::String &badstr){
     JavaFXOutput::String good(badstr);
-    for (int pos = 0; pos < badstr.length(); ++pos )
+    for (unsigned int pos = 0; pos < badstr.length(); ++pos )
         if((badstr.at(pos)=='-')||(badstr.at(pos)==' '))
             good.replace(pos, 1, "_");
     return good;
@@ -216,7 +229,7 @@
 /**
  * Output the file header
  */
-bool JavaFXOutput::doHeader()
+bool JavaFXOutput::doHeader(SPDocument *doc)
 {
     time_t tim = time(NULL);
     out("/*###################################################################\n");
@@ -228,7 +241,7 @@
     out("### NOTES:\n");
     out("### ============\n");
     out("### JavaFX information can be found at\n");
-    out("### hhttps://openjfx.dev.java.net\n");
+    out("### https://openjfx.dev.java.net\n");
     out("###\n");
     out("### If you have any problems with this output, please see the\n");
     out("### Inkscape project at http://www.inkscape.org, or visit\n");
@@ -241,21 +254,29 @@
     out("##==========================\n");
     out("##    Shapes   : %d\n", nrShapes);
     out("##    Nodes    : %d\n", nrNodes);
+    out("#####################################################################\n");
+    out("##   Document settings\n");
+    out("##==========================\n");
+    out("##    Document width  : %.3f\n", sp_document_height(doc));
+    out("##    Document height : %.3f\n", sp_document_height(doc));
     out("###################################################################*/\n");
     out("\n\n");
 
     // import javafx libraries we can need
-    out("import javafx.application.*;\n");
+    out("import javafx.stage.*;\n");
     out("import javafx.scene.*;\n");
-    out("import javafx.scene.geometry.*;\n");
+    out("import javafx.scene.shape.*;\n");
     out("import javafx.scene.transform.*;\n");
     out("import javafx.scene.paint.*;\n");
+    out("import javafx.scene.effect.*;\n");
+    out("import javafx.scene.text.*;\n");
+    out("import javafx.scene.image.*;\n");
     out("\n");
 
     out("\n\n");
 
     // Creates a class extended from CustomNode
-    out("public class %s extends CustomNode {\n", name.c_str());
+    out("class %s extends CustomNode {\n", name.c_str());
 
     return true;
 }
@@ -265,116 +286,142 @@
 /**
  *  Output the file footer
  */
-bool JavaFXOutput::doTail()
+bool JavaFXOutput::doTail(SPDocument *doc)
 {
     float border = 25.0;
+    double scaleX = 1.0;
+    double scaleY = 1.0;
+    double width  = sp_document_width ( doc );
+    double height = sp_document_height( doc );
+    
+    if (doc != NULL) {
+        SPRoot *root = SP_ROOT(doc->root);
+	if (root != NULL && root->viewBox_set) {
+	    scaleX = width  / (root->viewBox.x1 - root->viewBox.x0);
+	    scaleY = height / (root->viewBox.y1 - root->viewBox.y0);
+            if (scaleX != scaleY) {
+                scaleY = scaleX;
+	    }
+        }
+    }
 
     // Write the tail of CustomNode
-    out("           ] // content\n");
-    out("           transform: Translate { x : %s, y : %s }\n",
-	          DSTR((-minx) + border), DSTR((-miny) + border) );
-    out("       } // Group\n");
-    out("   } // function create()\n");
+    out("            ] // content\n");
+    out("            translateX : %.3f, translateY : %.3f\n", border, border );
+    out("            scaleX : %.3f, scaleY : %.3f\n", scaleX, scaleY);
+    out("        } // Group\n");
+    out("    } // function create()\n");
     out("} // class %s\n", name.c_str());
     out("\n");
 
     // Frame
-    out("Frame {\n");
+    out("Stage {\n");
     out("    title: \"%s\"\n", name.c_str());
-    out("    width: %s\n",  ISTR(maxx-minx + border * 2.0));
-    out("    height: %s\n", ISTR(maxy-miny + border * 2.0));
+    out("    width: %s\n",  ISTR(width  * scaleX + border * 2.0));
+    out("    height: %s\n", ISTR(height * scaleY + border * 2.0));
     out("    visible: true\n");
 
     // Stage
-    out("    stage: Stage {\n");
+    out("    scene: Scene {\n");
     out("        content: %s{}\n", name.c_str());
-    out("    } // Stage\n");
-
-    out("} // Frame\n");
-
-    out("\n");
+    out("    } // Scene\n");
 
+    out("} // Stage\n\n");
     out("/*###################################################################\n");
     out("### E N D   C L A S S    %s\n", name.c_str());
-    out("###################################################################*/\n");
-    out("\n\n");
+    out("###################################################################*/\n\n\n");
     return true;
 }
 
 
-
 /**
  *  Output gradient information to the buffer
  */
-bool JavaFXOutput::doGradient(SPGradient *grad, const String &id)
+bool JavaFXOutput::processGradient(SPGradient *grad)
 {
-    String jfxid = sanatize(id);
-
+    if (!grad) return true;
+    Geom::Matrix gt = grad->gradientTransform;
+    //char *transform_text = sp_svg_transform_write(gt);
     if (SP_IS_LINEARGRADIENT(grad))
-        {
+    {
         SPLinearGradient *g = SP_LINEARGRADIENT(grad);
-        out("    /* create LinearGradient for %s */\n", jfxid.c_str());
-        out("    private function %s(): LinearGradient {\n",  jfxid.c_str());
-        out("        LinearGradient {\n");
+	Geom::Matrix m1 = Geom::Matrix(Geom::Translate(g->x1.value, g->y1.value)) * gt;
+	Geom::Matrix m2 = Geom::Matrix(Geom::Translate(g->x2.value, g->y2.value)) * gt;
+	Geom::Point  p1 = m1.translation();
+	Geom::Point  p2 = m2.translation();
+
+        //g_free(transform_text);
+        out("                LinearGradient {\n");
+        out("                    startX: %.3f, startY: %.3f, endX: %.3f, endY: %.3f\n", p1[0], p1[1], p2[0], p2[1]);
+        if (SP_GRADIENT_UNITS(grad) == SP_GRADIENT_UNITS_USERSPACEONUSE)
+            out("                    proportional: false\n");
         std::vector<SPGradientStop> stops = g->vector.stops;
         if (stops.size() > 0)
-            {
-            out("            stops:\n");
-            out("                [\n");
+        {
+            out("                    stops: [\n");
             for (unsigned int i = 0 ; i<stops.size() ; i++)
-                {
+            {
                 SPGradientStop stop = stops[i];
-                out("                Stop {\n");
-                out("                    offset: %s\n", DSTR(stop.offset));
-                out("                    color: %s\n",  rgba(stop.color, stop.opacity).c_str());
-                out("                },\n");
-                }
-            out("            ]\n");
+                out("                        Stop { offset: %.3f, color: %s },\n", stop.offset, rgba(stop.color, stop.opacity).c_str());
             }
-        out("        };\n");
-        out("    } // end LinearGradient: %s\n", jfxid.c_str());
-        out("\n\n");
+            out("                    ]\n");
         }
+        out("                }\n");
+    }
     else if (SP_IS_RADIALGRADIENT(grad))
-        {
+    {
         SPRadialGradient *g = SP_RADIALGRADIENT(grad);
-        out("    /* create RadialGradient for %s */\n", jfxid.c_str());
-        out("    private function %s() {\n", jfxid.c_str());
-        out("        RadialGradient {\n");
-        out("            centerX: %s\n", DSTR(g->cx.value));
-        out("            centerY: %s\n", DSTR(g->cy.value));
-        out("            focusX: %s\n",  DSTR(g->fx.value));
-        out("            focusY: %s\n",  DSTR(g->fy.value));
-        out("            radius: %s\n",  DSTR(g->r.value ));
+	Geom::Matrix mc = Geom::Matrix(Geom::Translate(g->cx.value, g->cy.value)) * gt;
+        Geom::Matrix mf = Geom::Matrix(Geom::Translate(g->fx.value, g->fy.value)) * gt;
+        Geom::Matrix mr = Geom::Matrix(Geom::Scale(g->r.value, g->r.value)) * gt;
+	Geom::Point pc = mc.translation();
+        Geom::Point pf = mf.translation();
+        double rx = mr.expansionX();
+        double ry = mr.expansionY();
+        //g_free(transform_text);
+        out("                RadialGradient {\n");
+        out("                    centerX: %.3f, centerY: %.3f\n", pc[0], pc[1]);
+        out("                    focusX : %.3f, focusY : %.3f\n", pf[0], pf[1]);
+        // Use arithmetic mean value of rx and ry: javafx 1.0 doesn't support gradientTransform!
+        out("                    radius : %.3f\n", (rx+ry)/2.0);
+        if (SP_GRADIENT_UNITS(grad) == SP_GRADIENT_UNITS_USERSPACEONUSE)
+	    out("                    proportional: false\n"); 
         std::vector<SPGradientStop> stops = g->vector.stops;
         if (stops.size() > 0)
-            {
-            out("            stops:\n");
-            out("            [\n");
+        {
+            out("                    stops: [\n");
             for (unsigned int i = 0 ; i<stops.size() ; i++)
-                {
+            {
                 SPGradientStop stop = stops[i];
-                out("                Stop {\n");
-                out("                    offset: %s\n", DSTR(stop.offset));
-                out("                    color: %s\n",  rgba(stop.color, stop.opacity).c_str());
-                out("                },\n");
-                }
-            out("            ]\n");
+                out("                        Stop { offset: %.3f, color: %s },\n", stop.offset, rgba(stop.color, stop.opacity).c_str());
             }
-        out("        };\n");
-        out("    } // end RadialGradient: %s\n", jfxid.c_str());
-        out("\n\n");
+            out("                    ]\n");
         }
+        out("                }\n");
+    }
     else
-        {
-        err("Unknown gradient type for '%s'\n", jfxid.c_str());
+    {
+        //g_free(transform_text);
+        err("Unsupported gradient type\n");
         return false;
-        }
-
+    }
 
+    
     return true;
 }
 
+/**
+ *  Output filter information to the buffer
+ */
+bool JavaFXOutput::processFilter(SPFilter *filter)
+{
+    for (SPObject *child = filter->firstChild() ; child ; child = child->next)
+    {
+        if (!processEffect(child))
+            return false;
+    }
+    return true;
+}
 
 
 
@@ -386,28 +433,50 @@
     if (!style)
         return true;
 
-    out("            opacity: %s\n", DSTR(effective_opacity(style)));
+    out("            opacity: %.3f\n", effective_opacity(style));
 
     /**
      * Fill
      */
     SPIPaint fill = style->fill;
     if (fill.isColor())
-        {
+    {
         // see color.h for how to parse SPColor
         out("            fill: %s\n",
             rgba(fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value)).c_str());
-        }
-    else if (fill.isPaintserver()){
-        if (fill.value.href && fill.value.href->getURI() ){
+    }
+    else if (fill.isPaintserver()) {
+        if (fill.value.href && fill.value.href->getURI() ) {
             String uri = fill.value.href->getURI()->toString();
             /* trim the anchor '#' from the front */
             if (uri.size() > 0 && uri[0]=='#')
                 uri = uri.substr(1);
-            out("            fill: %s()\n", sanatize(uri).c_str());
+            SPGradient *grad = gradients[sanatize(uri)];
+            if (grad)
+                out("            fill:\n");
+            else
+                out("            fill: null\n");
+            if (!processGradient(grad))
+                return false;
         }
     }
+    else if (fill.isNoneSet())
+        out("            fill: null\n");
 
+    /**
+     * Filter
+     */
+    SPIFilter filter = style->filter;
+    if (filter.set) {
+        if (filter.href && filter.href->getURI()) {
+            String uri = filter.href->getURI()->toString();
+            if (uri.size() > 0 && uri[0]=='#')
+                uri = uri.substr(1);
+            SPFilter *filter = effects[sanatize(uri)];
+            if (!processFilter(filter))
+                return false;
+        }
+    }
 
     /**
      * Stroke
@@ -425,50 +494,154 @@
      * unsigned stroke_dashoffset_set : 1;
      * SPIScale24 stroke_opacity;
      */
-    if (style->stroke_opacity.value > 0)
-        {
+    if (!style->stroke.isNone() && style->stroke_opacity.value > 0)
+    {
         SPIPaint stroke = style->stroke;
         out("            stroke: %s\n",
             rgba(stroke.value.color, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)).c_str());
-        double strokewidth = style->stroke_width.value;
+        double strokewidth = style->stroke_width.computed;
         unsigned linecap   = style->stroke_linecap.value;
         unsigned linejoin  = style->stroke_linejoin.value;
-        out("            strokeWidth: %s\n",      DSTR(strokewidth));
-        out("            strokeLineCap: %s\n",    getStrokeLineCap(linecap).c_str());
-        out("            strokeLineJoin: %s\n",   getStrokeLineJoin(linejoin).c_str());
-        out("            strokeMiterLimit: %s\n", DSTR(style->stroke_miterlimit.value));
+        out("            strokeWidth     : %.3f\n", strokewidth);
+        out("            strokeLineCap   : %s\n",   getStrokeLineCap(linecap).c_str());
+        out("            strokeLineJoin  : %s\n",   getStrokeLineJoin(linejoin).c_str());
+        out("            strokeMiterLimit: %.3f\n", style->stroke_miterlimit.value);
         if(style->stroke_dasharray_set) {
            if(style->stroke_dashoffset_set) {
-               out("            strokeDashOffset: %s\n", DSTR(style->stroke_dash.offset));
+               out("            strokeDashOffset: %.3f\n", style->stroke_dash.offset);
            }
            out("            strokeDashArray: [ ");
-           for(int i = 0; i < style->stroke_dash.n_dash; i++ ) {
-               if(i > 0) {
+           for (int i = 0; i < style->stroke_dash.n_dash; i++ ) {
+               if (i > 0) {
                    out(", %.2lf", style->stroke_dash.dash[i]);
-               }else {
+               } else {
                    out(" %.2lf", style->stroke_dash.dash[i]);
                }
            }
            out(" ]\n");
         }
 
-        }
+    }
+    else if (style->stroke.isNone())
+        out("            stroke: null\n");
+
+    return true;
+}
+
+
+/**
+ *  Output rectangle to buffer
+ */
+bool JavaFXOutput::doRect(SPRect *item, const String &id)
+{
+    nrShapes++;
+
+    out("    /** rect %s */\n", id.c_str());
+    out("    function %s() : Rectangle {\n",id.c_str());
+    out("        Rectangle {\n");
+    //out("            id : \"%s\"\n", id.c_str());
+
+    /**
+     * Output the style information
+     */
+    if (!doStyle(SP_OBJECT_STYLE(item)))
+        return false;
+
+    out("            x : %.3f, y : %.3f\n", item->x.computed, item->y.computed);
+    out("            height : %.3f, width : %.3f\n", item->height.computed, item->width.computed);
+    out("            arcHeight : %.3f, arcWidth : %.3f\n", 2.0 * item->ry.computed, 2.0 * item->rx.computed);
+
+    // build transformation matrix:
+    Geom::Matrix const tm(sp_item_i2doc_affine(item)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0],pX[1],pY[0],pY[1],pZ[0],pZ[1]);
+    }
 
+    out("        };\n    }\n");
     return true;
 }
 
 
-#if 1
+/**
+ *  Output circle to buffer
+ */
+bool JavaFXOutput::doCircle(SPCircle *item, const String &id)
+{
+    nrShapes++;
+
+    out("    /** circle %s */\n", id.c_str());
+    out("    function %s() : Circle {\n",id.c_str());
+    out("        Circle {\n");
+    //out("            id : \"%s\"\n", id.c_str());
+
+    // Output the style information
+    if (!doStyle(SP_OBJECT_STYLE(item)))
+        return false;
+
+    out("            centerX : %.3f, centerY : %.3f\n", item->cx.value, item->cy.value);
+    out("            radius  : %.3f\n", item->rx.value);
+
+    // build transformation matrix:
+    Geom::Matrix const tm(sp_item_i2doc_affine(item)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0], pX[1], pY[0], pY[1], pZ[0], pZ[1]);
+    }
+
+    out("        };\n    }\n");
+    return true;
+}
+
+
+/**
+ *  Output ellipse to buffer
+ */
+bool JavaFXOutput::doEllipse(SPEllipse *item, const String &id)
+{
+    nrShapes++;
+
+    out("    /** ellipse %s */\n", id.c_str());
+    out("    function %s() : Ellipse {\n",id.c_str());
+    out("        Ellipse {\n");
+    //out("            id : \"%s\"\n", id.c_str());
+
+    // Output the style information
+    if (!doStyle(SP_OBJECT_STYLE(item)))
+        return false;
+
+    out("            centerX : %.3f, centerY : %.3f\n", item->cx.value, item->cy.value);
+    out("            radiusX : %.3f, radiusY : %.3f\n", item->rx.value, item->ry.value);
+
+    // build transformation matrix:
+    Geom::Matrix const tm(sp_item_i2doc_affine(item)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0],pX[1],pY[0],pY[1],pZ[0],pZ[1]);
+    }
+
+    out("        };\n    }\n");
+    return true;
+}
+
 
 /**
  *  Output the curve data to buffer
  */
-bool JavaFXOutput::doCurve(SPItem *item, const String &id)
+bool JavaFXOutput::doCurve(SPItem *item, const String &jfxid)
 {
     using Geom::X;
     using Geom::Y;
 
-    String jfxid = sanatize(id);
 
     //### Get the Shape
     if (!SP_IS_SHAPE(item))//Bulia's suggestion.  Allow all shapes
@@ -481,10 +654,13 @@
 
     nrShapes++;
 
+    gchar const *d = sp_object_getAttribute(item, "d", NULL);
     out("    /** path %s */\n", jfxid.c_str());
-    out("    private function %s() : Path {\n",jfxid.c_str());
-    out("        Path {\n");
-    out("            id: \"%s\"\n", jfxid.c_str());
+    out("    function %s() : SVGPath {\n",jfxid.c_str());
+    out("        SVGPath {\n");
+    //out("            id: \"%s\"\n", jfxid.c_str());
+    out("            content: \"%s\"\n", d);
+    out("            fillRule: FillRule.NON_ZERO\n");
 
     /**
      * Output the style information
@@ -493,9 +669,7 @@
         return false;
 
     // convert the path to only lineto's and cubic curveto's:
-    Geom::Scale yflip(1.0, -1.0);
-    Geom::Matrix tf = sp_item_i2d_affine(item) * yflip;
-    Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );
+    Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() );
 
     //Count the NR_CURVETOs/LINETOs (including closing line segment)
     guint segmentCount = 0;
@@ -505,7 +679,7 @@
             segmentCount += 1;
     }
 
-    out("            elements: [\n");
+    //out("            elements: [\n");
 
     unsigned int segmentNr = 0;
 
@@ -517,29 +691,21 @@
      * For all Subpaths in the <path>
      */
     for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit)
-        {
+    {
         Geom::Point p = pit->front().initialPoint();
         cminmax.expandTo(p);
-        out("                MoveTo {\n");
-        out("                    x: %s\n", DSTR(p[X]));
-        out("                    y: %s\n", DSTR(p[Y]));
-        out("                },\n");
 
         /**
          * For all segments in the subpath
          */
         for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit)
-            {
+        {
             //### LINE
             if( dynamic_cast<Geom::LineSegment  const *> (&*cit) ||
                 dynamic_cast<Geom::HLineSegment const *> (&*cit) ||
                 dynamic_cast<Geom::VLineSegment const *> (&*cit) )
                 {
                 Geom::Point p = cit->finalPoint();
-                out("                LineTo {\n");
-                out("                    x: %s\n", DSTR(p[X]));
-                out("                    y: %s\n", DSTR(p[Y]));
-                out("                },\n");
                 nrNodes++;
                 }
             //### BEZIER
@@ -549,14 +715,6 @@
                 Geom::Point p1 = points[1];
                 Geom::Point p2 = points[2];
                 Geom::Point p3 = points[3];
-                out("                CurveTo {\n");
-                out("                    controlX1: %s\n", DSTR(p1[X]));
-                out("                    controlY1: %s\n", DSTR(p1[Y]));
-                out("                    controlX2: %s\n", DSTR(p2[X]));
-                out("                    controlY2: %s\n", DSTR(p2[Y]));
-                out("                    x: %s\n",         DSTR(p3[X]));
-                out("                    y: %s\n",         DSTR(p3[Y]));
-                out("                },\n");
                 nrNodes++;
                 }
             else
@@ -565,15 +723,19 @@
                 }
             segmentNr++;
             cminmax.expandTo(cit->finalPoint());
-            }
-        if (pit->closed())
-            {
-            out("                ClosePath {},\n");
-            }
         }
+    }
+
+    Geom::Matrix const tm(sp_item_i2doc_affine(item)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0],pX[1],pY[0],pY[1],pZ[0],pZ[1]);
+    }
 
-    out("            ] // elements\n");
-    out("        }; // Path\n");
+    out("        }; // SVGPath\n");
     out("    } // end path %s\n\n", jfxid.c_str());
 
     double cminx = cminmax.min()[X];
@@ -593,208 +755,185 @@
     return true;
 }
 
+bool JavaFXOutput::doImage(SPImage *image, const Glib::ustring &id)
+{
+    out("    /** image %s */\n", id.c_str());
+    out("    function %s() : ImageView {\n", id.c_str());
+    out("        ImageView {\n");
+
+    out("            x: %s, y: %s\n",
+        sp_object_getAttribute(image, "x", NULL), sp_object_getAttribute(image, "y", NULL));
+    out("            fitWidth: %s, fitHeight: %s\n",
+        sp_object_getAttribute(image, "width", NULL), sp_object_getAttribute(image, "height", NULL));
+
+    char const *data_string = "data:image/";
+    char const *url_string = sp_object_getAttribute(image, "xlink:href", NULL);
+    if (strncmp(url_string, data_string, strlen(data_string)) == 0) {
+        char message[256];
+        sprintf(message,"No support for embedded image '%s' in JavaFX 1.0 ('null' image substituted)\n"
+			"Hint: use \"Effects->Images->Extract One Image...\" first!", id.c_str());
+        sp_ui_error_dialog(message);
+        out("            image: Image {url: null}\n");
+    }
+    else
+        out("            image: Image {url: \"{__DIR__}%s\"}\n", sp_object_getAttribute(image, "xlink:href", NULL));
 
+    Geom::Matrix const tm(sp_item_i2doc_affine(image)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0],pX[1],pY[0],pY[1],pZ[0],pZ[1]);
+    }
 
-#else
+    out("        };\n    }\n\n");
+    return true;
+}
 
-/**
- *  Output the curve data to buffer
- */
-bool JavaFXOutput::doCurve(SPItem *item, const String &id)
+bool JavaFXOutput::doText(SPText *text, const Glib::ustring &id)
 {
-    using Geom::X;
-    using Geom::Y;
-
-    //### Get the Shape
-    if (!SP_IS_SHAPE(item))//Bulia's suggestion.  Allow all shapes
-        return true;
+    out("    /** text %s */\n", id.c_str());
+    out("    function %s() : Text {\n",id.c_str());
+    out("        Text {\n");
+
+    SPStyle  *style = SP_OBJECT_STYLE(text);
+
+    if (style->text_decoration.set) {
+	if (style->text_decoration.overline)
+	    out("            overline : true\n");
+	if (style->text_decoration.underline)
+	    out("            underline : true\n");
+	if (style->text_decoration.line_through)
+	    out("            strikethrough : true\n");
+    }
+    if (style->text_align.set) {
+	if (style->text_align.value == SP_CSS_TEXT_ALIGN_LEFT ||
+		style->text_align.value == SP_CSS_TEXT_ALIGN_START) 
+	    out("            textAlignment : TextAlignment.LEFT\n");
+	else if (style->text_align.value == SP_CSS_TEXT_ALIGN_RIGHT ||
+		      style->text_align.value == SP_CSS_TEXT_ALIGN_END)
+	    out("            textAlignment : TextAlignment.RIGHT\n");
+	else if (style->text_align.value == SP_CSS_TEXT_ALIGN_CENTER)
+	    out("            textAlignment : TextAlignment.CENTER\n");
+	else if (style->text_align.value == SP_CSS_TEXT_ALIGN_JUSTIFY)
+	    out("            textAlignment : TextAlignment.JUSTIFY\n"); 
+    }
+    out("            font : Font {\n");
+    if (style->font_size.set)
+	out("                size : %.3f\n", style->font_size.computed);
+    if (style->text->font_family.set) {
+        char fullname[32];
+        int  len;
+        sprintf(fullname,"%s", style->text->font_family.value);
+        len = strlen(fullname);
+        if (style->font_stretch.set) {
+            if (style->font_stretch.value == SP_CSS_FONT_STRETCH_ULTRA_CONDENSED)
+                sprintf(fullname+len," UltraCondensed");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_EXTRA_CONDENSED)
+                sprintf(fullname+len," ExtraCondensed");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_CONDENSED)
+                sprintf(fullname+len," Condensed");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_SEMI_CONDENSED)
+                sprintf(fullname+len," SemiCondensed");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_NORMAL)
+                ;
+            else if (style->font_stretch.value ==  SP_CSS_FONT_STRETCH_SEMI_EXPANDED)
+                sprintf(fullname+len," SemiExpanded");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_EXPANDED)
+                sprintf(fullname+len," Expanded");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_EXTRA_EXPANDED)
+                sprintf(fullname+len," ExtraExpanded");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_ULTRA_EXPANDED)
+                sprintf(fullname+len," UltraExpanded");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_NARROWER)
+                sprintf(fullname+len," Narrower");
+            else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_WIDER)
+                sprintf(fullname+len," Wider");
+        }
 
-    SPShape *shape = SP_SHAPE(item);
-    SPCurve *curve = shape->curve;
-    if (curve->is_empty())
-        return true;
+        len = strlen(fullname);
+        if (style->font_weight.set) {
+            if (style->font_weight.value >= SP_CSS_FONT_WEIGHT_BOLD)
+                sprintf(fullname+len," Bold");
+        }
 
-    nrShapes++;
+        len = strlen(fullname);
+        if (style->font_style.set) {
+            if (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC)
+                sprintf(fullname+len," Italic");
+            else if (style->font_style.value == SP_CSS_FONT_STYLE_OBLIQUE)
+                sprintf(fullname+len," Oblique");
+        }
+	out("                name : \"%s\"\n", fullname);
+    }
+    out("            }\n");
 
-    out("        SVGPath \n");
-    out("        {\n");
-    out("        id: \"%s\"\n", id.c_str());
 
     /**
      * Output the style information
      */
-    if (!doStyle(SP_OBJECT_STYLE(shape)))
+    if (!doStyle(style))
         return false;
-
-    // convert the path to only lineto's and cubic curveto's:
-    Geom::Scale yflip(1.0, -1.0);
-    Geom::Matrix tf = sp_item_i2d_affine(item) * yflip;
-    Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );
-    
-    //Count the NR_CURVETOs/LINETOs (including closing line segment)
-    nrNodes = 0;
-    for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {
-        nrNodes += (*it).size();
-        if (it->closed())
-            nrNodes += 1;
+   
+    //Inkscape::XML::Node *node = SP_OBJECT(text)->repr;
+    char const *posX = sp_object_getAttribute(text, "x", NULL); //node->attribute("x")
+    char const *posY = sp_object_getAttribute(text, "y", NULL); //node->attribute("y");
+    if (posX)
+        out("            x: %s\n", posX);
+    if (posY)
+        out("            y: %s\n", posY);
+    Inkscape::Text::Layout const *layout = te_get_layout(text);
+    Glib::ustring content = sp_te_get_string_multiline(text, layout->begin(), layout->end());
+    out("            content : \"%s\"\n", content.c_str());
+
+    // build transformation matrix:
+    Geom::Matrix const tm(sp_item_i2doc_affine(text)); // <- _c[0],_c[1],_c[2],_c[3],_c[4],_c[5]
+    if ( !tm.isIdentity() ) {
+        Geom::Point pX = tm.xAxis();          // <- _c[0], _c[1]
+        Geom::Point pY = tm.yAxis();          // <- _c[2], _c[3]
+        Geom::Point pZ = tm.translation();    // <- _c[4], _c[5]
+        out("            transforms : Transform.affine(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n",
+                 pX[0],pX[1],pY[0],pY[1],pZ[0],pZ[1]);
     }
 
-    char *dataStr = sp_svg_write_path(pathv);
-    out("        content: \"%s\"\n", dataStr);
-    free(dataStr);
-
-    Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() ); 
-
-    /**
-     * Get the Min and Max X and Y extends for the Path. 
-     * ....For all Subpaths in the <path>
-     */	     
-    for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit)
-        {
-        cminmax.expandTo(pit->front().initialPoint());
-        /**
-         * For all segments in the subpath
-         */		         
-        for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit)
-            {
-            cminmax.expandTo(cit->finalPoint());
-            }
-        }
-
-    out("        },\n");
-
-    double cminx = cminmax.min()[X];
-    double cmaxx = cminmax.max()[X];
-    double cminy = cminmax.min()[Y];
-    double cmaxy = cminmax.max()[Y];
-
-    if (cminx < minx)
-        minx = cminx;
-    if (cmaxx > maxx)
-        maxx = cmaxx;
-    if (cminy < miny)
-        miny = cminy;
-    if (cmaxy > maxy)
-        maxy = cmaxy;
-
+    out("        };\n    }\n");
     return true;
 }
 
 
-
-#endif  /* #if o */
-
-
-
 /**
  *  Output the tree data to buffer
  */
-bool JavaFXOutput::doTreeRecursive(SPDocument *doc, SPObject *obj)
+bool JavaFXOutput::processEffect(SPObject *obj)
 {
-    /**
-     * Check the type of node and process
-     */
-    String id;
-    if (!obj->id)
-        {
-        char buf[16];
-        sprintf(buf, "id%d", idindex++);
-        id = buf;
-        }
-    else
-        {
-        id = obj->id;
-        }
-    if (SP_IS_ITEM(obj))
-        {
-        SPItem *item = SP_ITEM(obj);
-        if (!doCurve(item, id))
-            return false;
-        }
-    else if (SP_IS_GRADIENT(obj))
-        {
-        SPGradient *grad = SP_GRADIENT(obj);
-        if (!doGradient(grad, id))
-            return false;
-        }
+    if (SP_IS_GAUSSIANBLUR(obj)) {
+        SPGaussianBlur *blur = SP_GAUSSIANBLUR(obj);
+        double radius = 2.0 * blur->stdDeviation.getNumber();
+        if (radius >= 64.0)
+            radius = 64.0;
+        if (radius <= 1.0)
+            radius = 1.0;
+        out("            effect: GaussianBlur { radius : %.3f }\n", radius);
+    }
 
-    /**
-     * Descend into children
-     */	     
     for (SPObject *child = obj->firstChild() ; child ; child = child->next)
-        {
-		if (!doTreeRecursive(doc, child))
+    {
+		if (!processEffect(child))
 		    return false;
-		}
+    }
 
     return true;
 }
 
 
-/**
- *  Output the curve data to buffer
- */
-bool JavaFXOutput::doTree(SPDocument *doc)
-{
-
-    double bignum = 1000000.0;
-    minx  =  bignum;
-    maxx  = -bignum;
-    miny  =  bignum;
-    maxy  = -bignum;
-
-    if (!doTreeRecursive(doc, doc->root))
-        return false;
-
-    return true;
-
-}
 
-
-bool JavaFXOutput::doBody(SPDocument *doc, SPObject *obj)
+void JavaFXOutput::writeBody()
 {
-    /**
-     * Check the type of node and process
-     */
-    String id;
-    if (!obj->id)
-        {
-        char buf[16];
-        sprintf(buf, "id%d", idindex++);
-        id = buf;
-        }
-    else
-        {
-        id = obj->id;
-        }
-
-    if (SP_IS_ITEM(obj)) {
-        SPItem *item = SP_ITEM(obj);
-        //### Get the Shape
-        if (SP_IS_SHAPE(item)) {//Bulia's suggestion.  Allow all shapes
-            SPShape *shape = SP_SHAPE(item);
-            SPCurve *curve = shape->curve;
-            if (!curve->is_empty())
-                out("               %s(),\n", id.c_str());
-        }
-    }
-    else if (SP_IS_GRADIENT(obj)) {
-        //TODO: what to do with Gradient within body?????
-        //SPGradient *grad = SP_GRADIENT(reprobj);
-        //if (!doGradient(grad, id))
-        //    return false;
+    std::vector<Glib::ustring>::iterator i;
+    for (i = shapes.begin(); i != shapes.end(); i++) {
+        out("               %s(),\n", (*i).c_str());
     }
-
-    /**
-     * Descend into children
-     */
-    for (SPObject *child = obj->firstChild() ; child ; child = child->next)
-        {
-		if (!doBody(doc, child))
-		    return false;
-		}
-
-    return true;
 }
 
 
@@ -810,6 +949,19 @@
  */
 void JavaFXOutput::reset()
 {
+    std::map<Glib::ustring, SPGradientPtr>::iterator ig;
+    for (ig = gradients.begin(); ig != gradients.end(); ig++) {
+        ig->second = NULL;
+    }
+    gradients.clear();
+
+    std::map<Glib::ustring, SPFilterPtr>::iterator ie;
+    for (ie = effects.begin(); ie != effects.end(); ie++) {
+        ie->second = NULL;
+    }
+    effects.clear();
+    shapes.clear();
+
     nrNodes    = 0;
     nrShapes   = 0;
     idindex    = 0;
@@ -819,6 +971,86 @@
 }
 
 
+/**
+ *  Output the tree data to buffer
+ */
+bool JavaFXOutput::traverseTree(Inkscape::XML::Node *node)
+{
+    /**
+     * Check the type of node and process
+     */
+    Glib::ustring id;
+    SPObject *obj = NULL;
+    Glib::ustring nodeName = node->name();
+    char const *cid = node->attribute("id"); 
+
+    if (!cid)
+        goto recursion;
+
+    // Convert SVG id to "valid" JavaFX id
+    id  = sanatize(cid);
+    obj = SP_ACTIVE_DOCUMENT->getObjectByRepr(node);
+    if (!obj)
+        goto recursion;
+
+    if (SP_IS_RECT(obj)) {
+        SPRect *item = SP_RECT(obj);
+        if (!doRect(item, id))
+            return false;
+        shapes.push_back(id);
+    }
+    else if (SP_IS_CIRCLE(obj)) {
+        SPCircle *item = SP_CIRCLE(obj);
+        if (!doCircle(item, id))
+            return false;
+        shapes.push_back(id);
+    }
+    else if (SP_IS_ELLIPSE(obj)) {
+        SPEllipse *item = SP_ELLIPSE(obj);
+        if (!doEllipse(item, id))
+            return false;
+        shapes.push_back(id);
+    }
+    else if (SP_IS_IMAGE(obj)) {
+        SPImage *image = SP_IMAGE(obj);
+        if (!doImage(image, id))
+            return false;
+        shapes.push_back(id);
+    }
+    else if (SP_IS_TEXT(obj)) {
+        SPText *text = SP_TEXT(obj);
+        if (!doText(text, id))
+            return false;
+        shapes.push_back(id);
+    }
+    else if (SP_IS_GRADIENT(obj)) {
+        SPGradient *grad = SP_GRADIENT(obj);
+        gradients[id] = grad;
+    }
+    else if (SP_IS_FILTER(obj)) {
+        SPFilter *filter = SP_FILTER(obj);
+        effects[id] = filter;
+    }       
+    else if (SP_IS_ITEM(obj)) {
+        SPItem *item = SP_ITEM(obj);
+        if (!doCurve(item, id))
+            return false;
+        if (SP_IS_SHAPE(obj))
+	    shapes.push_back(id);
+    }
+
+recursion:
+	     
+    for (Inkscape::XML::Node *child = node->firstChild(); child; child = child->next())
+    {
+        if (!traverseTree(child))
+            return false;
+    }
+
+    return true;
+}
+
+
 
 /**
  * Saves the <paths> of an Inkscape SVG file as JavaFX spline definitions
@@ -833,32 +1065,27 @@
     if (pos > 0)
         name = name.substr(0, pos);
 
-
-    //###### SAVE IN JAVAFX FORMAT TO BUFFER
-    //# Lets do the curves first, to get the stats
-
-    if (!doTree(doc))
+    //g_message("native file:%s\n", uri);
+    documentUri = URI(uri);
+    if (!traverseTree(doc->rroot))
         return false;
+
     String curveBuf = outbuf;
     outbuf.clear();
 
-    if (!doHeader())
+    if (!doHeader(doc))
         return false;
 
     outbuf.append(curveBuf);
 
-#ifdef JAVAFX_SDK_1_0
-    out("   override function create(): Node {\n");
-#else
-    out("   public function create(): Node {\n");
-#endif
-    out("       Group {\n");
-    out("           content: [\n");
+    out("    override function create(): Node {\n");
+    out("        Group {\n");
+    out("            content: [\n");
     idindex    = 0;
 
-    doBody(doc, doc->root);
+    writeBody();
 
-    if (!doTail())
+    if (!doTail(doc))
         return false;
 
 
@@ -866,15 +1093,15 @@
     //###### WRITE TO FILE
     FILE *f = Inkscape::IO::fopen_utf8name(uri, "w");
     if (!f)
-        {
+    {
         err("Could open JavaFX file '%s' for writing", uri);
         return false;
-        }
+    }
 
     for (String::iterator iter = outbuf.begin() ; iter!=outbuf.end(); iter++)
-        {
+    {
         fputc(*iter, f);
-        }
+    }
         
     fclose(f);
     
@@ -948,7 +1175,6 @@
 
 
 
-
 
 }  // namespace Internal
 }  // namespace Extension
diff -Naur inkscape2/src/extension/internal/javafx-out.h inkscape/src/extension/internal/javafx-out.h
--- inkscape2/src/extension/internal/javafx-out.h	2009-02-12 10:39:35.000000000 +0100
+++ inkscape/src/extension/internal/javafx-out.h	2009-02-10 10:35:03.000000000 +0100
@@ -15,10 +15,26 @@
 #ifndef EXTENSION_INTERNAL_JAVAFX_OUT_H
 #define EXTENSION_INTERNAL_JAVAFX_OUT_H
 
+#include <dom/dom.h>
+#include <dom/io/stringstream.h>
+#include <dom/uri.h>
+
 #include <glib.h>
 #include "extension/implementation/implementation.h"
 #include <document.h>
 #include <sp-gradient.h>
+#include <sp-filter.h>
+#include <sp-gaussian-blur.h>
+#include <sp-rect.h>
+#include <sp-ellipse.h>
+#include <sp-image.h>
+#include <sp-text.h>
+
+#include <string>
+#include <map>
+
+#include <dom/util/ziptool.h>
+#include <dom/io/domstream.h>
 
 namespace Inkscape
 {
@@ -27,7 +43,10 @@
 namespace Internal
 {
 
+// Use the same structures as in odf.h
 
+typedef org::w3c::dom::URI URI;
+typedef org::w3c::dom::io::Writer Writer;
 
 /**
  * Output the current svg document in JavaFX format.
@@ -37,68 +56,70 @@
  */ 
 class JavaFXOutput : public Inkscape::Extension::Implementation::Implementation
 {
-
-
 public:
 
-    /**
-     * Our internal String definition
-     */
     typedef Glib::ustring String;
-
+    typedef SPGradient*   SPGradientPtr;
+    typedef SPFilter*     SPFilterPtr;
 
     /**
      * Check whether we can actually output using this module
      */
-	virtual bool check (Inkscape::Extension::Extension * module);
+    virtual bool check (Inkscape::Extension::Extension * module);
 
     /**
      * API call to perform the output to a file
      */
-	virtual void save (Inkscape::Extension::Output *mod,
-	           SPDocument *doc, const gchar *uri);
+    virtual void save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri);
 
     /**
      * Inkscape runtime startup call.
      */
-	static void init(void);
+    static void init(void);
 	
     /**
      * Reset variables to initial state
      */
-	void reset();
+    void reset();
 	
 private:
 
+    URI documentUri;
+
+    std::map<String, SPGradientPtr> gradients;     // Gradient table
+    std::map<String, SPFilterPtr>   effects;       // Filter effect's table
+    std::vector<String> shapes;                    // shapes consisting a scene
     //output class name
     String name;
-
     //For formatted output
-	String outbuf;   //main output buffer
-	String foutbuf;  //header function buffer
-
+    String outbuf;   //main output buffer
+    String foutbuf;  //header function buffer
 
-	/**
-	 * Format text to our output buffer
-	 */
-	void out(const char *fmt, ...) G_GNUC_PRINTF(2,3);
 
-	/**
-	 * Format text to our function output buffer
-	 */
-	void fout(const char *fmt, ...) G_GNUC_PRINTF(2,3);
+    /**
+     * Format text to our output buffer
+     */
+    void out(const char *fmt, ...) G_GNUC_PRINTF(2,3);
 
-	//Output the parts of the file
+    /**
+     * Format text to our function output buffer
+     */
+    void fout(const char *fmt, ...) G_GNUC_PRINTF(2,3);
 
     /**
      * Output the file header
      */
-	bool doHeader();
+    bool doHeader(SPDocument *doc);
 
     /**
      *  Output gradient information to the buffer
      */
-    bool doGradient(SPGradient *grad, const String &id);
+    bool processGradient(SPGradient *grad);
+
+    /**
+     *  Output filter information to the buffer
+     */
+    bool processFilter(SPFilter *filter);
 
     /**
      *  Output an element's style attribute
@@ -108,23 +129,29 @@
     /**
      * Output the SVG document's curve data as JavaFX geometry types
      */
-    bool doCurve(SPItem *item, const String &id);
-    bool doTreeRecursive(SPDocument *doc, SPObject *obj);
-    bool doTree(SPDocument *doc);
+    bool doRect(SPRect *item,       const String &id);
+    bool doCircle(SPCircle *item,   const String &id);
+    bool doEllipse(SPEllipse *item, const String &id);
+    bool doCurve(SPItem *item,      const String &id);
+    bool doImage(SPImage *image,    const String &id);
+    bool doText(SPText *text,       const String &id);
+
+    bool processEffect(SPObject *obj);
+    bool traverseTree(Inkscape::XML::Node *node);
 
-    bool doBody(SPDocument *doc, SPObject *obj);
+    void writeBody();
 
     /**
      * Output the file footer
      */
-	bool doTail();
+    bool doTail(SPDocument *doc);
 
 
 
     /**
      * Actual method to save document
      */
-	bool saveDocument(SPDocument *doc, const gchar *uri);
+    bool saveDocument(SPDocument *doc, const gchar *uri);
 
     //For statistics
     int nrNodes;
@@ -136,13 +163,10 @@
     double miny;
     double maxx;
     double maxy;
-    
-
 };
 
 
 
-
 }  // namespace Internal
 }  // namespace Extension
 }  // namespace Inkscape
diff -Naur inkscape2/src/extension/internal/Makefile_insert inkscape/src/extension/internal/Makefile_insert
--- inkscape2/src/extension/internal/Makefile_insert	2009-02-12 10:39:35.000000000 +0100
+++ inkscape/src/extension/internal/Makefile_insert	2009-02-10 10:35:03.000000000 +0100
@@ -110,6 +110,8 @@
 	extension/internal/cairo-renderer-pdf-out.cpp	\
 	extension/internal/cairo-png-out.h \
 	extension/internal/cairo-png-out.cpp \
+	extension/internal/javafx-fxz.cpp	\
+	extension/internal/javafx-fxz.h	\
 	extension/internal/javafx-out.cpp	\
 	extension/internal/javafx-out.h	\
 	extension/internal/gdkpixbuf-input.h	\
