e6d02b62dbf5db759328d644dcaa2135267f4398
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)
104 {
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;
140 }
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)
155 {
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);
168 g_free(buffer);
169 return doc;
170 #else
171 return sp_document_new (uri, TRUE);
172 #endif
173 }
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)
201 {
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;
235 }
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 :