Code

r11472@tres: ted | 2006-04-22 20:32:45 -0700
[inkscape.git] / src / extension / internal / svg.cpp
1 /*
2  * This is the code that moves all of the SVG loading and saving into
3  * the module format.  Really Inkscape is built to handle these formats
4  * internally, so this is just calling those internal functions.
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *   Ted Gould <ted@gould.cx>
9  *
10  * Copyright (C) 2002-2003 Authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 #include "sp-object.h"
19 #include "svg.h"
20 #include "file.h"
21 #include "extension/system.h"
22 #include "extension/output.h"
24 #ifdef WITH_GNOME_VFS
25 # include <libgnomevfs/gnome-vfs.h>
26 #endif
28 namespace Inkscape {
29 namespace Extension {
30 namespace Internal {
32 #include "clear-n_.h"
34 /**
35     \return   None
36     \brief    What would an SVG editor be without loading/saving SVG
37               files.  This function sets that up.
39     For each module there is a call to Inkscape::Extension::build_from_mem
40     with a rather large XML file passed in.  This is a constant string
41     that describes the module.  At the end of this call a module is
42     returned that is basically filled out.  The one thing that it doesn't
43     have is the key function for the operation.  And that is linked at
44     the end of each call.
45 */
46 void
47 Svg::init(void)
48 {
49     Inkscape::Extension::Extension * ext;
51     /* SVG in */
52     ext = Inkscape::Extension::build_from_mem(
53         "<inkscape-extension>\n"
54             "<name>" N_("SVG Input") "</name>\n"
55             "<id>" SP_MODULE_KEY_INPUT_SVG "</id>\n"
56             "<input>\n"
57                 "<extension>.svg</extension>\n"
58                 "<mimetype>image/x-svg</mimetype>\n"
59                 "<filetypename>" N_("Scalable Vector Graphic (*.svg)") "</filetypename>\n"
60                 "<filetypetooltip>" N_("Inkscape native file format and W3C standard") "</filetypetooltip>\n"
61                 "<output_extension>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</output_extension>\n"
62             "</input>\n"
63         "</inkscape-extension>", new Svg());
65     /* SVG out Inkscape */
66     ext = Inkscape::Extension::build_from_mem(
67         "<inkscape-extension>\n"
68             "<name>" N_("SVG Output Inkscape") "</name>\n"
69             "<id>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</id>\n"
70             "<output>\n"
71                 "<extension>.svg</extension>\n"
72                 "<mimetype>image/x-svg</mimetype>\n"
73                 "<filetypename>" N_("Inkscape SVG (*.svg)") "</filetypename>\n"
74                 "<filetypetooltip>" N_("SVG format with Inkscape extensions") "</filetypetooltip>\n"
75                 "<dataloss>FALSE</dataloss>\n"
76             "</output>\n"
77         "</inkscape-extension>", new Svg());
79     /* SVG out */
80     ext = Inkscape::Extension::build_from_mem(
81         "<inkscape-extension>\n"
82             "<name>" N_("SVG Output") "</name>\n"
83             "<id>" SP_MODULE_KEY_OUTPUT_SVG "</id>\n"
84             "<output>\n"
85                 "<extension>.svg</extension>\n"
86                 "<mimetype>image/x-svg</mimetype>\n"
87                 "<filetypename>" N_("Plain SVG (*.svg)") "</filetypename>\n"
88                 "<filetypetooltip>" N_("Scalable Vector Graphics format as defined by the W3C") "</filetypetooltip>\n"
89             "</output>\n"
90         "</inkscape-extension>", new Svg());
92 #ifdef WITH_GNOME_VFS
93     gnome_vfs_init();
94 #endif
97     return;
98 }
101 #ifdef WITH_GNOME_VFS
102 #define BUF_SIZE 8192
104 gchar *
105 _load_uri (const gchar *uri)
107     GnomeVFSHandle   *handle = NULL;
108     GnomeVFSFileSize  bytes_read;
109     gchar             buffer[BUF_SIZE] = "";
110     gchar            *doc = NULL;
111     gchar            *new_doc = NULL;
113         gsize bytesRead = 0;
114         gsize bytesWritten = 0;
115         GError* error = NULL;
116         gchar* uri_local = g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error);
118         if ( uri_local == NULL ) {
119             g_warning( "Error converting filename to locale encoding.");
120         }
122     GnomeVFSResult result = gnome_vfs_open (&handle, uri_local, GNOME_VFS_OPEN_READ);
124     if (result != GNOME_VFS_OK) {
125         g_warning(gnome_vfs_result_to_string(result));
126     }
128     while (result == GNOME_VFS_OK) {
129         result = gnome_vfs_read (handle, buffer, BUF_SIZE, &bytes_read);
130         buffer[bytes_read] = '\0';
132         if (doc == NULL) {
133             doc = g_strndup(buffer, bytes_read);
134         } else {
135             new_doc = g_strconcat(doc, buffer, NULL);
136             g_free(doc);
137             doc = new_doc;
138         }
139     }
141     return doc;
143 #endif
146 /**
147     \return    A new document just for you!
148     \brief     This function takes in a filename of a SVG document and
149                turns it into a SPDocument.
150     \param     mod   Module to use
151     \param     uri   The path to the file (UTF-8)
153     This function is really simple, it just calls sp_document_new...
154 */
155 SPDocument *
156 Svg::open (Inkscape::Extension::Input *mod, const gchar *uri)
158 #ifdef WITH_GNOME_VFS
159     if (gnome_vfs_uri_is_local(gnome_vfs_uri_new(uri))) {
160         // Use built-in loader instead of VFS for this
161         return sp_document_new(uri, TRUE);
162     }
163     gchar * buffer = _load_uri(uri);
164     if (buffer == NULL) {
165         g_warning("Error:  Could not open file '%s' with VFS\n", uri);
166         return NULL;
167     }
168     SPDocument * doc = sp_document_new_from_mem(buffer, strlen(buffer), 1);
169     
170     g_free(buffer);
171     return doc;
172 #else
173     return sp_document_new (uri, TRUE);
174 #endif
177 /**
178     \return    None
179     \brief     This is the function that does all of the SVG saves in
180                Inkscape.  It detects whether it should do a Inkscape
181                namespace save internally.
182     \param     mod   Extension to use.
183     \param     doc   Document to save.
184     \param     uri   The filename to save the file to.
186     This function first checks it's parameters, and makes sure that
187     we're getting good data.  It also checks the module ID of the
188     incoming module to figure out if this is save should include
189     the Inkscape namespace stuff or not.  The result of that comparison
190     is stored in the spns variable.
192     If there is not to be Inkscape name spaces a new document is created
193     without.  (I think, I'm not sure on this code)
195     All of the internally referenced imageins are also set to relative
196     paths in the file.  And the file is saved.
198     This really needs to be fleshed out more, but I don't quite understand
199     all of this code.  I just stole it.
200 */
201 void
202 Svg::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
204     g_return_if_fail(doc != NULL);
205     g_return_if_fail(uri != NULL);
207     gchar *save_path = g_path_get_dirname (uri);
209     gboolean const spns = (!mod->get_id() 
210       || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)
211       || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVGZ_INKSCAPE));
213     Inkscape::XML::Document *rdoc = NULL;
214     Inkscape::XML::Node *repr = NULL;
215     if (spns) {
216         repr = sp_document_repr_root (doc);
217     } else {
218         rdoc = sp_repr_document_new ("svg:svg");
219         repr = sp_repr_document_root (rdoc);
220         repr = sp_document_root (doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
221     }
223     Inkscape::IO::fixupHrefs( doc, save_path, spns );
225     gboolean const s = sp_repr_save_file (sp_repr_document (repr), uri, SP_SVG_NS_URI);
226     if (s == FALSE) {
227         throw Inkscape::Extension::Output::save_failed();
228     }
230     if (!spns) {
231         Inkscape::GC::release(rdoc);
232     }
234     g_free(save_path);
236     return;
239 } } }  /* namespace inkscape, module, implementation */
241 /*
242   Local Variables:
243   mode:c++
244   c-file-style:"stroustrup"
245   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
246   indent-tabs-mode:nil
247   fill-column:99
248   End:
249 */
250 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :