Code

e6d02b62dbf5db759328d644dcaa2135267f4398
[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 /**
33     \return   None
34     \brief    What would an SVG editor be without loading/saving SVG
35               files.  This function sets that up.
37     For each module there is a call to Inkscape::Extension::build_from_mem
38     with a rather large XML file passed in.  This is a constant string
39     that describes the module.  At the end of this call a module is
40     returned that is basically filled out.  The one thing that it doesn't
41     have is the key function for the operation.  And that is linked at
42     the end of each call.
43 */
44 void
45 Svg::init(void)
46 {
47     Inkscape::Extension::Extension * ext;
49     /* SVG in */
50     ext = Inkscape::Extension::build_from_mem(
51         "<inkscape-extension>\n"
52             "<name>SVG Input</name>\n"
53             "<id>" SP_MODULE_KEY_INPUT_SVG "</id>\n"
54             "<input>\n"
55                 "<extension>.svg</extension>\n"
56                 "<mimetype>image/x-svg</mimetype>\n"
57                 "<filetypename>Scalable Vector Graphic (*.svg)</filetypename>\n"
58                 "<filetypetooltip>Inkscape native file format and W3C standard</filetypetooltip>\n"
59                 "<output_extension>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</output_extension>\n"
60             "</input>\n"
61         "</inkscape-extension>", new Svg());
63     /* SVG out Inkscape */
64     ext = Inkscape::Extension::build_from_mem(
65         "<inkscape-extension>\n"
66             "<name>SVG Output Inkscape</name>\n"
67             "<id>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</id>\n"
68             "<output>\n"
69                 "<extension>.svg</extension>\n"
70                 "<mimetype>image/x-svg</mimetype>\n"
71                 "<filetypename>Inkscape SVG (*.svg)</filetypename>\n"
72                 "<filetypetooltip>SVG format with Inkscape extensions</filetypetooltip>\n"
73                 "<dataloss>FALSE</dataloss>\n"
74             "</output>\n"
75         "</inkscape-extension>", new Svg());
77     /* SVG out */
78     ext = Inkscape::Extension::build_from_mem(
79         "<inkscape-extension>\n"
80             "<name>SVG Output</name>\n"
81             "<id>" SP_MODULE_KEY_OUTPUT_SVG "</id>\n"
82             "<output>\n"
83                 "<extension>.svg</extension>\n"
84                 "<mimetype>image/x-svg</mimetype>\n"
85                 "<filetypename>Plain SVG (*.svg)</filetypename>\n"
86                 "<filetypetooltip>Scalable Vector Graphics format as defined by the W3C</filetypetooltip>\n"
87             "</output>\n"
88         "</inkscape-extension>", new Svg());
90 #ifdef WITH_GNOME_VFS
91     gnome_vfs_init();
92 #endif
95     return;
96 }
99 #ifdef WITH_GNOME_VFS
100 #define BUF_SIZE 8192
102 gchar *
103 _load_uri (const gchar *uri)
105     GnomeVFSHandle   *handle = NULL;
106     GnomeVFSFileSize  bytes_read;
107     gchar             buffer[BUF_SIZE] = "";
108     gchar            *doc = NULL;
109     gchar            *new_doc = NULL;
111         gsize bytesRead = 0;
112         gsize bytesWritten = 0;
113         GError* error = NULL;
114         gchar* uri_local = g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error);
116         if ( uri_local == NULL ) {
117             g_warning( "Error converting filename to locale encoding.");
118         }
120     GnomeVFSResult result = gnome_vfs_open (&handle, uri_local, GNOME_VFS_OPEN_READ);
122     if (result != GNOME_VFS_OK) {
123         g_warning(gnome_vfs_result_to_string(result));
124     }
126     while (result == GNOME_VFS_OK) {
127         result = gnome_vfs_read (handle, buffer, BUF_SIZE, &bytes_read);
128         buffer[bytes_read] = '\0';
130         if (doc == NULL) {
131             doc = g_strndup(buffer, bytes_read);
132         } else {
133             new_doc = g_strconcat(doc, buffer, NULL);
134             g_free(doc);
135             doc = new_doc;
136         }
137     }
139     return doc;
141 #endif
144 /**
145     \return    A new document just for you!
146     \brief     This function takes in a filename of a SVG document and
147                turns it into a SPDocument.
148     \param     mod   Module to use
149     \param     uri   The path to the file (UTF-8)
151     This function is really simple, it just calls sp_document_new...
152 */
153 SPDocument *
154 Svg::open (Inkscape::Extension::Input *mod, const gchar *uri)
156 #ifdef WITH_GNOME_VFS
157     if (gnome_vfs_uri_is_local(gnome_vfs_uri_new(uri))) {
158         // Use built-in loader instead of VFS for this
159         return sp_document_new(uri, TRUE);
160     }
161     gchar * buffer = _load_uri(uri);
162     if (buffer == NULL) {
163         g_warning("Error:  Could not open file '%s' with VFS\n", uri);
164         return NULL;
165     }
166     SPDocument * doc = sp_document_new_from_mem(buffer, strlen(buffer), 1);
167     
168     g_free(buffer);
169     return doc;
170 #else
171     return sp_document_new (uri, TRUE);
172 #endif
175 /**
176     \return    None
177     \brief     This is the function that does all of the SVG saves in
178                Inkscape.  It detects whether it should do a Inkscape
179                namespace save internally.
180     \param     mod   Extension to use.
181     \param     doc   Document to save.
182     \param     uri   The filename to save the file to.
184     This function first checks it's parameters, and makes sure that
185     we're getting good data.  It also checks the module ID of the
186     incoming module to figure out if this is save should include
187     the Inkscape namespace stuff or not.  The result of that comparison
188     is stored in the spns variable.
190     If there is not to be Inkscape name spaces a new document is created
191     without.  (I think, I'm not sure on this code)
193     All of the internally referenced imageins are also set to relative
194     paths in the file.  And the file is saved.
196     This really needs to be fleshed out more, but I don't quite understand
197     all of this code.  I just stole it.
198 */
199 void
200 Svg::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
202     g_return_if_fail(doc != NULL);
203     g_return_if_fail(uri != NULL);
205     gchar *save_path = g_path_get_dirname (uri);
207     gboolean const spns = (!mod->get_id() 
208       || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)
209       || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVGZ_INKSCAPE));
211     Inkscape::XML::Document *rdoc = NULL;
212     Inkscape::XML::Node *repr = NULL;
213     if (spns) {
214         repr = sp_document_repr_root (doc);
215     } else {
216         rdoc = sp_repr_document_new ("svg:svg");
217         repr = sp_repr_document_root (rdoc);
218         repr = sp_document_root (doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
219     }
221     Inkscape::IO::fixupHrefs( doc, save_path, spns );
223     gboolean const s = sp_repr_save_file (sp_repr_document (repr), uri, SP_SVG_NS_URI);
224     if (s == FALSE) {
225         throw Inkscape::Extension::Output::save_failed();
226     }
228     if (!spns) {
229         Inkscape::GC::release(rdoc);
230     }
232     g_free(save_path);
234     return;
237 } } }  /* namespace inkscape, module, implementation */
239 /*
240   Local Variables:
241   mode:c++
242   c-file-style:"stroustrup"
243   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
244   indent-tabs-mode:nil
245   fill-column:99
246   End:
247 */
248 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :