Code

initial impl of gradients and opacities
authorishmal <ishmal@users.sourceforge.net>
Sat, 2 Aug 2008 16:40:24 +0000 (16:40 +0000)
committerishmal <ishmal@users.sourceforge.net>
Sat, 2 Aug 2008 16:40:24 +0000 (16:40 +0000)
src/extension/internal/javafx-out.cpp
src/extension/internal/javafx-out.h

index c013987612242a91a9b23e453ddc86a3e5800c21..d25ec096cc98b2c47340d7edc14958f26852303c 100644 (file)
@@ -20,6 +20,8 @@
 #include <inkscape.h>\r
 #include <inkscape_version.h>\r
 #include <sp-path.h>\r
+#include <sp-linear-gradient.h>\r
+#include <sp-radial-gradient.h>\r
 #include <style.h>\r
 #include <display/curve.h>\r
 #include <libnr/n-art-bpath.h>\r
@@ -31,6 +33,7 @@
 #include "helper/geom.h"\r
 #include <io/sys.h>\r
 \r
+\r
 #include <string>\r
 #include <stdio.h>\r
 #include <stdarg.h>\r
@@ -46,6 +49,44 @@ namespace Internal
 \r
 \r
 \r
+//########################################################################\r
+//# M E S S A G E S\r
+//########################################################################\r
+\r
+static void err(const char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    g_logv(NULL, G_LOG_LEVEL_WARNING, fmt, args);\r
+    va_end(args);\r
+}\r
+\r
+\r
+//########################################################################\r
+//# U T I L I T Y\r
+//########################################################################\r
+\r
+/**\r
+ * Got this method from Bulia, and modified it a bit.  It basically\r
+ * starts with this style, gets its SPObject parent, walks up the object\r
+ * tree and finds all of the opacities and multiplies them.\r
+ *\r
+ * We use this for our "flat" object output.  If the code is modified\r
+ * to reflect a tree of <groups>, then this will be unneccessary.\r
+ */\r
+static double effective_opacity(const SPStyle *style)\r
+{\r
+    double val = 1.0;\r
+    for (SPObject const *obj = style->object; obj ; obj = obj->parent)\r
+        {\r
+        style = SP_OBJECT_STYLE(obj);\r
+        if (!style)\r
+            return val;\r
+        val *= SP_SCALE24_TO_FLOAT(style->opacity.value);\r
+        }\r
+    return val;\r
+}\r
+\r
 //########################################################################\r
 //# OUTPUT FORMATTING\r
 //########################################################################\r
@@ -65,6 +106,33 @@ static JavaFXOutput::String dstr(double d)
 \r
 \r
 \r
+/**\r
+ * Format an rgba() string\r
+ */\r
+static JavaFXOutput::String rgba(guint32 rgba)\r
+{\r
+    unsigned int r = SP_RGBA32_R_U(rgba);\r
+    unsigned int g = SP_RGBA32_G_U(rgba);\r
+    unsigned int b = SP_RGBA32_B_U(rgba);\r
+    unsigned int a = SP_RGBA32_A_U(rgba);\r
+    char buf[80];\r
+    snprintf(buf, 79, "rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)",\r
+                           r, g, b, a);\r
+    JavaFXOutput::String s = buf;\r
+    return s;\r
+}\r
+\r
+\r
+/**\r
+ * Format an rgba() string for a color and a 0.0-1.0 alpha\r
+ */\r
+static JavaFXOutput::String rgba(SPColor color, gdouble alpha)\r
+{\r
+    return rgba(color.toRGBA32(alpha));\r
+}\r
+\r
+\r
+\r
 \r
 /**\r
  *  Output data to the buffer, printf()-style\r
@@ -79,11 +147,24 @@ void JavaFXOutput::out(const char *fmt, ...)
     g_free(output);\r
 }\r
 \r
+/**\r
+ *  Output header data to the buffer, printf()-style\r
+ */\r
+void JavaFXOutput::fout(const char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    gchar *output = g_strdup_vprintf(fmt, args);\r
+    va_end(args);\r
+    foutbuf.append(output);\r
+    g_free(output);\r
+}\r
+\r
 \r
 /**\r
  * Output the file header\r
  */\r
-bool JavaFXOutput::doHeader(const String &name)\r
+bool JavaFXOutput::doHeader()\r
 {\r
     time_t tim = time(NULL);\r
     out("/*###################################################################\n");\r
@@ -118,8 +199,20 @@ bool JavaFXOutput::doHeader(const String &name)
     out("import java.lang.System;\n");\r
     out("\n\n");\r
     out("public class %s extends CompositeNode {\n", name.c_str());\r
+    for (unsigned int i = 0 ; i < linearGradients.size() ; i++)\r
+        {\r
+        out("    public function %s(): LinearGradient;\n",\r
+            linearGradients[i].c_str());\r
+        }\r
+    for (unsigned int i = 0 ; i < radialGradients.size() ; i++)\r
+        {\r
+        out("    public function %s(): RadialGradient;\n",\r
+            radialGradients[i].c_str());\r
+        }\r
     out("}\n");\r
     out("\n\n");\r
+    outbuf.append(foutbuf);\r
+    out("\n\n");\r
     out("function %s.composeNode() =\n", name.c_str());\r
     out("Group\n");\r
     out("    {\n");\r
@@ -133,7 +226,7 @@ bool JavaFXOutput::doHeader(const String &name)
 /**\r
  *  Output the file footer\r
  */\r
-bool JavaFXOutput::doTail(const String &name)\r
+bool JavaFXOutput::doTail()\r
 {\r
     int border = 25.0;\r
     out("        ] // content\n");\r
@@ -163,6 +256,151 @@ bool JavaFXOutput::doTail(const String &name)
 }\r
 \r
 \r
+\r
+/**\r
+ *  Output gradient information to the buffer\r
+ */\r
+bool JavaFXOutput::doGradient(SPGradient *grad, const String &id)\r
+{\r
+    if (SP_IS_LINEARGRADIENT(grad))\r
+        {\r
+        SPLinearGradient *g = SP_LINEARGRADIENT(grad);\r
+        linearGradients.push_back(id);\r
+        fout("function %s.%s() =\n", name.c_str(), id.c_str());\r
+        fout("    [\n");\r
+        fout("    LinearGradient\n");\r
+        fout("        {\n");\r
+        std::vector<SPGradientStop> stops = g->vector.stops;\r
+        if (stops.size() > 0)\r
+            {\r
+            fout("        stops:\n");\r
+            fout("            [\n");\r
+            for (unsigned int i = 0 ; i<stops.size() ; i++)\r
+                {\r
+                SPGradientStop stop = stops[i];\r
+                fout("            Stop\n");\r
+                fout("                {\n");\r
+                fout("                offset: %s\n", dstr(stop.offset).c_str());\r
+                fout("                color: %s\n", rgba(stop.color, stop.opacity).c_str());\r
+                fout("                },\n");\r
+                }\r
+            fout("            ]\n");\r
+            }\r
+        fout("        },\n");\r
+        fout("    ];\n");\r
+        fout("\n\n");\r
+        }\r
+    else if (SP_IS_RADIALGRADIENT(grad))\r
+        {\r
+        SPRadialGradient *g = SP_RADIALGRADIENT(grad);\r
+        radialGradients.push_back(id);\r
+        fout("function %s.%s() =\n", name.c_str(), id.c_str());\r
+        fout("    [\n");\r
+        fout("    RadialGradient\n");\r
+        fout("        {\n");\r
+        fout("        cx: %s\n", dstr(g->cx.value).c_str());\r
+        fout("        cy: %s\n", dstr(g->cy.value).c_str());\r
+        fout("        focusX: %s\n", dstr(g->fx.value).c_str());\r
+        fout("        focusY: %s\n", dstr(g->fy.value).c_str());\r
+        fout("        radius: %s\n", dstr(g->r.value).c_str());\r
+        fout("        gradientUnits: OBJECT_BOUNDING_BOX\n");\r
+        fout("        spreadMethod: PAD\n");\r
+        std::vector<SPGradientStop> stops = g->vector.stops;\r
+        if (stops.size() > 0)\r
+            {\r
+            fout("        stops:\n");\r
+            fout("            [\n");\r
+            for (unsigned int i = 0 ; i<stops.size() ; i++)\r
+                {\r
+                SPGradientStop stop = stops[i];\r
+                fout("            Stop\n");\r
+                fout("                {\n");\r
+                fout("                offset: %s\n", dstr(stop.offset).c_str());\r
+                fout("                color: %s\n", rgba(stop.color, stop.opacity).c_str());\r
+                fout("                },\n");\r
+                }\r
+            fout("            ]\n");\r
+            }\r
+        fout("        },\n");\r
+        fout("    ];\n");\r
+        fout("\n\n");\r
+        }\r
+    else\r
+        {\r
+        err("Unknown gradient type for '%s'\n", id.c_str());\r
+        return false;\r
+        }\r
+\r
+\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ *  Output an element's style attribute\r
+ */\r
+bool JavaFXOutput::doStyle(SPStyle *style)\r
+{\r
+    if (!style)\r
+        return true;\r
+\r
+    out("        opacity: %s\n", dstr(effective_opacity(style)).c_str());\r
+\r
+    /**\r
+     * Fill\r
+     */\r
+    SPIPaint fill = style->fill;\r
+    if (fill.isColor())\r
+        {\r
+        // see color.h for how to parse SPColor\r
+        out("        fill: %s\n",\r
+            rgba(fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value)).c_str());\r
+        }\r
+    else if (fill.isPaintserver())\r
+        {\r
+        if (fill.value.href && fill.value.href->getURI() )\r
+            {\r
+            String uri = fill.value.href->getURI()->toString();\r
+            if (uri.size()>0 && uri[0]=='#')\r
+                uri = uri.substr(1);\r
+            out("        fill: %s()\n", uri.c_str());\r
+            }\r
+        }\r
+\r
+\r
+    /**\r
+     * Stroke\r
+     */\r
+    /**\r
+     *NOTE:  Things in style we can use:\r
+     * SPIPaint stroke;\r
+     * SPILength stroke_width;\r
+     * SPIEnum stroke_linecap;\r
+     * SPIEnum stroke_linejoin;\r
+     * SPIFloat stroke_miterlimit;\r
+     * NRVpathDash stroke_dash;\r
+     * unsigned stroke_dasharray_set : 1;\r
+     * unsigned stroke_dasharray_inherit : 1;\r
+     * unsigned stroke_dashoffset_set : 1;\r
+     * SPIScale24 stroke_opacity;\r
+     */\r
+    if (style->stroke_opacity.value > 0)\r
+        {\r
+        SPIPaint stroke = style->stroke;\r
+        out("        stroke: %s\n",\r
+            rgba(stroke.value.color, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)).c_str());\r
+        double strokewidth = style->stroke_width.value;\r
+        out("        strokeWidth: %s\n", dstr(strokewidth).c_str());\r
+        }\r
+\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
 /**\r
  *  Output the curve data to buffer\r
  */\r
@@ -190,57 +428,10 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id)
     out("        id: \"%s\"\n", id.c_str());\r
 \r
     /**\r
-     * Get the fill and stroke of the shape\r
+     * Output the style information\r
      */\r
-    SPStyle *style = SP_OBJECT_STYLE(shape);\r
-    if (style)\r
-        {\r
-        /**\r
-         * Fill\r
-         */\r
-        if (style->fill.isColor())\r
-            {\r
-            // see color.h for how to parse SPColor\r
-            gint alpha = 0xffffffff;\r
-            guint32 rgba = style->fill.value.color.toRGBA32(alpha);\r
-            unsigned int r = SP_RGBA32_R_U(rgba);\r
-            unsigned int g = SP_RGBA32_G_U(rgba);\r
-            unsigned int b = SP_RGBA32_B_U(rgba);\r
-            unsigned int a = SP_RGBA32_A_U(rgba);\r
-            out("        fill: rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",\r
-                               r, g, b, a);\r
-            }\r
-        /**\r
-         * Stroke\r
-         */\r
-        /**\r
-         *NOTE:  Things in style we can use:\r
-            * SPIPaint stroke;\r
-            * SPILength stroke_width;\r
-            * SPIEnum stroke_linecap;\r
-            * SPIEnum stroke_linejoin;\r
-            * SPIFloat stroke_miterlimit;\r
-            * NRVpathDash stroke_dash;\r
-            * unsigned stroke_dasharray_set : 1;\r
-            * unsigned stroke_dasharray_inherit : 1;\r
-            * unsigned stroke_dashoffset_set : 1;\r
-            * SPIScale24 stroke_opacity;\r
-         */\r
-        if (style->stroke_opacity.value > 0)\r
-            {\r
-            gint alpha = 0xffffffff;\r
-            guint32 rgba = style->stroke.value.color.toRGBA32(alpha);\r
-            unsigned int r = SP_RGBA32_R_U(rgba);\r
-            unsigned int g = SP_RGBA32_G_U(rgba);\r
-            unsigned int b = SP_RGBA32_B_U(rgba);\r
-            unsigned int a = SP_RGBA32_A_U(rgba);\r
-            out("        stroke: rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",\r
-                               r, g, b, a);\r
-            double strokewidth = style->stroke_width.value;\r
-            out("        strokeWidth: %s\n", dstr(strokewidth).c_str());\r
-            }\r
-        }\r
-\r
+    if (!doStyle(SP_OBJECT_STYLE(shape)))\r
+        return false;\r
 \r
     // convert the path to only lineto's and cubic curveto's:\r
     Geom::Scale yflip(1.0, -1.0);\r
