1 #define __INK_STOCK_ITEMS__
3 /*
4 * Stock-items
5 *
6 * Stock Item management code
7 *
8 * Authors:
9 * John Cliff <simarilius@yahoo.com>
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-fns.h"
27 #include "document-private.h"
28 #include "sp-pattern.h"
29 #include "sp-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 = sp_document_new(markers, FALSE);
60 }
61 g_free(markers);
62 if (doc) {
63 sp_document_ensure_up_to_date(doc);
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::Node *mark_repr = SP_OBJECT_REPR(object)->duplicate();
74 SP_OBJECT_REPR(defs)->addChild(mark_repr, NULL);
75 SPObject *cloned_item = current_doc->getObjectByRepr(mark_repr);
76 Inkscape::GC::release(mark_repr);
77 return cloned_item;
78 }
79 }
80 return NULL;
81 }
84 static SPObject *
85 sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc)
86 {
87 static SPDocument *doc = NULL;
88 static unsigned int edoc = FALSE;
89 if (!current_doc) {
90 return NULL;
91 }
92 /* Try to load from document */
93 if (!edoc && !doc) {
94 gchar *patterns = g_build_filename(INKSCAPE_PATTERNSDIR, "/patterns.svg", NULL);
95 if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) {
96 doc = sp_document_new(patterns, FALSE);
97 }
98 g_free(patterns);
99 if (doc) {
100 sp_document_ensure_up_to_date(doc);
101 } else {
102 edoc = TRUE;
103 }
104 }
105 if (!edoc && doc) {
106 /* Get the pattern we want */
107 SPObject *object = doc->getObjectById(name);
108 if (object && SP_IS_PATTERN(object)) {
109 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc);
110 Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate();
111 SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL);
112 Inkscape::GC::release(pat_repr);
113 return object;
114 }
115 }
116 return NULL;
117 }
120 static SPObject *
121 sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc)
122 {
123 static SPDocument *doc = NULL;
124 static unsigned int edoc = FALSE;
125 if (!current_doc) {
126 return NULL;
127 }
128 /* Try to load from document */
129 if (!edoc && !doc) {
130 gchar *gradients = g_build_filename(INKSCAPE_GRADIENTSDIR, "/gradients.svg", NULL);
131 if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) {
132 doc = sp_document_new(gradients, FALSE);
133 }
134 g_free(gradients);
135 if (doc) {
136 sp_document_ensure_up_to_date(doc);
137 } else {
138 edoc = TRUE;
139 }
140 }
141 if (!edoc && doc) {
142 /* Get the gradient we want */
143 SPObject *object = doc->getObjectById(name);
144 if (object && SP_IS_GRADIENT(object)) {
145 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(current_doc);
146 Inkscape::XML::Node *pat_repr = SP_OBJECT_REPR(object)->duplicate();
147 SP_OBJECT_REPR(defs)->addChild(pat_repr, NULL);
148 Inkscape::GC::release(pat_repr);
149 return object;
150 }
151 }
152 return NULL;
153 }
155 // get_stock_item returns a pointer to an instance of the desired stock object in the current doc
156 // if necessary it will import the object. Copes with name clashes through use of the inkscape:stockid property
157 // This should be set to be the same as the id in the libary file.
159 SPObject *get_stock_item(gchar const *urn)
160 {
161 g_assert(urn != NULL);
163 /* check its an inkscape URN */
164 if (!strncmp (urn, "urn:inkscape:", 13)) {
166 gchar const *e = urn + 13;
167 int a = 0;
168 gchar * name = g_strdup(e);
169 gchar *name_p = name;
170 while (*name_p != ':' && *name_p != '\0'){
171 name_p++;
172 a++;
173 }
175 if (*name_p ==':') {
176 name_p++;
177 }
179 gchar * base = g_strndup(e, a);
181 SPDesktop *desktop = inkscape_active_desktop();
182 SPDocument *doc = SP_DT_DOCUMENT(desktop);
183 SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS(doc);
185 SPObject *object = NULL;
186 if (!strcmp(base, "marker")) {
187 for (SPObject *child = sp_object_first_child(SP_OBJECT(defs));
188 child != NULL;
189 child = SP_OBJECT_NEXT(child))
190 {
191 if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") &&
192 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
193 SP_IS_MARKER(child))
194 {
195 object = child;
196 }
197 }
199 }
200 else if (!strcmp(base,"pattern")) {
201 for (SPObject *child = sp_object_first_child(SP_OBJECT(defs)) ;
202 child != NULL;
203 child = SP_OBJECT_NEXT(child) )
204 {
205 if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") &&
206 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
207 SP_IS_PATTERN(child))
208 {
209 object = child;
210 }
211 }
213 }
214 else if (!strcmp(base,"gradient")) {
215 for (SPObject *child = sp_object_first_child(SP_OBJECT(defs));
216 child != NULL;
217 child = SP_OBJECT_NEXT(child))
218 {
219 if (SP_OBJECT_REPR(child)->attribute("inkscape:stockid") &&
220 !strcmp(name_p, SP_OBJECT_REPR(child)->attribute("inkscape:stockid")) &&
221 SP_IS_GRADIENT(child))
222 {
223 object = child;
224 }
225 }
227 }
229 if (object == NULL) {
231 if (!strcmp(base, "marker")) {
232 object = sp_marker_load_from_svg(name_p, doc);
233 }
234 else if (!strcmp(base, "pattern")) {
235 object = sp_pattern_load_from_svg(name_p, doc);
236 }
237 else if (!strcmp(base, "gradient")) {
238 object = sp_gradient_load_from_svg(name_p, doc);
239 }
240 }
242 g_free(base);
243 g_free(name);
245 return object;
246 }
248 else {
250 SPDesktop *desktop = inkscape_active_desktop();
251 SPDocument *doc = SP_DT_DOCUMENT(desktop);
252 SPObject *object = doc->getObjectById(urn);
254 return object;
255 }
256 }
258 /*
259 Local Variables:
260 mode:c++
261 c-file-style:"stroustrup"
262 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
263 indent-tabs-mode:nil
264 fill-column:99
265 End:
266 */
267 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :