Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / helper / stock-items.cpp
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;
128 static SPObject *
129 sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc)
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;
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)
176     g_assert(urn != NULL);
177     
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         }
189         
190         if (*name_p ==':') {
191             name_p++;
192         }
193         
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             }
211             
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             }
223             
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             }
235             
236         }
237         
238         if (object == NULL) {
239             
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         }
250         
251         g_free(base);
252         g_free(name);
253         
254         return object;
255     }
256     
257     else {
258         
259         SPDesktop *desktop = inkscape_active_desktop();
260         SPDocument *doc = sp_desktop_document(desktop);
261         SPObject *object = doc->getObjectById(urn);
263         return object;
264     }
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 :