@@ -358,17 +549,33 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id)
 bool JavaFXOutput::doCurvesRecursive(SPDocument *doc, Inkscape::XML::Node *node)\r
 {\r
     /**\r
-     * If the object is an Item, try processing it\r
-     */             \r
-    char *str  = (char *) node->attribute("id");\r
+     * Check the type of node and process\r
+     */\r
+    String id;\r
+    char *idstr = (char *) node->attribute("id");\r
+    if (!idstr)\r
+        {\r
+        char buf[16];\r
+        sprintf(buf, "id%d", idindex++);\r
+        id = buf;\r
+        }\r
+    else\r
+        {\r
+        id = idstr;\r
+        }\r
     SPObject *reprobj = doc->getObjectByRepr(node);\r
-    if (SP_IS_ITEM(reprobj) && str)\r
+    if (SP_IS_ITEM(reprobj))\r
         {\r
         SPItem *item = SP_ITEM(reprobj);\r
-        String id = str;\r
         if (!doCurve(item, id))\r
             return false;\r
         }\r
+    else if (SP_IS_GRADIENT(reprobj))\r
+        {\r
+        SPGradient *grad = SP_GRADIENT(reprobj);\r
+        if (!doGradient(grad, id))\r
+            return false;\r
+        }\r
 \r
     /**\r
      * Descend into children\r
@@ -420,7 +627,12 @@ void JavaFXOutput::reset()
     nrNodes    = 0;\r
     nrSegments = 0;\r
     nrShapes   = 0;\r
+    idindex    = 0;\r
+    name.clear();\r
     outbuf.clear();\r
+    foutbuf.clear();\r
+    linearGradients.clear();\r
+    radialGradients.clear();\r
 }\r
 \r
 \r
@@ -433,7 +645,7 @@ bool JavaFXOutput::saveDocument(SPDocument *doc, gchar const *uri)
     reset();\r
 \r
 \r
-    String name = Glib::path_get_basename(uri);\r
+    name = Glib::path_get_basename(uri);\r
     int pos = name.find('.');\r
     if (pos > 0)\r
         name = name.substr(0, pos);\r
@@ -447,12 +659,12 @@ bool JavaFXOutput::saveDocument(SPDocument *doc, gchar const *uri)
     String curveBuf = outbuf;\r
     outbuf.clear();\r
 \r
-    if (!doHeader(name))\r
+    if (!doHeader())\r
         return false;\r
     \r
     outbuf.append(curveBuf);\r
-    \r
-    if (!doTail(name))\r
+\r
+    if (!doTail())\r
         return false;\r
 \r
 \r
@@ -462,7 +674,7 @@ bool JavaFXOutput::saveDocument(SPDocument *doc, gchar const *uri)
     FILE *f = Inkscape::IO::fopen_utf8name(uri, "w");\r
     if (!f)\r
         {\r
-        g_warning("Could open JavaFX file '%s' for writing", uri);\r
+        err("Could open JavaFX file '%s' for writing", uri);\r
         return false;\r
         }\r
 \r
index 27a742861cbc067d11959df2f780666e45e2a99a..917cc529a3ed069343ae70c149bb4b6c0df383dc 100644 (file)
@@ -1,10 +1,7 @@
 /*\r
- * A simple utility for exporting Inkscape svg Shapes as PovRay bezier\r
- * prisms.  Note that this is output-only, and would thus seem to be\r
- * better placed as an 'export' rather than 'output'.  However, Export\r
- * handles all or partial documents, while this outputs ALL shapes in\r
- * the current SVG document.\r
- *\r
+ * A simple utility for exporting an Inkscape svg image as a JavaFX\r
+ * scene tree.\r
+\ *\r
  * Authors:\r
  *   Bob Jamison <ishmal@inkscape.org>\r
  *\r
@@ -18,6 +15,8 @@
 \r
 #include <glib.h>\r
 #include "extension/implementation/implementation.h"\r
+#include <document.h>\r
+#include <sp-gradient.h>\r
 \r
 namespace Inkscape\r
 {\r
@@ -69,22 +68,40 @@ public:
        \r
 private:\r
 \r
-    \r
+    //output class name\r
+    String name;\r
+\r
     //For formatted output\r
-       String outbuf;\r
-       \r
+       String outbuf;   //main output buffer\r
+       String foutbuf;  //header function buffer\r
+\r
 \r
        /**\r
         * Format text to our output buffer\r
         */\r
        void out(const char *fmt, ...) G_GNUC_PRINTF(2,3);\r
 \r
+       /**\r
+        * Format text to our function output buffer\r
+        */\r
+       void fout(const char *fmt, ...) G_GNUC_PRINTF(2,3);\r
+\r
        //Output the parts of the file\r
 \r
     /**\r
      * Output the file header\r
      */\r
-       bool doHeader(const String &name);\r
+       bool doHeader();\r
+\r
+    /**\r
+     *  Output gradient information to the buffer\r
+     */\r
+    bool doGradient(SPGradient *grad, const String &id);\r
+\r
+    /**\r
+     *  Output an element's style attribute\r
+     */\r
+    bool doStyle(SPStyle *style);\r
 \r
     /**\r
      * Output the SVG document's curve data as POV curves\r
@@ -96,7 +113,7 @@ private:
     /**\r
      * Output the file footer\r
      */\r
-       bool doTail(const String &name);\r
+       bool doTail();\r
 \r
 \r
 \r
@@ -109,11 +126,16 @@ private:
     int nrNodes;\r
     int nrSegments;\r
     int nrShapes;\r
+    \r
+    int idindex;\r
 \r
     double minx;\r
     double miny;\r
     double maxx;\r
     double maxy;\r
+    \r
+    std::vector<String> linearGradients;\r
+    std::vector<String> radialGradients;\r
 \r
 };\r
 \r