Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
stock-items.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Stock-items
4 *
5 * Stock Item management code
6 *
7 * Authors:
8 * John Cliff <simarilius@yahoo.com>
9 * Jon A. Cruz <jon@joncruz.org>
10 * Abhishek Sharma
11 *
12 * Copyright 2004 John Cliff
13 *
14 *
15 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
16 */
17
18#include "stock-items.h"
19
20#include <cstring>
21#include <glibmm/fileutils.h>
22
23#include "document.h"
24#include "inkscape.h"
25
26#include "io/resource.h"
28#include "object/sp-gradient.h"
29#include "object/sp-pattern.h"
30#include "object/sp-marker.h"
31#include "object/sp-defs.h"
32#include "util/static-doc.h"
33
35{
36 using namespace Inkscape::IO::Resource;
37 auto files = get_filenames(SYSTEM, PAINT, {".svg"});
38 auto share = get_filenames(SHARED, PAINT, {".svg"});
39 auto user = get_filenames(USER, PAINT, {".svg"});
40 files.insert(files.end(), user.begin(), user.end());
41 files.insert(files.end(), share.begin(), share.end());
42 for (auto const &file : files) {
43 if (Glib::file_test(file, Glib::FileTest::IS_REGULAR)) {
44 if (auto doc = SPDocument::createNewDoc(file.c_str(), false)) {
45 doc->ensureUpToDate(); // update, so patterns referencing clippaths render properly
46 documents.push_back(std::move(doc));
47 } else {
48 g_warning("File %s not loaded.", file.c_str());
49 }
50 }
51 }
52}
53
54std::vector<SPDocument *> StockPaintDocuments::get_paint_documents(std::function<bool (SPDocument *)> const &filter)
55{
56 std::vector<SPDocument *> out;
57
58 for (auto const &doc : documents) {
59 if (filter(doc.get())) {
60 out.push_back(doc.get());
61 }
62 }
63
64 return out;
65}
66
67static std::unique_ptr<SPDocument> load_paint_doc(char const *basename, Inkscape::IO::Resource::Type type = Inkscape::IO::Resource::PAINT)
68{
69 using namespace Inkscape::IO::Resource;
70
71 for (Domain const domain : {SYSTEM, CREATE}) {
72 auto const filename = get_path_string(domain, type, basename);
73 if (Glib::file_test(filename, Glib::FileTest::IS_REGULAR)) {
74 if (auto doc = SPDocument::createNewDoc(filename.c_str(), false)) {
75 doc->ensureUpToDate();
76 return doc;
77 }
78 }
79 }
80
81 return nullptr;
82}
83
84// FIXME: these should be merged with the icon loading code so they
85// can share a common file/doc cache. This function should just
86// take the dir to look in, and the file to check for, and cache
87// against that, rather than the existing copy/paste code seen here.
88
89static SPObject *sp_marker_load_from_svg(char const *name, SPDocument *current_doc)
90{
91 if (!current_doc) {
92 return nullptr;
93 }
94
95 // Try to load from document.
96 auto const doc = Inkscape::Util::cache_static_doc([] { return load_paint_doc("markers.svg", Inkscape::IO::Resource::MARKERS); });
97 if (!doc) {
98 return nullptr;
99 }
100
101 // Get the object we want.
102 auto obj = doc->getObjectById(name);
103 if (!is<SPMarker>(obj)) {
104 return nullptr;
105 }
106
107 auto defs = current_doc->getDefs();
108 auto xml_doc = current_doc->getReprDoc();
109 auto repr = obj->getRepr()->duplicate(xml_doc);
110 defs->getRepr()->addChild(repr, nullptr);
111 auto copied = current_doc->getObjectByRepr(repr);
113
114 return copied;
115}
116
117static SPObject* sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc, SPDocument* source_doc) {
118 if (!current_doc || !source_doc) {
119 return nullptr;
120 }
121 // Try to load from document
122 // Get the pattern we want
123 if (auto pattern = cast<SPPattern>(source_doc->getObjectById(name))) {
124 return sp_copy_resource(pattern, current_doc);
125 }
126 return nullptr;
127}
128
129static SPObject *sp_gradient_load_from_svg(char const *name, SPDocument *current_doc)
130{
131 if (!current_doc) {
132 return nullptr;
133 }
134
135 // Try to load from document.
136 auto const doc = Inkscape::Util::cache_static_doc([] { return load_paint_doc("gradients.svg"); });
137 if (!doc) {
138 return nullptr;
139 }
140
141 // Get the object we want.
142 auto obj = doc->getObjectById(name);
143 if (!is<SPGradient>(obj)) {
144 return nullptr;
145 }
146
147 auto defs = current_doc->getDefs();
148 auto xml_doc = current_doc->getReprDoc();
149 auto repr = obj->getRepr()->duplicate(xml_doc);
150 defs->getRepr()->addChild(repr, nullptr);
151 auto copied = current_doc->getObjectByRepr(repr);
153
154 return copied;
155}
156
157// get_stock_item returns a pointer to an instance of the desired stock object in the current doc
158// if necessary it will import the object. Copes with name clashes through use of the inkscape:stockid property
159// This should be set to be the same as the id in the library file.
160
161SPObject *get_stock_item(gchar const *urn, bool stock, SPDocument* stock_doc)
162{
163 g_assert(urn != nullptr);
164
165 /* check its an inkscape URN */
166 if (!strncmp (urn, "urn:inkscape:", 13)) {
167
168 gchar const *e = urn + 13;
169 int a = 0;
170 gchar * name = g_strdup(e);
171 gchar *name_p = name;
172 while (*name_p != ':' && *name_p != '\0'){
173 name_p++;
174 a++;
175 }
176
177 if (*name_p ==':') {
178 name_p++;
179 }
180
181 gchar * base = g_strndup(e, a);
182
183 SPDocument *doc = SP_ACTIVE_DOCUMENT;
184 SPDefs *defs = doc->getDefs();
185 if (!defs) {
186 g_free(base);
187 return nullptr;
188 }
189 SPObject *object = nullptr;
190 if (!strcmp(base, "marker") && !stock) {
191 for (auto& child: defs->children)
192 {
193 if (child.getRepr()->attribute("inkscape:stockid") &&
194 !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
195 is<SPMarker>(&child))
196 {
197 object = &child;
198 }
199 }
200 }
201 else if (!strcmp(base,"pattern") && !stock) {
202 for (auto& child: defs->children)
203 {
204 if (child.getRepr()->attribute("inkscape:stockid") &&
205 !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
206 is<SPPattern>(&child))
207 {
208 object = &child;
209 }
210 }
211 }
212 else if (!strcmp(base,"gradient") && !stock) {
213 for (auto& child: defs->children)
214 {
215 if (child.getRepr()->attribute("inkscape:stockid") &&
216 !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
217 is<SPGradient>(&child))
218 {
219 object = &child;
220 }
221 }
222 }
223
224 if (object == nullptr) {
225
226 if (!strcmp(base, "marker")) {
227 object = sp_marker_load_from_svg(name_p, doc);
228 }
229 else if (!strcmp(base, "pattern")) {
230 object = sp_pattern_load_from_svg(name_p, doc, stock_doc);
231 if (object) {
232 object->getRepr()->setAttribute("inkscape:collect", "always");
233 }
234 }
235 else if (!strcmp(base, "gradient")) {
236 object = sp_gradient_load_from_svg(name_p, doc);
237 }
238 }
239
240 g_free(base);
241 g_free(name);
242
243 if (object) {
244 object->setAttribute("inkscape:isstock", "true");
245 }
246
247 return object;
248 }
249
250 else {
251
252 SPDocument *doc = SP_ACTIVE_DOCUMENT;
253 SPObject *object = doc->getObjectById(urn);
254
255 return object;
256 }
257}
258
259/*
260 Local Variables:
261 mode:c++
262 c-file-style:"stroustrup"
263 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
264 indent-tabs-mode:nil
265 fill-column:99
266 End:
267*/
268// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
Typed SVG document implementation.
Definition document.h:101
SPObject * getObjectById(std::string const &id) const
SPDefs * getDefs()
Return the main defs object for the document.
Definition document.cpp:247
static std::unique_ptr< SPDocument > createNewDoc(char const *filename, bool keepalive, bool make_new=false, SPDocument *parent=nullptr)
Fetches document from filename, or creates new, if NULL; public document appears in document list.
Definition document.cpp:659
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:211
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
ChildrenList children
Definition sp-object.h:907
std::vector< SPDocument * > get_paint_documents(std::function< bool(SPDocument *)> const &filter)
std::vector< std::unique_ptr< SPDocument > > documents
Definition stock-items.h:34
SPObject * sp_copy_resource(const SPObject *source, SPDocument *dest_document)
Copy source resource form one document into another destination document.
static R & release(R &r)
Decrements the reference count of a anchored object.
SPDocument * cache_static_doc(F &&f)
Wrapper for a static SPDocument to ensure it is destroyed early enough.
Definition static-doc.h:27
Ocnode * child[8]
Definition quantize.cpp:33
Inkscape::IO::Resource - simple resource API.
SVG <pattern> implementation.
static SPObject * sp_marker_load_from_svg(char const *name, SPDocument *current_doc)
static SPObject * sp_gradient_load_from_svg(char const *name, SPDocument *current_doc)
SPObject * get_stock_item(gchar const *urn, bool stock, SPDocument *stock_doc)
static SPObject * sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc, SPDocument *source_doc)
static std::unique_ptr< SPDocument > load_paint_doc(char const *basename, Inkscape::IO::Resource::Type type=Inkscape::IO::Resource::PAINT)
TODO: insert short description here.
Document * duplicate(Document *doc) const override=0
Create a duplicate of this node.
Glib::ustring name
Definition toolbars.cpp:55