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"
23 #include <vector>
25 #ifdef WITH_GNOME_VFS
26 # include <libgnomevfs/gnome-vfs.h>
27 #endif
29 namespace Inkscape {
30 namespace Extension {
31 namespace Internal {
33 #include "clear-n_.h"
35 /**
36 \return None
37 \brief What would an SVG editor be without loading/saving SVG
38 files. This function sets that up.
40 For each module there is a call to Inkscape::Extension::build_from_mem
41 with a rather large XML file passed in. This is a constant string
42 that describes the module. At the end of this call a module is
43 returned that is basically filled out. The one thing that it doesn't
44 have is the key function for the operation. And that is linked at
45 the end of each call.
46 */
47 void
48 Svg::init(void)
49 {
50 Inkscape::Extension::Extension * ext;
52 /* SVG in */
53 ext = Inkscape::Extension::build_from_mem(
54 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
55 "<name>" N_("SVG Input") "</name>\n"
56 "<id>" SP_MODULE_KEY_INPUT_SVG "</id>\n"
57 "<input>\n"
58 "<extension>.svg</extension>\n"
59 "<mimetype>image/svg+xml</mimetype>\n"
60 "<filetypename>" N_("Scalable Vector Graphic (*.svg)") "</filetypename>\n"
61 "<filetypetooltip>" N_("Inkscape native file format and W3C standard") "</filetypetooltip>\n"
62 "<output_extension>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</output_extension>\n"
63 "</input>\n"
64 "</inkscape-extension>", new Svg());
66 /* SVG out Inkscape */
67 ext = Inkscape::Extension::build_from_mem(
68 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
69 "<name>" N_("SVG Output Inkscape") "</name>\n"
70 "<id>" SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE "</id>\n"
71 "<output>\n"
72 "<extension>.svg</extension>\n"
73 "<mimetype>image/x-inkscape-svg</mimetype>\n"
74 "<filetypename>" N_("Inkscape SVG (*.svg)") "</filetypename>\n"
75 "<filetypetooltip>" N_("SVG format with Inkscape extensions") "</filetypetooltip>\n"
76 "<dataloss>false</dataloss>\n"
77 "</output>\n"
78 "</inkscape-extension>", new Svg());
80 /* SVG out */
81 ext = Inkscape::Extension::build_from_mem(
82 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
83 "<name>" N_("SVG Output") "</name>\n"
84 "<id>" SP_MODULE_KEY_OUTPUT_SVG "</id>\n"
85 "<output>\n"
86 "<extension>.svg</extension>\n"
87 "<mimetype>image/svg+xml</mimetype>\n"
88 "<filetypename>" N_("Plain SVG (*.svg)") "</filetypename>\n"
89 "<filetypetooltip>" N_("Scalable Vector Graphics format as defined by the W3C") "</filetypetooltip>\n"
90 "</output>\n"
91 "</inkscape-extension>", new Svg());
93 #ifdef WITH_GNOME_VFS
94 gnome_vfs_init();
95 #endif
98 return;
99 }
102 #ifdef WITH_GNOME_VFS
103 #define BUF_SIZE 8192
105 static gchar *
106 _load_uri (const gchar *uri)
107 {
108 GnomeVFSHandle *handle = NULL;
109 GnomeVFSFileSize bytes_read;
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("%s", gnome_vfs_result_to_string(result));
124 }
126 std::vector<gchar> doc;
127 while (result == GNOME_VFS_OK) {
128 gchar buffer[BUF_SIZE];
129 result = gnome_vfs_read (handle, buffer, BUF_SIZE, &bytes_read);
130 doc.insert(doc.end(), buffer, buffer+bytes_read);
131 }
133 return g_strndup(&doc[0], doc.size());
134 }
135 #endif
138 /**
139 \return A new document just for you!
140 \brief This function takes in a filename of a SVG document and
141 turns it into a SPDocument.
142 \param mod Module to use
143 \param uri The path to the file (UTF-8)
145 This function is really simple, it just calls sp_document_new...
146 */
147 SPDocument *
148 Svg::open (Inkscape::Extension::Input */*mod*/, const gchar *uri)
149 {
150 #ifdef WITH_GNOME_VFS
151 if (!gnome_vfs_initialized() || gnome_vfs_uri_is_local(gnome_vfs_uri_new(uri))) {
152 // Use built-in loader instead of VFS for this
153 return sp_document_new(uri, TRUE);
154 }
155 gchar * buffer = _load_uri(uri);
156 if (buffer == NULL) {
157 g_warning("Error: Could not open file '%s' with VFS\n", uri);
158 return NULL;
159 }
160 SPDocument * doc = sp_document_new_from_mem(buffer, strlen(buffer), 1);
162 g_free(buffer);
163 return doc;
164 #else
165 return sp_document_new (uri, TRUE);
166 #endif
167 }
169 /**
170 \return None
171 \brief This is the function that does all of the SVG saves in
172 Inkscape. It detects whether it should do a Inkscape
173 namespace save internally.
174 \param mod Extension to use.
175 \param doc Document to save.
176 \param uri The filename to save the file to.
178 This function first checks its parameters, and makes sure that
179 we're getting good data. It also checks the module ID of the
180 incoming module to figure out whether this save should include
181 the Inkscape namespace stuff or not. The result of that comparison
182 is stored in the spns variable.
184 If there is not to be Inkscape name spaces a new document is created
185 without. (I think, I'm not sure on this code)
187 All of the internally referenced imageins are also set to relative
188 paths in the file. And the file is saved.
190 This really needs to be fleshed out more, but I don't quite understand
191 all of this code. I just stole it.
192 */
193 void
194 Svg::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
195 {
196 g_return_if_fail(doc != NULL);
197 g_return_if_fail(filename != NULL);
199 gchar *save_path = g_path_get_dirname(filename);
201 bool const spns = ( !mod->get_id()
202 || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)
203 || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVGZ_INKSCAPE));
205 Inkscape::XML::Document *rdoc = NULL;
206 Inkscape::XML::Node *repr = NULL;
207 if (spns) {
208 repr = sp_document_repr_root (doc);
209 } else {
210 rdoc = sp_repr_document_new ("svg:svg");
211 repr = rdoc->root();
212 repr = sp_document_root (doc)->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD);
213 }
215 if (!sp_repr_save_rebased_file(repr->document(), filename, SP_SVG_NS_URI,
216 doc->base, filename)) {
217 throw Inkscape::Extension::Output::save_failed();
218 }
220 if (!spns) {
221 Inkscape::GC::release(rdoc);
222 }
224 g_free(save_path);
226 return;
227 }
229 } } } /* namespace inkscape, module, implementation */
231 /*
232 Local Variables:
233 mode:c++
234 c-file-style:"stroustrup"
235 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
236 indent-tabs-mode:nil
237 fill-column:99
238 End:
239 */
240 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :