Code

2e0f2d59fa528d4556615528a182c1e9b38ad7b4
[inkscape.git] / src / extension / internal / javafx-out.cpp
1 /*\r
2  * A simple utility for exporting Inkscape svg Shapes as JavaFX paths.\r
3  *\r
4  *  For information on the JavaFX file format, see:\r
5  *      https://openjfx.dev.java.net/\r
6  *\r
7  * Authors:\r
8  *   Bob Jamison <ishmal@inkscape.org>\r
9  *\r
10  * Copyright (C) 2008 Authors\r
11  *\r
12  * Released under GNU GPL, read the file 'COPYING' for more information\r
13  */\r
14 \r
15 \r
16 #ifdef HAVE_CONFIG_H\r
17 # include <config.h>\r
18 #endif\r
19 #include "javafx-out.h"\r
20 #include <inkscape.h>\r
21 #include <inkscape_version.h>\r
22 #include <sp-path.h>\r
23 #include <sp-linear-gradient.h>\r
24 #include <sp-radial-gradient.h>\r
25 #include <style.h>\r
26 #include <display/curve.h>\r
27 #include <extension/system.h>\r
28 #include <2geom/pathvector.h>\r
29 #include <2geom/rect.h>\r
30 #include <2geom/bezier-curve.h>\r
31 #include <2geom/hvlinesegment.h>\r
32 #include "helper/geom.h"\r
33 #include <io/sys.h>\r
34 \r
35 \r
36 #include <string>\r
37 #include <stdio.h>\r
38 #include <stdarg.h>\r
39 \r
40 \r
41 namespace Inkscape\r
42 {\r
43 namespace Extension\r
44 {\r
45 namespace Internal\r
46 {\r
47 \r
48 \r
49 \r
50 \r
51 //########################################################################\r
52 //# M E S S A G E S\r
53 //########################################################################\r
54 \r
55 static void err(const char *fmt, ...)\r
56 {\r
57     va_list args;\r
58     va_start(args, fmt);\r
59     g_logv(NULL, G_LOG_LEVEL_WARNING, fmt, args);\r
60     va_end(args);\r
61 }\r
62 \r
63 \r
64 //########################################################################\r
65 //# U T I L I T Y\r
66 //########################################################################\r
67 \r
68 /**\r
69  * Got this method from Bulia, and modified it a bit.  It basically\r
70  * starts with this style, gets its SPObject parent, walks up the object\r
71  * tree and finds all of the opacities and multiplies them.\r
72  *\r
73  * We use this for our "flat" object output.  If the code is modified\r
74  * to reflect a tree of <groups>, then this will be unneccessary.\r
75  */\r
76 static double effective_opacity(const SPStyle *style)\r
77 {\r
78     double val = 1.0;\r
79     for (SPObject const *obj = style->object; obj ; obj = obj->parent)\r
80         {\r
81         style = SP_OBJECT_STYLE(obj);\r
82         if (!style)\r
83             return val;\r
84         val *= SP_SCALE24_TO_FLOAT(style->opacity.value);\r
85         }\r
86     return val;\r
87 }\r
88 \r
89 //########################################################################\r
90 //# OUTPUT FORMATTING\r
91 //########################################################################\r
92 \r
93 \r
94 /**\r
95  * We want to control floating output format\r
96  */\r
97 static JavaFXOutput::String dstr(double d)\r
98 {\r
99     char dbuf[G_ASCII_DTOSTR_BUF_SIZE+1];\r
100     g_ascii_formatd(dbuf, G_ASCII_DTOSTR_BUF_SIZE,\r
101                   "%.8f", (gdouble)d);\r
102     JavaFXOutput::String s = dbuf;\r
103     return s;\r
104 }\r
105 \r
106 \r
107 \r
108 /**\r
109  * Format an rgba() string\r
110  */\r
111 static JavaFXOutput::String rgba(guint32 rgba)\r
112 {\r
113     unsigned int r = SP_RGBA32_R_U(rgba);\r
114     unsigned int g = SP_RGBA32_G_U(rgba);\r
115     unsigned int b = SP_RGBA32_B_U(rgba);\r
116     unsigned int a = SP_RGBA32_A_U(rgba);\r
117     char buf[80];\r
118     snprintf(buf, 79, "rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)",\r
119                            r, g, b, a);\r
120     JavaFXOutput::String s = buf;\r
121     return s;\r
122 }\r
123 \r
124 \r
125 /**\r
126  * Format an rgba() string for a color and a 0.0-1.0 alpha\r
127  */\r
128 static JavaFXOutput::String rgba(SPColor color, gdouble alpha)\r
129 {\r
130     return rgba(color.toRGBA32(alpha));\r
131 }\r
132 \r
133 \r
134 \r
135 \r
136 /**\r
137  *  Output data to the buffer, printf()-style\r
138  */\r
139 void JavaFXOutput::out(const char *fmt, ...)\r
140 {\r
141     va_list args;\r
142     va_start(args, fmt);\r
143     gchar *output = g_strdup_vprintf(fmt, args);\r
144     va_end(args);\r
145     outbuf.append(output);\r
146     g_free(output);\r
147 }\r
148 \r
149 /**\r
150  *  Output header data to the buffer, printf()-style\r
151  */\r
152 void JavaFXOutput::fout(const char *fmt, ...)\r
153 {\r
154     va_list args;\r
155     va_start(args, fmt);\r
156     gchar *output = g_strdup_vprintf(fmt, args);\r
157     va_end(args);\r
158     foutbuf.append(output);\r
159     g_free(output);\r
160 }\r
161 \r
162 \r
163 /**\r
164  * Output the file header\r
165  */\r
166 bool JavaFXOutput::doHeader()\r
167 {\r
168     time_t tim = time(NULL);\r
169     out("/*###################################################################\n");\r
170     out("### This JavaFX document was generated by Inkscape\n");\r
171     out("### http://www.inkscape.org\n");\r
172     out("### Created: %s", ctime(&tim));\r
173     out("### Version: %s\n", INKSCAPE_VERSION);\r
174     out("#####################################################################\n");\r
175     out("### NOTES:\n");\r
176     out("### ============\n");\r
177     out("### JavaFX information can be found at\n");\r
178     out("### hhttps://openjfx.dev.java.net\n");\r
179     out("###\n");\r
180     out("### If you have any problems with this output, please see the\n");\r
181     out("### Inkscape project at http://www.inkscape.org, or visit\n");\r
182     out("### the #inkscape channel on irc.freenode.net . \n");\r
183     out("###\n");\r
184     out("###################################################################*/\n");\r
185     out("\n\n");\r
186     out("/*###################################################################\n");\r
187     out("##   Exports in this file\n");\r
188     out("##==========================\n");\r
189     out("##    Shapes   : %d\n", nrShapes);\r
190     out("##    Segments : %d\n", nrSegments);\r
191     out("##    Nodes    : %d\n", nrNodes);\r
192     out("###################################################################*/\n");\r
193     out("\n\n");\r
194     out("import javafx.ui.UIElement;\n");\r
195     out("import javafx.ui.*;\n");\r
196     out("import javafx.ui.canvas.*;\n");\r
197     out("\n");\r
198     out("import java.lang.System;\n");\r
199     out("\n\n");\r
200     out("public class %s extends CompositeNode {\n", name.c_str());\r
201     for (unsigned int i = 0 ; i < linearGradients.size() ; i++)\r
202         {\r
203         out("    public function %s(): LinearGradient;\n",\r
204             linearGradients[i].c_str());\r
205         }\r
206     for (unsigned int i = 0 ; i < radialGradients.size() ; i++)\r
207         {\r
208         out("    public function %s(): RadialGradient;\n",\r
209             radialGradients[i].c_str());\r
210         }\r
211     out("}\n");\r
212     out("\n\n");\r
213     outbuf.append(foutbuf);\r
214     out("\n\n");\r
215     out("function %s.composeNode() =\n", name.c_str());\r
216     out("Group\n");\r
217     out("    {\n");\r
218     out("    content:\n");\r
219     out("        [\n");\r
220     return true;\r
221 }\r
222 \r
223 \r
224 \r
225 /**\r
226  *  Output the file footer\r
227  */\r
228 bool JavaFXOutput::doTail()\r
229 {\r
230     int border = 25.0;\r
231     out("        ] // content\n");\r
232     out("    transform: [ translate(%s, %s), ]\n",\r
233                   dstr((-minx) + border).c_str(), dstr((-miny) + border).c_str());\r
234     out("    }; // Group\n");\r
235     out("// end function %s.composeNode()\n", name.c_str());\r
236     out("\n\n\n\n");\r
237     out("Frame {\n");\r
238     out("    title: \"Test\"\n");\r
239     out("    width: %s\n", dstr(maxx-minx + border * 2.0).c_str());\r
240     out("    height: %s\n", dstr(maxy-miny + border * 2.0).c_str());\r
241     out("    onClose: function()\n");\r
242     out("        {\n");\r
243     out("        return System.exit( 0 );\n");\r
244     out("        }\n");\r
245     out("    visible: true\n");\r
246     out("    content: Canvas {\n");\r
247     out("        content: %s{}\n", name.c_str());\r
248     out("    }\n");\r
249     out("}\n");\r
250     out("/*###################################################################\n");\r
251     out("### E N D   C L A S S    %s\n", name.c_str());\r
252     out("###################################################################*/\n");\r
253     out("\n\n");\r
254     return true;\r
255 }\r
256 \r
257 \r
258 \r
259 /**\r
260  *  Output gradient information to the buffer\r
261  */\r
262 bool JavaFXOutput::doGradient(SPGradient *grad, const String &id)\r
263 {\r
264     if (SP_IS_LINEARGRADIENT(grad))\r
265         {\r
266         SPLinearGradient *g = SP_LINEARGRADIENT(grad);\r
267         linearGradients.push_back(id);\r
268         fout("function %s.%s() =\n", name.c_str(), id.c_str());\r
269         fout("    [\n");\r
270         fout("    LinearGradient\n");\r
271         fout("        {\n");\r
272         std::vector<SPGradientStop> stops = g->vector.stops;\r
273         if (stops.size() > 0)\r
274             {\r
275             fout("        stops:\n");\r
276             fout("            [\n");\r
277             for (unsigned int i = 0 ; i<stops.size() ; i++)\r
278                 {\r
279                 SPGradientStop stop = stops[i];\r
280                 fout("            Stop\n");\r
281                 fout("                {\n");\r
282                 fout("                offset: %s\n", dstr(stop.offset).c_str());\r
283                 fout("                color: %s\n", rgba(stop.color, stop.opacity).c_str());\r
284                 fout("                },\n");\r
285                 }\r
286             fout("            ]\n");\r
287             }\r
288         fout("        },\n");\r
289         fout("    ];\n");\r
290         fout("\n\n");\r
291         }\r
292     else if (SP_IS_RADIALGRADIENT(grad))\r
293         {\r
294         SPRadialGradient *g = SP_RADIALGRADIENT(grad);\r
295         radialGradients.push_back(id);\r
296         fout("function %s.%s() =\n", name.c_str(), id.c_str());\r
297         fout("    [\n");\r
298         fout("    RadialGradient\n");\r
299         fout("        {\n");\r
300         fout("        cx: %s\n", dstr(g->cx.value).c_str());\r
301         fout("        cy: %s\n", dstr(g->cy.value).c_str());\r
302         fout("        focusX: %s\n", dstr(g->fx.value).c_str());\r
303         fout("        focusY: %s\n", dstr(g->fy.value).c_str());\r
304         fout("        radius: %s\n", dstr(g->r.value).c_str());\r
305         fout("        gradientUnits: OBJECT_BOUNDING_BOX\n");\r
306         fout("        spreadMethod: PAD\n");\r
307         std::vector<SPGradientStop> stops = g->vector.stops;\r
308         if (stops.size() > 0)\r
309             {\r
310             fout("        stops:\n");\r
311             fout("            [\n");\r
312             for (unsigned int i = 0 ; i<stops.size() ; i++)\r
313                 {\r
314                 SPGradientStop stop = stops[i];\r
315                 fout("            Stop\n");\r
316                 fout("                {\n");\r
317                 fout("                offset: %s\n", dstr(stop.offset).c_str());\r
318                 fout("                color: %s\n", rgba(stop.color, stop.opacity).c_str());\r
319                 fout("                },\n");\r
320                 }\r
321             fout("            ]\n");\r
322             }\r
323         fout("        },\n");\r
324         fout("    ];\n");\r
325         fout("\n\n");\r
326         }\r
327     else\r
328         {\r
329         err("Unknown gradient type for '%s'\n", id.c_str());\r
330         return false;\r
331         }\r
332 \r
333 \r
334     return true;\r
335 }\r
336 \r
337 \r
338 \r
339 \r
340 /**\r
341  *  Output an element's style attribute\r
342  */\r
343 bool JavaFXOutput::doStyle(SPStyle *style)\r
344 {\r
345     if (!style)\r
346         return true;\r
347 \r
348     out("        opacity: %s\n", dstr(effective_opacity(style)).c_str());\r
349 \r
350     /**\r
351      * Fill\r
352      */\r
353     SPIPaint fill = style->fill;\r
354     if (fill.isColor())\r
355         {\r
356         // see color.h for how to parse SPColor\r
357         out("        fill: %s\n",\r
358             rgba(fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value)).c_str());\r
359         }\r
360     else if (fill.isPaintserver())\r
361         {\r
362         if (fill.value.href && fill.value.href->getURI() )\r
363             {\r
364             String uri = fill.value.href->getURI()->toString();\r
365             if (uri.size()>0 && uri[0]=='#')\r
366                 uri = uri.substr(1);\r
367             out("        fill: %s()\n", uri.c_str());\r
368             }\r
369         }\r
370 \r
371 \r
372     /**\r
373      * Stroke\r
374      */\r
375     /**\r
376      *NOTE:  Things in style we can use:\r
377      * SPIPaint stroke;\r
378      * SPILength stroke_width;\r
379      * SPIEnum stroke_linecap;\r
380      * SPIEnum stroke_linejoin;\r
381      * SPIFloat stroke_miterlimit;\r
382      * NRVpathDash stroke_dash;\r
383      * unsigned stroke_dasharray_set : 1;\r
384      * unsigned stroke_dasharray_inherit : 1;\r
385      * unsigned stroke_dashoffset_set : 1;\r
386      * SPIScale24 stroke_opacity;\r
387      */\r
388     if (style->stroke_opacity.value > 0)\r
389         {\r
390         SPIPaint stroke = style->stroke;\r
391         out("        stroke: %s\n",\r
392             rgba(stroke.value.color, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)).c_str());\r
393         double strokewidth = style->stroke_width.value;\r
394         out("        strokeWidth: %s\n", dstr(strokewidth).c_str());\r
395         }\r
396 \r
397     return true;\r
398 }\r
399 \r
400 \r
401 \r
402 \r
403 /**\r
404  *  Output the curve data to buffer\r
405  */\r
406 bool JavaFXOutput::doCurve(SPItem *item, const String &id)\r
407 {\r
408     using Geom::X;\r
409     using Geom::Y;\r
410 \r
411     //### Get the Shape\r
412     if (!SP_IS_SHAPE(item))//Bulia's suggestion.  Allow all shapes\r
413         return true;\r
414 \r
415     SPShape *shape = SP_SHAPE(item);\r
416     SPCurve *curve = shape->curve;\r
417     if (curve->is_empty())\r
418         return true;\r
419 \r
420     nrShapes++;\r
421 \r
422     out("        /*###################################################\n");\r
423     out("        ### PATH:  %s\n", id.c_str());\r
424     out("        ###################################################*/\n");\r
425     out("        Path \n");\r
426     out("        {\n");\r
427     out("        id: \"%s\"\n", id.c_str());\r
428 \r
429     /**\r
430      * Output the style information\r
431      */\r
432     if (!doStyle(SP_OBJECT_STYLE(shape)))\r
433         return false;\r
434 \r
435     // convert the path to only lineto's and cubic curveto's:\r
436     Geom::Scale yflip(1.0, -1.0);\r
437     Geom::Matrix tf = sp_item_i2d_affine(item) * yflip;\r
438     Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );\r
439 \r
440     //Count the NR_CURVETOs/LINETOs (including closing line segment)\r
441     guint segmentCount = 0;\r
442     for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) {\r
443         segmentCount += (*it).size();\r
444         if (it->closed())\r
445             segmentCount += 1;\r
446     }\r
447 \r
448     out("        d:\n");\r
449     out("            [\n");\r
450 \r
451     unsigned int segmentNr = 0;\r
452 \r
453     nrSegments += segmentCount;\r
454 \r
455     Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() ); \r
456 \r
457     /**\r
458      * For all Subpaths in the <path>\r
459      */      \r
460     for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit)\r
461         {\r
462         Geom::Point p = pit->front().initialPoint();\r
463         cminmax.expandTo(p);\r
464         out("            MoveTo {\n");\r
465         out("                x: %s\n", dstr(p[X]).c_str());\r
466         out("                y: %s\n", dstr(p[Y]).c_str());\r
467         out("                absolute: true\n");\r
468         out("                },\n");\r
469         \r
470         /**\r
471          * For all segments in the subpath\r
472          */                      \r
473         for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit)\r
474             {\r
475             //### LINE\r
476             if( dynamic_cast<Geom::LineSegment const *> (&*cit) ||\r
477                 dynamic_cast<Geom::HLineSegment const *>(&*cit) ||\r
478                 dynamic_cast<Geom::VLineSegment const *>(&*cit) )\r
479                 {\r
480                 Geom::Point p = cit->finalPoint();\r
481                 out("            LineTo {\n");\r
482                 out("                x: %s\n", dstr(p[X]).c_str());\r
483                 out("                y: %s\n", dstr(p[Y]).c_str());\r
484                 out("                absolute: true\n");\r
485                 out("                },\n");\r
486                 nrNodes++;\r
487                 }\r
488             //### BEZIER\r
489             else if(Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit))\r
490                 {\r
491                 std::vector<Geom::Point> points = cubic->points();\r
492                 Geom::Point p1 = points[1];\r
493                 Geom::Point p2 = points[2];\r
494                 Geom::Point p3 = points[3];\r
495                 out("            CurveTo {\n");\r
496                 out("                x1: %s\n", dstr(p1[X]).c_str());\r
497                 out("                y1: %s\n", dstr(p1[Y]).c_str());\r
498                 out("                x2: %s\n", dstr(p2[X]).c_str());\r
499                 out("                y2: %s\n", dstr(p2[Y]).c_str());\r
500                 out("                x3: %s\n", dstr(p3[X]).c_str());\r
501                 out("                y3: %s\n", dstr(p3[Y]).c_str());\r
502                 out("                absolute: true\n");\r
503                 out("                },\n");\r
504                 nrNodes++;\r
505                 }\r
506             else\r
507                 {\r
508                 g_error ("logical error, because pathv_to_linear_and_cubic_beziers was used");\r
509                 }\r
510             segmentNr++;\r
511             cminmax.expandTo(cit->finalPoint());\r
512             }\r
513         if (pit->closed())\r
514             {\r
515             out("            ClosePath {},\n");\r
516             }\r
517         }\r
518 \r
519     out("            ] // d\n");\r
520     out("        }, // Path\n");\r
521 \r
522                  \r
523     out("        /*###################################################\n");\r
524     out("        ### end path %s\n", id.c_str());\r
525     out("        ###################################################*/\n\n\n\n");\r
526 \r
527     double cminx = cminmax.min()[X];\r
528     double cmaxx = cminmax.max()[X];\r
529     double cminy = cminmax.min()[Y];\r
530     double cmaxy = cminmax.max()[Y];\r
531 \r
532     if (cminx < minx)\r
533         minx = cminx;\r
534     if (cmaxx > maxx)\r
535         maxx = cmaxx;\r
536     if (cminy < miny)\r
537         miny = cminy;\r
538     if (cmaxy > maxy)\r
539         maxy = cmaxy;\r
540 \r
541     return true;\r
542 }\r
543 \r
544 \r
545 /**\r
546  *  Output the curve data to buffer\r
547  */\r
548 bool JavaFXOutput::doCurvesRecursive(SPDocument *doc, Inkscape::XML::Node *node)\r
549 {\r
550     /**\r
551      * Check the type of node and process\r
552      */\r
553     String id;\r
554     char *idstr = (char *) node->attribute("id");\r
555     if (!idstr)\r
556         {\r
557         char buf[16];\r
558         sprintf(buf, "id%d", idindex++);\r
559         id = buf;\r
560         }\r
561     else\r
562         {\r
563         id = idstr;\r
564         }\r
565     SPObject *reprobj = doc->getObjectByRepr(node);\r
566     if (SP_IS_ITEM(reprobj))\r
567         {\r
568         SPItem *item = SP_ITEM(reprobj);\r
569         if (!doCurve(item, id))\r
570             return false;\r
571         }\r
572     else if (SP_IS_GRADIENT(reprobj))\r
573         {\r
574         SPGradient *grad = SP_GRADIENT(reprobj);\r
575         if (!doGradient(grad, id))\r
576             return false;\r
577         }\r
578 \r
579     /**\r
580      * Descend into children\r
581      */      \r
582     for (Inkscape::XML::Node *child = node->firstChild() ; child ;\r
583               child = child->next())\r
584         {\r
585                 if (!doCurvesRecursive(doc, child))\r
586                     return false;\r
587                 }\r
588 \r
589     return true;\r
590 }\r
591 \r
592 \r
593 /**\r
594  *  Output the curve data to buffer\r
595  */\r
596 bool JavaFXOutput::doCurves(SPDocument *doc)\r
597 {\r
598 \r
599     double bignum = 1000000.0;\r
600     minx  =  bignum;\r
601     maxx  = -bignum;\r
602     miny  =  bignum;\r
603     maxy  = -bignum;\r
604 \r
605     if (!doCurvesRecursive(doc, doc->rroot))\r
606         return false;\r
607 \r
608     return true;\r
609 \r
610 }\r
611 \r
612 \r
613 \r
614 \r
615 //########################################################################\r
616 //# M A I N    O U T P U T\r
617 //########################################################################\r
618 \r
619 \r
620 \r
621 /**\r
622  *  Set values back to initial state\r
623  */\r
624 void JavaFXOutput::reset()\r
625 {\r
626     nrNodes    = 0;\r
627     nrSegments = 0;\r
628     nrShapes   = 0;\r
629     idindex    = 0;\r
630     name.clear();\r
631     outbuf.clear();\r
632     foutbuf.clear();\r
633     linearGradients.clear();\r
634     radialGradients.clear();\r
635 }\r
636 \r
637 \r
638 \r
639 /**\r
640  * Saves the <paths> of an Inkscape SVG file as JavaFX spline definitions\r
641  */\r
642 bool JavaFXOutput::saveDocument(SPDocument *doc, gchar const *uri)\r
643 {\r
644     reset();\r
645 \r
646 \r
647     name = Glib::path_get_basename(uri);\r
648     int pos = name.find('.');\r
649     if (pos > 0)\r
650         name = name.substr(0, pos);\r
651 \r
652 \r
653     //###### SAVE IN POV FORMAT TO BUFFER\r
654     //# Lets do the curves first, to get the stats\r
655     \r
656     if (!doCurves(doc))\r
657         return false;\r
658     String curveBuf = outbuf;\r
659     outbuf.clear();\r
660 \r
661     if (!doHeader())\r
662         return false;\r
663     \r
664     outbuf.append(curveBuf);\r
665 \r
666     if (!doTail())\r
667         return false;\r
668 \r
669 \r
670 \r
671 \r
672     //###### WRITE TO FILE\r
673     FILE *f = Inkscape::IO::fopen_utf8name(uri, "w");\r
674     if (!f)\r
675         {\r
676         err("Could open JavaFX file '%s' for writing", uri);\r
677         return false;\r
678         }\r
679 \r
680     for (String::iterator iter = outbuf.begin() ; iter!=outbuf.end(); iter++)\r
681         {\r
682         fputc(*iter, f);\r
683         }\r
684         \r
685     fclose(f);\r
686     \r
687     return true;\r
688 }\r
689 \r
690 \r
691 \r
692 \r
693 //########################################################################\r
694 //# EXTENSION API\r
695 //########################################################################\r
696 \r
697 \r
698 \r
699 #include "clear-n_.h"\r
700 \r
701 \r
702 \r
703 /**\r
704  * API call to save document\r
705 */\r
706 void\r
707 JavaFXOutput::save(Inkscape::Extension::Output */*mod*/,\r
708                         SPDocument *doc, gchar const *uri)\r
709 {\r
710     if (!saveDocument(doc, uri))\r
711         {\r
712         g_warning("Could not save JavaFX file '%s'", uri);\r
713         }\r
714 }\r
715 \r
716 \r
717 \r
718 /**\r
719  * Make sure that we are in the database\r
720  */\r
721 bool JavaFXOutput::check (Inkscape::Extension::Extension */*module*/)\r
722 {\r
723     /* We don't need a Key\r
724     if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_JFX))\r
725         return FALSE;\r
726     */\r
727 \r
728     return true;\r
729 }\r
730 \r
731 \r
732 \r
733 /**\r
734  * This is the definition of JavaFX output.  This function just\r
735  * calls the extension system with the memory allocated XML that\r
736  * describes the data.\r
737 */\r
738 void\r
739 JavaFXOutput::init()\r
740 {\r
741     Inkscape::Extension::build_from_mem(\r
742         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"\r
743             "<name>" N_("JavaFX Output") "</name>\n"\r
744             "<id>org.inkscape.output.jfx</id>\n"\r
745             "<output>\n"\r
746                 "<extension>.fx</extension>\n"\r
747                 "<mimetype>text/x-javafx-script</mimetype>\n"\r
748                 "<filetypename>" N_("JavaFX (*.fx)") "</filetypename>\n"\r
749                 "<filetypetooltip>" N_("JavaFX Raytracer File") "</filetypetooltip>\n"\r
750             "</output>\n"\r
751         "</inkscape-extension>",\r
752         new JavaFXOutput());\r
753 }\r
754 \r
755 \r
756 \r
757 \r
758 \r
759 }  // namespace Internal\r
760 }  // namespace Extension\r
761 }  // namespace Inkscape\r
762 \r
763 \r
764 /*\r
765   Local Variables:\r
766   mode:c++\r
767   c-file-style:"stroustrup"\r
768   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
769   indent-tabs-mode:nil\r
770   fill-column:99\r
771   End:\r
772 */\r
773 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r