Code

Fixed desktop-to-doc Y flip
[inkscape.git] / src / extension / internal / odf.cpp
1 /**
2  * OpenDocument <drawing> input and output
3  *
4  * This is an an entry in the extensions mechanism to begin to enable
5  * the inputting and outputting of OpenDocument Format (ODF) files from
6  * within Inkscape.  Although the initial implementations will be very lossy
7  * do to the differences in the models of SVG and ODF, they will hopefully
8  * improve greatly with time.
9  *
10  * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
11  *
12  * Authors:
13  *   Bob Jamison
14  *
15  * Copyright (C) 2006 Bob Jamison
16  *
17  *  This library is free software; you can redistribute it and/or
18  *  modify it under the terms of the GNU Lesser General Public
19  *  License as published by the Free Software Foundation; either
20  *  version 2.1 of the License, or (at your option) any later version.
21  *
22  *  This library is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  *  Lesser General Public License for more details.
26  *
27  *  You should have received a copy of the GNU Lesser General Public
28  *  License along with this library; if not, write to the Free Software
29  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30  */
34 #ifdef HAVE_CONFIG_H
35 # include <config.h>
36 #endif
38 #include "odf.h"
40 //# System includes
41 #include <stdio.h>
42 #include <time.h>
43 #include <vector>
46 //# Inkscape includes
47 #include "clear-n_.h"
48 #include "inkscape.h"
49 #include <style.h>
50 #include "display/curve.h"
51 #include "libnr/n-art-bpath.h"
52 #include "extension/system.h"
54 #include "xml/repr.h"
55 #include "xml/attribute-record.h"
56 #include "sp-image.h"
57 #include "sp-path.h"
58 #include "sp-text.h"
59 #include "sp-flowtext.h"
60 #include "svg/svg.h"
61 #include "text-editing.h"
64 //# DOM-specific includes
65 #include "dom/dom.h"
66 #include "dom/util/ziptool.h"
67 #include "dom/io/domstream.h"
68 #include "dom/io/bufferstream.h"
71 //# Shorthand notation
72 typedef org::w3c::dom::DOMString DOMString;
73 typedef org::w3c::dom::io::OutputStreamWriter OutputStreamWriter;
74 typedef org::w3c::dom::io::BufferOutputStream BufferOutputStream;
79 namespace Inkscape
80 {
81 namespace Extension
82 {
83 namespace Internal
84 {
87 //#define pxToCm  0.0275
88 #define pxToCm  0.0333
89 #define piToRad 0.0174532925
90 #define docHeightCm 22.86
93 //########################################################################
94 //# O U T P U T
95 //########################################################################
97 static std::string getAttribute( Inkscape::XML::Node *node, char *attrName)
98 {
99     std::string val;
100     char *valstr = (char *)node->attribute(attrName);
101     if (valstr)
102         val = (const char *)valstr;
103     return val;
107 static std::string getExtension(const std::string &fname)
109     std::string ext;
111     unsigned int pos = fname.rfind('.');
112     if (pos == fname.npos)
113         {
114         ext = "";
115         }
116     else
117         {
118         ext = fname.substr(pos);
119         }
120     return ext;
123 /**
124  * Method descends into the repr tree, converting image and style info
125  * into forms compatible in ODF.
126  */
127 void
128 OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node)
131     std::string nodeName = node->name();
132     std::string id       = getAttribute(node, "id");
134     if (nodeName == "image" || nodeName == "svg:image")
135         {
136         //g_message("image");
137         std::string href = getAttribute(node, "xlink:href");
138         if (href.size() > 0)
139             {
140             std::string oldName = href;
141             std::string ext = getExtension(oldName);
142             if (ext == ".jpeg")
143                 ext = ".jpg";
144             if (imageTable.find(oldName) == imageTable.end())
145                 {
146                 char buf[64];
147                 snprintf(buf, 63, "Pictures/image%d%s",
148                     imageTable.size(), ext.c_str());
149                 std::string newName = buf;
150                 imageTable[oldName] = newName;
151                 std::string comment = "old name was: ";
152                 comment.append(oldName);
153                 ZipEntry *ze = zf.addFile(oldName, comment);
154                 if (ze)
155                     {
156                     ze->setFileName(newName);
157                     }
158                 else
159                     {
160                     g_warning("Could not load image file '%s'", oldName.c_str());
161                     }
162                 }
163             }
164         }
168     SPObject *reprobj = SP_ACTIVE_DOCUMENT->getObjectByRepr(node);
169     if (!reprobj)
170         return;
171     if (!SP_IS_ITEM(reprobj))
172         {
173         return;
174         }
175     SPItem *item = SP_ITEM(reprobj);
176     SPStyle *style = SP_OBJECT_STYLE(item);
177     if (style && id.size()>0)
178         {
179         StyleInfo si;
180         if (style->fill.type == SP_PAINT_TYPE_COLOR)
181             {
182             guint32 fillCol =
183                 sp_color_get_rgba32_ualpha(&style->fill.value.color, 0);
184             char buf[16];
185             int r = (fillCol >> 24) & 0xff;
186             int g = (fillCol >> 16) & 0xff;
187             int b = (fillCol >>  8) & 0xff;
188             //g_message("## %s %lx", id.c_str(), fillCol);
189             snprintf(buf, 15, "#%02x%02x%02x", r, g, b);
190             si.fillColor = buf;
191             si.fill      = "solid";
192             }
193         if (style->stroke.type == SP_PAINT_TYPE_COLOR)
194             {
195             guint32 strokeCol =
196                 sp_color_get_rgba32_ualpha(&style->stroke.value.color, 0);
197             char buf[16];
198             int r = (strokeCol >> 24) & 0xff;
199             int g = (strokeCol >> 16) & 0xff;
200             int b = (strokeCol >>  8) & 0xff;
201             snprintf(buf, 15, "#%02x%02x%02x", r, g, b);
202             si.strokeColor = buf;
203             snprintf(buf, 15, "%.2fpt", style->stroke_width.value);
204             si.strokeWidth = buf;
205             si.stroke      = "solid";
206             }
208         styleTable[id] = si;
209         }
211     /*
212     //Look for style values in the svg element
213     Inkscape::Util::List<Inkscape::XML::AttributeRecord const> attr =
214         node->attributeList();
215     for ( ; attr ; ++attr)
216         {
217         if (!attr->key || !attr->value)
218             {
219             g_warning("null key or value in attribute");
220             continue;
221             }
222         //g_message("key:%s value:%s", g_quark_to_string(attr->key),
223         //                             g_quark_to_string(attr->value)  );
225         std::string attrName  = (const char *)g_quark_to_string(attr->key);
226         std::string attrValue = (const char *)attr->value;
227         //g_message("tag:'%s'    key:'%s'    value:'%s'",
228         //    nodeName.c_str(), attrName.c_str(), attrValue.c_str()  );
229         if (attrName == "style")
230             {
231             StyleInfo si(attrName, attrValue);
232             if (styleTable.find(attrValue) != styleTable.end())
233                 {
234                 //g_message("duplicate style");
235                 }
236             else
237                 {
238                 char buf[16];
239                 snprintf(buf, 15, "style%d", styleTable.size());
240                 std::string attrName  = buf;
241                 //Map from value-->name .   Looks backwards, i know
242                 styleTable[attrValue] = si;
243                 //g_message("mapping '%s' to '%s'",
244                 //    attrValue.c_str(), attrName.c_str());
245                 }
246             }
247         }
248     */
251     for (Inkscape::XML::Node *child = node->firstChild() ;
252             child ; child = child->next())
253         preprocess(zf, child);
258 bool OdfOutput::writeManifest(ZipFile &zf)
260     BufferOutputStream bouts;
261     OutputStreamWriter outs(bouts);
263     time_t tim;
264     time(&tim);
266     outs.printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
267     outs.printf("<!DOCTYPE manifest:manifest PUBLIC \"-//OpenOffice.org//DTD Manifest 1.0//EN\" \"Manifest.dtd\">\n");
268     outs.printf("\n");
269     outs.printf("\n");
270     outs.printf("<!--\n");
271     outs.printf("*************************************************************************\n");
272     outs.printf("  file:  manifest.xml\n");
273     outs.printf("  Generated by Inkscape: %s", ctime(&tim)); //ctime has its own <cr>
274     outs.printf("  http://www.inkscape.org\n");
275     outs.printf("*************************************************************************\n");
276     outs.printf("-->\n");
277     outs.printf("\n");
278     outs.printf("\n");
279     outs.printf("<manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\">\n");
280     outs.printf("    <manifest:file-entry manifest:media-type=\"application/vnd.oasis.opendocument.graphics\" manifest:full-path=\"/\"/>\n");
281     outs.printf("    <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"content.xml\"/>\n");
282     outs.printf("    <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"meta.xml\"/>\n");
283     outs.printf("    <!--List our images here-->\n");
284     std::map<std::string, std::string>::iterator iter;
285     for (iter = imageTable.begin() ; iter!=imageTable.end() ; iter++)
286         {
287         std::string oldName = iter->first;
288         std::string newName = iter->second;
290         std::string ext = getExtension(oldName);
291         if (ext == ".jpeg")
292             ext = ".jpg";
293         outs.printf("    <manifest:file-entry manifest:media-type=\"");
294         if (ext == ".gif")
295             outs.printf("image/gif");
296         else if (ext == ".png")
297             outs.printf("image/png");
298         else if (ext == ".jpg")
299             outs.printf("image/jpeg");
300         outs.printf("\" manifest:full-path=\"");
301         outs.printf((char *)newName.c_str());
302         outs.printf("\"/>\n");
303         }
304     outs.printf("</manifest:manifest>\n");
306     outs.close();
308     //Make our entry
309     ZipEntry *ze = zf.newEntry("META-INF/manifest.xml", "ODF file manifest");
310     ze->setUncompressedData(bouts.getBuffer());
311     ze->finish();
313     return true;
317 bool OdfOutput::writeMeta(ZipFile &zf)
319     BufferOutputStream bouts;
320     OutputStreamWriter outs(bouts);
322     time_t tim;
323     time(&tim);
325     outs.printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
326     outs.printf("\n");
327     outs.printf("\n");
328     outs.printf("<!--\n");
329     outs.printf("*************************************************************************\n");
330     outs.printf("  file:  meta.xml\n");
331     outs.printf("  Generated by Inkscape: %s", ctime(&tim)); //ctime has its own <cr>
332     outs.printf("  http://www.inkscape.org\n");
333     outs.printf("*************************************************************************\n");
334     outs.printf("-->\n");
335     outs.printf("\n");
336     outs.printf("\n");
337     outs.printf("<office:document-meta\n");
338     outs.printf("xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"\n");
339     outs.printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n");
340     outs.printf("xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n");
341     outs.printf("xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"\n");
342     outs.printf("xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\"\n");
343     outs.printf("xmlns:ooo=\"http://openoffice.org/2004/office\"\n");
344     outs.printf("xmlns:smil=\"urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0\"\n");
345     outs.printf("xmlns:anim=\"urn:oasis:names:tc:opendocument:xmlns:animation:1.0\"\n");
346     outs.printf("office:version=\"1.0\">\n");
347     outs.printf("<office:meta>\n");
348     outs.printf("    <meta:generator>Inkscape.org - 0.44</meta:generator>\n");
349     outs.printf("    <meta:initial-creator>clark kent</meta:initial-creator>\n");
350     outs.printf("    <meta:creation-date>2006-04-13T17:12:29</meta:creation-date>\n");
351     outs.printf("    <dc:creator>clark kent</dc:creator>\n");
352     outs.printf("    <dc:date>2006-04-13T17:13:20</dc:date>\n");
353     outs.printf("    <dc:language>en-US</dc:language>\n");
354     outs.printf("    <meta:editing-cycles>2</meta:editing-cycles>\n");
355     outs.printf("    <meta:editing-duration>PT56S</meta:editing-duration>\n");
356     outs.printf("    <meta:user-defined meta:name=\"Info 1\"/>\n");
357     outs.printf("    <meta:user-defined meta:name=\"Info 2\"/>\n");
358     outs.printf("    <meta:user-defined meta:name=\"Info 3\"/>\n");
359     outs.printf("    <meta:user-defined meta:name=\"Info 4\"/>\n");
360     outs.printf("    <meta:document-statistic meta:object-count=\"2\"/>\n");
361     outs.printf("</office:meta>\n");
362     outs.printf("</office:document-meta>\n");
363     outs.printf("\n");
364     outs.printf("\n");
367     outs.close();
369     //Make our entry
370     ZipEntry *ze = zf.newEntry("meta.xml", "ODF info file");
371     ze->setUncompressedData(bouts.getBuffer());
372     ze->finish();
374     return true;
378 bool OdfOutput::writeStyle(Writer &outs)
380     outs.printf("<office:automatic-styles>\n");
381     outs.printf("<style:style style:name=\"dp1\" style:family=\"drawing-page\"/>\n");
382     outs.printf("<style:style style:name=\"grx1\" style:family=\"graphic\" style:parent-style-name=\"standard\">\n");
383     outs.printf("  <style:graphic-properties draw:stroke=\"none\" draw:fill=\"solid\"\n");
384     outs.printf("       draw:textarea-horizontal-align=\"center\"\n");
385     outs.printf("       draw:textarea-vertical-align=\"middle\" draw:color-mode=\"standard\"\n");
386     outs.printf("       draw:luminance=\"0%\" draw:contrast=\"0%\" draw:gamma=\"100%\" draw:red=\"0%\"\n");
387     outs.printf("       draw:green=\"0%\" draw:blue=\"0%\" fo:clip=\"rect(0cm 0cm 0cm 0cm)\"\n");
388     outs.printf("       draw:image-opacity=\"100%\" style:mirror=\"none\"/>\n");
389     outs.printf("</style:style>\n");
390     outs.printf("<style:style style:name=\"P1\" style:family=\"paragraph\">\n");
391     outs.printf("  <style:paragraph-properties fo:text-align=\"center\"/>\n");
392     outs.printf("</style:style>\n");
394     //##  Dump our style table
395     std::map<std::string, StyleInfo>::iterator iter;
396     for (iter = styleTable.begin() ; iter != styleTable.end() ; iter++)
397         {
398         outs.printf("<style:style style:name=\"%s\"", iter->first.c_str());
399         StyleInfo s(iter->second);
400         outs.printf(" style:family=\"graphic\" style:parent-style-name=\"standard\">\n");
401         outs.printf("  <style:graphic-properties");
402         outs.printf(" draw:fill=\"%s\" ", s.getFill().c_str());
403         if (s.getFill() != "none")
404             outs.printf(" draw:fill-color=\"%s\" ", s.getFillColor().c_str());
405         outs.printf(" draw:stroke=\"%s\" ", s.getStroke().c_str());
406         if (s.getStroke() != "none")
407             {
408             outs.printf(" svg:stroke-width=\"%s\" ", s.getStrokeWidth().c_str());
409             outs.printf(" svg:stroke-color=\"%s\" ", s.getStrokeColor().c_str());
410             }
411         outs.printf("/>\n");
412         outs.printf("</style:style>\n");
413         }
415     outs.printf("</office:automatic-styles>\n");
416     outs.printf("\n");
418     return true;
422 static void
423 writePath(Writer &outs, NArtBpath const *bpath,
424           NR::Matrix &tf, double xoff, double yoff)
426     bool closed = false;
427     NArtBpath *bp = (NArtBpath *)bpath;
428     for (  ; bp->code != NR_END; bp++)
429         {
430         NR::Point const p1(bp->c(1) * tf);
431         NR::Point const p2(bp->c(2) * tf);
432         NR::Point const p3(bp->c(3) * tf);
433         double x1 = (p1[NR::X] * pxToCm - xoff) * 1000.0;
434         double y1 = (p1[NR::Y] * pxToCm - yoff) * 1000.0;
435         double x2 = (p2[NR::X] * pxToCm - xoff) * 1000.0;
436         double y2 = (p2[NR::Y] * pxToCm - yoff) * 1000.0;
437         double x3 = (p3[NR::X] * pxToCm - xoff) * 1000.0;
438         double y3 = (p3[NR::Y] * pxToCm - yoff) * 1000.0;
440         switch (bp->code)
441             {
442             case NR_LINETO:
443                 outs.printf("L %.3f,%.3f ",  x3 , y3);
444                 break;
446             case NR_CURVETO:
447                 outs.printf("C %.3f,%.3f %.3f,%.3f %.3f,%.3f ",
448                               x1, y1, x2, y2, x3, y3);
449                 break;
451             case NR_MOVETO_OPEN:
452             case NR_MOVETO:
453                 if (closed)
454                     outs.printf("z ");
455                 closed = ( bp->code == NR_MOVETO );
456                 outs.printf("M %.3f,%.3f ",  x3 , y3);
457                 break;
459             default:
460                 break;
462             }
464         }
466     if (closed)
467         outs.printf("z");;
473 bool OdfOutput::writeTree(Writer &outs, Inkscape::XML::Node *node)
475     //# Get the SPItem, if applicable
476     SPObject *reprobj = SP_ACTIVE_DOCUMENT->getObjectByRepr(node);
477     if (!reprobj)
478         return true;
479     if (!SP_IS_ITEM(reprobj))
480         {
481         return true;
482         }
483     SPItem *item = SP_ITEM(reprobj);
485     std::string nodeName = node->name();
486     std::string id       = getAttribute(node, "id");
488     NR::Matrix tf = sp_item_i2d_affine(item);
489     NR::Rect bbox = sp_item_bbox_desktop(item);
491     //Flip Y into document coordinates
492     double svgHeight = sp_document_height(SP_ACTIVE_DOCUMENT);
493     double doc_height = svgHeight; // * pxToCm;
494     NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1, -1));
495     doc2dt_tf = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height));
496     tf        = tf   * doc2dt_tf;
497     bbox      = bbox * doc2dt_tf;
499     double x      = pxToCm * bbox.min()[NR::X];
500     double y      = pxToCm * bbox.min()[NR::Y];
501     double width  = pxToCm * ( bbox.max()[NR::X] - bbox.min()[NR::X] );
502     double height = pxToCm * ( bbox.max()[NR::Y] - bbox.min()[NR::Y] );
505     //# Do our stuff
506     SPCurve *curve = NULL;
508     //g_message("##### %s #####", nodeName.c_str());
510     if (nodeName == "svg" || nodeName == "svg:svg")
511         {
512         //# Iterate through the children
513         for (Inkscape::XML::Node *child = node->firstChild() ; child ; child = child->next())
514             {
515             if (!writeTree(outs, child))
516                 return false;
517             }
518         return true;
519         }
520     else if (nodeName == "g" || nodeName == "svg:g")
521         {
522         if (id.size() > 0)
523             outs.printf("<draw:g id=\"%s\">", id.c_str());
524         else
525             outs.printf("<draw:g>\n");
526         //# Iterate through the children
527         for (Inkscape::XML::Node *child = node->firstChild() ; child ; child = child->next())
528             {
529             if (!writeTree(outs, child))
530                 return false;
531             }
532         outs.printf("</draw:g>\n");
533         return true;
534         }
535     else if (nodeName == "image" || nodeName == "svg:image")
536         {
537         std::string href = getAttribute(node, "xlink:href");
538         std::map<std::string, std::string>::iterator iter = imageTable.find(href);
539         if (iter == imageTable.end())
540             {
541             g_warning("image '%s' not in table", href.c_str());
542             return false;
543             }
544         std::string newName = iter->second;
546         outs.printf("<draw:frame ");
547         if (id.size() > 0)
548             outs.printf("id=\"%s\" ", id.c_str());
549         outs.printf("draw:style-name=\"gr1\" draw:text-style-name=\"P1\" draw:layer=\"layout\"");
550         outs.printf(" svg:width=\"%.3f\" svg:height=\"%.3f\" svg:x=\"%.3f\" svg:y=\"%.3f\">\n",
551                                   x, y, width, height);
553         outs.printf("    <draw:image xlink:href=\"%s\"/>\n", newName.c_str());
554         outs.printf("</draw:frame>\n");
555         return true;
556         }
557     else if (SP_IS_SHAPE(item))
558         {
559         //g_message("### %s is a shape", nodeName.c_str());
560         curve = sp_shape_get_curve(SP_SHAPE(item));
561         }
562     else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))
563         {
564         curve = te_get_layout(item)->convertToCurves();
565         }
567     if (curve)
568         {
569         //Inkscape::XML::Node *repr = sp_repr_new("svg:path");
570         /* Transformation */
571         //repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform"));
573         /* Rotation center */
574         //sp_repr_set_attr(repr, "inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"));
575         //sp_repr_set_attr(repr, "inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"));
577         /* Definition */
579         outs.printf("<draw:path ");
580         if (id.size()>0)
581             outs.printf("id=\"%s\" ", id.c_str());
583         std::map<std::string, StyleInfo>::iterator iter;
584         iter = styleTable.find(id);
585         if (iter != styleTable.end())
586             outs.printf("draw:style-name=\"%s\" ", id.c_str());
588         outs.printf("draw:layer=\"layout\" svg:x=\"%.3fcm\" svg:y=\"%.3fcm\" ",
589                        x, y);
590         outs.printf("svg:width=\"%.3fcm\" svg:height=\"%.3fcm\" ",
591                        width, height);
592         outs.printf("svg:viewBox=\"0.0 0.0 %.3f %.3f\"\n",
593                        width * 1000.0, height * 1000.0);
595         outs.printf("    svg:d=\"");
596         writePath(outs, curve->bpath, tf, x, y);
597         outs.printf("\"");
599         outs.printf(">\n");
600         outs.printf("</draw:path>\n");
603         sp_curve_unref(curve);
604         }
606     return true;
612 bool OdfOutput::writeContent(ZipFile &zf, Inkscape::XML::Node *node)
614     BufferOutputStream bouts;
615     OutputStreamWriter outs(bouts);
617     time_t tim;
618     time(&tim);
620     outs.printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
621     outs.printf("\n");
622     outs.printf("\n");
623     outs.printf("<!--\n");
624     outs.printf("*************************************************************************\n");
625     outs.printf("  file:  content.xml\n");
626     outs.printf("  Generated by Inkscape: %s", ctime(&tim)); //ctime has its own <cr>
627     outs.printf("  http://www.inkscape.org\n");
628     outs.printf("*************************************************************************\n");
629     outs.printf("-->\n");
630     outs.printf("\n");
631     outs.printf("\n");
632     outs.printf("<office:document-content\n");
633     outs.printf("    xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"\n");
634     outs.printf("    xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"\n");
635     outs.printf("    xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\"\n");
636     outs.printf("    xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\"\n");
637     outs.printf("    xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\"\n");
638     outs.printf("    xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\"\n");
639     outs.printf("    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n");
640     outs.printf("    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n");
641     outs.printf("    xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"\n");
642     outs.printf("    xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\"\n");
643     outs.printf("    xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\"\n");
644     outs.printf("    xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\"\n");
645     outs.printf("    xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\"\n");
646     outs.printf("    xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\"\n");
647     outs.printf("    xmlns:math=\"http://www.w3.org/1998/Math/MathML\"\n");
648     outs.printf("    xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\"\n");
649     outs.printf("    xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\"\n");
650     outs.printf("    xmlns:ooo=\"http://openoffice.org/2004/office\"\n");
651     outs.printf("    xmlns:ooow=\"http://openoffice.org/2004/writer\"\n");
652     outs.printf("    xmlns:oooc=\"http://openoffice.org/2004/calc\"\n");
653     outs.printf("    xmlns:dom=\"http://www.w3.org/2001/xml-events\"\n");
654     outs.printf("    xmlns:xforms=\"http://www.w3.org/2002/xforms\"\n");
655     outs.printf("    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
656     outs.printf("    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
657     outs.printf("    xmlns:smil=\"urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0\"\n");
658     outs.printf("    xmlns:anim=\"urn:oasis:names:tc:opendocument:xmlns:animation:1.0\"\n");
659     outs.printf("    office:version=\"1.0\">\n");
660     outs.printf("\n");
661     outs.printf("\n");
662     outs.printf("<office:scripts/>\n");
663     outs.printf("\n");
664     outs.printf("\n");
665     //AffineTransform trans = new AffineTransform();
666     //trans.scale(12.0, 12.0);
667     outs.printf("<!-- ######### CONVERSION FROM SVG STARTS ######## -->\n");
668     outs.printf("<!--\n");
669     outs.printf("*************************************************************************\n");
670     outs.printf("  S T Y L E S\n");
671     outs.printf("  Style entries have been pulled from the svg style and\n");
672     outs.printf("  representation attributes in the SVG tree.  The tree elements\n");
673     outs.printf("  then refer to them by name, in the ODF manner\n");
674     outs.printf("*************************************************************************\n");
675     outs.printf("-->\n");
676     outs.printf("\n");
677     outs.printf("\n");
679     if (!writeStyle(outs))
680         {
681         g_warning("Failed to write styles");
682         return false;
683         }
685     outs.printf("\n");
686     outs.printf("\n");
687     outs.printf("\n");
688     outs.printf("\n");
689     outs.printf("<!--\n");
690     outs.printf("*************************************************************************\n");
691     outs.printf("  D R A W I N G\n");
692     outs.printf("  This section is the heart of SVG-ODF conversion.  We are\n");
693     outs.printf("  starting with simple conversions, and will slowly evolve\n");
694     outs.printf("  into a 'smarter' translation as time progresses.  Any help\n");
695     outs.printf("  in improving .odg export is welcome.\n");
696     outs.printf("*************************************************************************\n");
697     outs.printf("-->\n");
698     outs.printf("\n");
699     outs.printf("\n");
700     outs.printf("<office:body>\n");
701     outs.printf("<office:drawing>\n");
702     outs.printf("<draw:page draw:name=\"page1\" draw:style-name=\"dp1\"\n");
703     outs.printf("        draw:master-page-name=\"Default\">\n");
704     outs.printf("\n");
705     outs.printf("\n");
707     if (!writeTree(outs, node))
708         {
709         g_warning("Failed to convert SVG tree");
710         return false;
711         }
713     outs.printf("\n");
714     outs.printf("\n");
716     outs.printf("</draw:page>\n");
717     outs.printf("</office:drawing>\n");
719     outs.printf("\n");
720     outs.printf("\n");
721     outs.printf("<!-- ######### CONVERSION FROM SVG ENDS ######## -->\n");
722     outs.printf("\n");
723     outs.printf("\n");
725     outs.printf("</office:body>\n");
726     outs.printf("</office:document-content>\n");
727     outs.printf("\n");
728     outs.printf("\n");
729     outs.printf("\n");
730     outs.printf("<!--\n");
731     outs.printf("*************************************************************************\n");
732     outs.printf("  E N D    O F    F I L E\n");
733     outs.printf("  Have a nice day  - ishmal\n");
734     outs.printf("*************************************************************************\n");
735     outs.printf("-->\n");
736     outs.printf("\n");
737     outs.printf("\n");
741     //Make our entry
742     ZipEntry *ze = zf.newEntry("content.xml", "ODF master content file");
743     ze->setUncompressedData(bouts.getBuffer());
744     ze->finish();
746     return true;
752 /**
753  * Descends into the SVG tree, mapping things to ODF when appropriate
754  */
755 void
756 OdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *uri)
758     ZipFile zf;
759     styleTable.clear();
760     imageTable.clear();
761     preprocess(zf, doc->rroot);
763     if (!writeManifest(zf))
764         {
765         g_warning("Failed to write manifest");
766         return;
767         }
769     if (!writeMeta(zf))
770         {
771         g_warning("Failed to write metafile");
772         return;
773         }
775     if (!writeContent(zf, doc->rroot))
776         {
777         g_warning("Failed to write content");
778         return;
779         }
781     if (!zf.writeFile(uri))
782         {
783         return;
784         }
788 /**
789  * This is the definition of PovRay output.  This function just
790  * calls the extension system with the memory allocated XML that
791  * describes the data.
792 */
793 void
794 OdfOutput::init()
796     Inkscape::Extension::build_from_mem(
797         "<inkscape-extension>\n"
798             "<name>" N_("OpenDocument Drawing Output") "</name>\n"
799             "<id>org.inkscape.output.odf</id>\n"
800             "<output>\n"
801                 "<extension>.odg</extension>\n"
802                 "<mimetype>text/x-povray-script</mimetype>\n"
803                 "<filetypename>" N_("OpenDocument drawing (*.odg)") "</filetypename>\n"
804                 "<filetypetooltip>" N_("OpenDocument drawing file") "</filetypetooltip>\n"
805             "</output>\n"
806         "</inkscape-extension>",
807         new OdfOutput());
810 /**
811  * Make sure that we are in the database
812  */
813 bool
814 OdfOutput::check (Inkscape::Extension::Extension *module)
816     /* We don't need a Key
817     if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_POV))
818         return FALSE;
819     */
821     return TRUE;
826 //########################################################################
827 //# I N P U T
828 //########################################################################
832 //#######################
833 //# L A T E R  !!!  :-)
834 //#######################
848 }  //namespace Internal
849 }  //namespace Extension
850 }  //namespace Inkscape
853 //########################################################################
854 //# E N D    O F    F I L E
855 //########################################################################
857 /*
858   Local Variables:
859   mode:c++
860   c-file-style:"stroustrup"
861   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
862   indent-tabs-mode:nil
863   fill-column:99
864   End:
865 */
866 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :