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)
106 {
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;
142 }
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)
157 {
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);
170 g_free(buffer);
171 return doc;
172 #else
173 return sp_document_new (uri, TRUE);
174 #endif
175 }
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)
203 {
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;
237 }
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 :