1 /*
2 * Stock-items
3 *
4 * Stock Item management code
5 *
6 * Authors:
7 * John Cliff <simarilius@yahoo.com>
8 * Jon A. Cruz <jon@joncruz.org>
9 * Abhishek Sharma
10 *
11 * Copyright 2004 John Cliff
12 *
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 */
17 #define noSP_SS_VERBOSE
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 #include "path-prefix.h"
25 #include <xml/repr.h>
26 #include "sp-gradient.h"
27 #include "document-private.h"
28 #include "sp-pattern.h"
29 #include "marker.h"
30 #include "desktop-handles.h"
31 #include "inkscape.h"
33 #include "io/sys.h"
38 static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc);
39 static SPObject *sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc);
40 static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc);
43 // FIXME: these should be merged with the icon loading code so they
44 // can share a common file/doc cache. This function should just
45 // take the dir to look in, and the file to check for, and cache
46 // against that, rather than the existing copy/paste code seen here.
48 static SPObject * sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc)
49 {
50 static SPDocument *doc = NULL;
51 static unsigned int edoc = FALSE;
52 if (!current_doc) {
53 return NULL;
54 }
55 /* Try to load from document */
56 if (!edoc && !doc) {
57 gchar *markers = g_build_filename(INKSCAPE_MARKERSDIR, "/markers.svg", NULL);
58 if (Inkscape::IO::file_test(markers, G_FILE_TEST_IS_REGULAR)) {
59 doc = SPDocument::createNewDoc(markers, FALSE);
60 }
61 g_free(markers);
62 if (doc) {
63 doc->ensureUpToDate();
64 } else {
65 edoc = TRUE;
66 }
67 }
68 if (!edoc && doc) {
69 /* Get the marker we want */
70 SPObject *object = doc->getObjectById(name);
71 if (object && SP_IS_MARKER(object)) {
72 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc);
73 Inkscape::XML::Document *xml_doc = current_doc->getReprDoc();
74 Inkscape::XML::Node *mark_repr = SP_OBJECT_REPR(object)->duplicate(xml_doc);
75 SP_OBJECT_REPR(defs)->addChild(mark_repr, NULL);
76 SPObject *cloned_item = current_doc->getObjectByRepr(mark_repr);
77 Inkscape::GC::release(mark_repr);
78 return cloned_item;
79 }
80 }
81 return NULL;
82 }
85 static SPObject *
86 sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc)
87 {
88 static SPDocument *doc = NULL;
89 static unsigned int edoc = FALSE;
90 if (!current_doc) {
91 return NULL;
92 }
93 /* Try to load from document */
94 if (!edoc && !doc) {
95 gchar *patterns = g_build_filename(INKSCAPE_PATTERNSDIR, "/patterns.svg", NULL);
96 if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) {
97 doc = SPDocument::createNewDoc(patterns, FALSE);
98 }
99 if (!doc) {
100 gchar *patterns = g_build_filename(CREATE_PATTERNSDIR, "/patterns.svg", NULL);
101 if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) {
102 doc = SPDocument::createNewDoc(patterns, FALSE);
103 }
104 g_free(patterns);
105 if (doc) {
106 doc->ensureUpToDate();
107 } else {
108 edoc = TRUE;
109 }
110 }
111 }
112 if (!edoc && doc) {
113 /* Get the pattern we want */
114 SPObject *object = doc->getObjectById(name);
115 if (object && SP_IS_PATTERN(object)) {
116 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc);
117 Inkscape::XML::Document *xml_doc = current_doc->getReprDoc();
118 Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate(xml_doc);
119 SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL);
120 Inkscape::GC::release(pat_repr);
121 return object;
122 }
123 }
124 return NULL;
125 }
128 static SPObject *
129 sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc)
130 {
131 static SPDocument *doc = NULL;
132 static unsigned int edoc = FALSE;
133 if (!current_doc) {
134 return NULL;
135 }
136 /* Try to load from document */
137 if (!edoc && !doc) {
138 gchar *gradients = g_build_filename(INKSCAPE_GRADIENTSDIR, "/gradients.svg", NULL);
139 if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) {
140 doc = SPDocument::createNewDoc(gradients, FALSE);
141 }
142 if (!doc) {
143 gchar *gradients = g_build_filename(CREATE_GRADIENTSDIR, "/gradients.svg", NULL);
144 if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) {
145 doc = SPDocument::createNewDoc(gradients, FALSE);
146 }
147 g_free(gradients);
148 if (doc) {
149 doc->ensureUpToDate();
150 } else {
151 edoc = TRUE;
152 }
153 }
154 }
155 if (!edoc && doc) {
156 /* Get the gradient we want */
157 SPObject *object = doc->getObjectById(name);
158 if (object && SP_IS_GRADIENT(object)) {
159 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc);
160 Inkscape::XML::Document *xml_doc = current_doc->getReprDoc();
161 Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate(xml_doc);
162 SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL);
163 Inkscape::GC::release(pat_repr);
164 return object;
165 }
166 }
167 return NULL;
168 }
170 // get_stock_item returns a pointer to an instance of the desired stock object in the current doc
171 // if necessary it will import the object. Copes with name clashes through use of the inkscape:stockid property
172 // This should be set to be the same as the id in the libary file.
174 SPObject *get_stock_item(gchar const *urn)
175 {
176 g_assert(urn != NULL);
178 /* check its an inkscape URN */
179 if (!strncmp (urn, "urn:inkscape:", 13)) {
181 gchar const *e = urn + 13;
182 int a = 0;
183 gchar * name = g_strdup(e);
184 gchar *name_p = name;
185 while (*name_p != ':' && *name_p != '\0'){
186 name_p++;
187 a++;
188 }
190 if (*name_p ==':') {
191 name_p++;
192 }
194 gchar * base = g_strndup(e, a);
196 SPDesktop *desktop = inkscape_active_desktop();
197 SPDocument *doc = sp_desktop_document(desktop);
198 SPDefs *defs = reinterpret_cast<SPDefs *>(SP_DOCUMENT_DEFS(doc));
200 SPObject *object = NULL;
201 if (!strcmp(base, "marker")) {
202 for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
203 {
204 if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") &&
205 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
206 SP_IS_MARKER(child))
207 {
208 object = child;
209 }
210 }
212 }
213 else if (!strcmp(base,"pattern")) {
214 for ( SPObject *child = defs->firstChild() ; child; child = child->getNext() )
215 {
216 if (child->getRepr()->attribute("inkscape:stockid") &&
217 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
218 SP_IS_PATTERN(child))
219 {
220 object = child;
221 }
222 }
224 }
225 else if (!strcmp(base,"gradient")) {
226 for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
227 {
228 if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") &&
229 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
230 SP_IS_GRADIENT(child))
231 {
232 object = child;
233 }
234 }
236 }
238 if (object == NULL) {
240 if (!strcmp(base, "marker")) {
241 object = sp_marker_load_from_svg(name_p, doc);
242 }
243 else if (!strcmp(base, "pattern")) {
244 object = sp_pattern_load_from_svg(name_p, doc);
245 }
246 else if (!strcmp(base, "gradient")) {
247 object = sp_gradient_load_from_svg(name_p, doc);
248 }
249 }
251 g_free(base);
252 g_free(name);
254 return object;
255 }
257 else {
259 SPDesktop *desktop = inkscape_active_desktop();
260 SPDocument *doc = sp_desktop_document(desktop);
261 SPObject *object = doc->getObjectById(urn);
263 return object;
264 }
265 }
267 /*
268 Local Variables:
269 mode:c++
270 c-file-style:"stroustrup"
271 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
272 indent-tabs-mode:nil
273 fill-column:99
274 End:
275 */
276 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :