diff options
Diffstat (limited to 'src/helper/stock-items.cpp')
-rw-r--r-- | src/helper/stock-items.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/helper/stock-items.cpp b/src/helper/stock-items.cpp new file mode 100644 index 0000000..ca96d6b --- /dev/null +++ b/src/helper/stock-items.cpp @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Stock-items + * + * Stock Item management code + * + * Authors: + * John Cliff <simarilius@yahoo.com> + * Jon A. Cruz <jon@joncruz.org> + * Abhishek Sharma + * + * Copyright 2004 John Cliff + * + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#define noSP_SS_VERBOSE + +#include <cstring> + +#include "path-prefix.h" + +#include <xml/repr.h> +#include "inkscape.h" + +#include "io/sys.h" +#include "stock-items.h" + +#include "object/sp-gradient.h" +#include "object/sp-pattern.h" +#include "object/sp-marker.h" +#include "object/sp-defs.h" + +static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc); +static SPObject *sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc); +static SPObject *sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc); + + +// FIXME: these should be merged with the icon loading code so they +// can share a common file/doc cache. This function should just +// take the dir to look in, and the file to check for, and cache +// against that, rather than the existing copy/paste code seen here. + +static SPObject * sp_marker_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = nullptr; + static unsigned int edoc = FALSE; + if (!current_doc) { + return nullptr; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *markers = g_build_filename(INKSCAPE_MARKERSDIR, "/markers.svg", NULL); + if (Inkscape::IO::file_test(markers, G_FILE_TEST_IS_REGULAR)) { + doc = SPDocument::createNewDoc(markers, FALSE); + } + g_free(markers); + if (doc) { + doc->ensureUpToDate(); + } else { + edoc = TRUE; + } + } + if (!edoc && doc) { + /* Get the marker we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_MARKER(object)) { + SPDefs *defs = current_doc->getDefs(); + Inkscape::XML::Document *xml_doc = current_doc->getReprDoc(); + Inkscape::XML::Node *mark_repr = object->getRepr()->duplicate(xml_doc); + defs->getRepr()->addChild(mark_repr, nullptr); + SPObject *cloned_item = current_doc->getObjectByRepr(mark_repr); + Inkscape::GC::release(mark_repr); + return cloned_item; + } + } + return nullptr; +} + + +static SPObject * +sp_pattern_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = nullptr; + static unsigned int edoc = FALSE; + if (!current_doc) { + return nullptr; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *patterns = g_build_filename(INKSCAPE_PAINTDIR, "/patterns.svg", NULL); + if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) { + doc = SPDocument::createNewDoc(patterns, FALSE); + } + if (!doc) { + gchar *patterns = g_build_filename(CREATE_PAINTDIR, "/patterns.svg", NULL); + if (Inkscape::IO::file_test(patterns, G_FILE_TEST_IS_REGULAR)) { + doc = SPDocument::createNewDoc(patterns, FALSE); + } + g_free(patterns); + if (doc) { + doc->ensureUpToDate(); + } else { + edoc = TRUE; + } + } + } + if (!edoc && doc) { + /* Get the pattern we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_PATTERN(object)) { + SPDefs *defs = current_doc->getDefs(); + Inkscape::XML::Document *xml_doc = current_doc->getReprDoc(); + Inkscape::XML::Node *pat_repr = object->getRepr()->duplicate(xml_doc); + defs->getRepr()->addChild(pat_repr, nullptr); + Inkscape::GC::release(pat_repr); + return object; + } + } + return nullptr; +} + + +static SPObject * +sp_gradient_load_from_svg(gchar const *name, SPDocument *current_doc) +{ + static SPDocument *doc = nullptr; + static unsigned int edoc = FALSE; + if (!current_doc) { + return nullptr; + } + /* Try to load from document */ + if (!edoc && !doc) { + gchar *gradients = g_build_filename(INKSCAPE_PAINTDIR, "/gradients.svg", NULL); + if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) { + doc = SPDocument::createNewDoc(gradients, FALSE); + } + if (!doc) { + gchar *gradients = g_build_filename(CREATE_PAINTDIR, "/gradients.svg", NULL); + if (Inkscape::IO::file_test(gradients, G_FILE_TEST_IS_REGULAR)) { + doc = SPDocument::createNewDoc(gradients, FALSE); + } + g_free(gradients); + if (doc) { + doc->ensureUpToDate(); + } else { + edoc = TRUE; + } + } + } + if (!edoc && doc) { + /* Get the gradient we want */ + SPObject *object = doc->getObjectById(name); + if (object && SP_IS_GRADIENT(object)) { + SPDefs *defs = current_doc->getDefs(); + Inkscape::XML::Document *xml_doc = current_doc->getReprDoc(); + Inkscape::XML::Node *pat_repr = object->getRepr()->duplicate(xml_doc); + defs->getRepr()->addChild(pat_repr, nullptr); + Inkscape::GC::release(pat_repr); + return object; + } + } + return nullptr; +} + +// get_stock_item returns a pointer to an instance of the desired stock object in the current doc +// if necessary it will import the object. Copes with name clashes through use of the inkscape:stockid property +// This should be set to be the same as the id in the library file. + +SPObject *get_stock_item(gchar const *urn, gboolean stock) +{ + g_assert(urn != nullptr); + + /* check its an inkscape URN */ + if (!strncmp (urn, "urn:inkscape:", 13)) { + + gchar const *e = urn + 13; + int a = 0; + gchar * name = g_strdup(e); + gchar *name_p = name; + while (*name_p != ':' && *name_p != '\0'){ + name_p++; + a++; + } + + if (*name_p ==':') { + name_p++; + } + + gchar * base = g_strndup(e, a); + + SPDocument *doc = SP_ACTIVE_DOCUMENT; + SPDefs *defs = doc->getDefs(); + if (!defs) { + g_free(base); + return nullptr; + } + SPObject *object = nullptr; + if (!strcmp(base, "marker") && !stock) { + for (auto& child: defs->children) + { + if (child.getRepr()->attribute("inkscape:stockid") && + !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) && + SP_IS_MARKER(&child)) + { + object = &child; + } + } + } + else if (!strcmp(base,"pattern") && !stock) { + for (auto& child: defs->children) + { + if (child.getRepr()->attribute("inkscape:stockid") && + !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) && + SP_IS_PATTERN(&child)) + { + object = &child; + } + } + } + else if (!strcmp(base,"gradient") && !stock) { + for (auto& child: defs->children) + { + if (child.getRepr()->attribute("inkscape:stockid") && + !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) && + SP_IS_GRADIENT(&child)) + { + object = &child; + } + } + } + + if (object == nullptr) { + + if (!strcmp(base, "marker")) { + object = sp_marker_load_from_svg(name_p, doc); + } + else if (!strcmp(base, "pattern")) { + object = sp_pattern_load_from_svg(name_p, doc); + } + else if (!strcmp(base, "gradient")) { + object = sp_gradient_load_from_svg(name_p, doc); + } + } + + g_free(base); + g_free(name); + + if (object) { + object->setAttribute("inkscape:isstock", "true"); + } + + return object; + } + + else { + + SPDocument *doc = SP_ACTIVE_DOCUMENT; + SPObject *object = doc->getObjectById(urn); + + return object; + } +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |