1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2008 Authors:
4  *   Ted Gould <ted@gould.cx>
5  *
6  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
7  */
8 
9 #include "filter.h"
10 
11 #include "io/sys.h"
12 #include "io/resource.h"
13 #include "io/stream/inkscapestream.h"
14 
15 /* Directory includes */
16 #include "path-prefix.h"
17 #include "inkscape.h"
18 
19 /* Extension */
20 #include "extension/extension.h"
21 #include "extension/system.h"
22 
23 /* System includes */
24 #include <glibmm/i18n.h>
25 #include <glibmm/fileutils.h>
26 
27 using namespace Inkscape::IO::Resource;
28 
29 namespace Inkscape {
30 namespace Extension {
31 namespace Internal {
32 namespace Filter {
33 
34 void
filters_load_file(Glib::ustring filename,gchar * menuname)35 filters_load_file (Glib::ustring filename, gchar * menuname)
36 {
37     Inkscape::XML::Document *doc = sp_repr_read_file(filename.c_str(), INKSCAPE_EXTENSION_URI);
38 	if (doc == nullptr) {
39 		g_warning("File (%s) is not parseable as XML.  Ignored.", filename.c_str());
40 		return;
41 	}
42 
43 	Inkscape::XML::Node * root = doc->root();
44 	if (strcmp(root->name(), "svg:svg")) {
45 		Inkscape::GC::release(doc);
46 		g_warning("File (%s) is not SVG.  Ignored.", filename.c_str());
47 		return;
48 	}
49 
50 	for (Inkscape::XML::Node * child = root->firstChild();
51 			child != nullptr; child = child->next()) {
52 		if (!strcmp(child->name(), "svg:defs")) {
53 			for (Inkscape::XML::Node * defs = child->firstChild();
54 					defs != nullptr; defs = defs->next()) {
55 				if (!strcmp(defs->name(), "svg:filter")) {
56                                     Filter::filters_load_node(defs, menuname);
57 				} // oh!  a filter
58 			} //defs
59 		} // is defs
60 	} // children of root
61 
62 	Inkscape::GC::release(doc);
63 	return;
64 }
65 
filters_all_files()66 void Filter::filters_all_files()
67 {
68     for(auto &filename: get_filenames(USER, FILTERS, {".svg"})) {
69         filters_load_file(filename, _("Personal"));
70     }
71     for(auto &filename: get_filenames(SYSTEM, FILTERS, {".svg"})) {
72         filters_load_file(filename, _("Bundled"));
73     }
74 }
75 
76 
77 #include "extension/internal/clear-n_.h"
78 
79 class mywriter : public Inkscape::IO::BasicWriter {
80 	Glib::ustring _str;
81 public:
82 	void close() override;
83 	void flush() override;
84 	void put (char ch) override;
c_str()85 	gchar const * c_str () { return _str.c_str(); }
86 };
87 
close()88 void mywriter::close () { return; }
flush()89 void mywriter::flush () { return; }
put(char ch)90 void mywriter::put (char ch) { _str += ch; }
91 
92 
93 void
filters_load_node(Inkscape::XML::Node * node,gchar * menuname)94 Filter::filters_load_node (Inkscape::XML::Node *node, gchar * menuname)
95 {
96 	gchar const * label = node->attribute("inkscape:label");
97 	gchar const * menu = node->attribute("inkscape:menu");
98 	gchar const * menu_tooltip = node->attribute("inkscape:menu-tooltip");
99 	gchar const * id = node->attribute("id");
100 
101 	if (label == nullptr) {
102 		label = id;
103 	}
104 
105     // clang-format off
106 	gchar * xml_str = g_strdup_printf(
107         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
108             "<name>%s</name>\n"
109             "<id>org.inkscape.effect.filter.%s</id>\n"
110             "<effect>\n"
111                 "<object-type>all</object-type>\n"
112                 "<effects-menu>\n"
113                     "<submenu name=\"" N_("Filters") "\">\n"
114                         "<submenu name=\"%s\"/>\n"
115                     "</submenu>\n"
116                 "</effects-menu>\n"
117                 "<menu-tip>%s</menu-tip>\n"
118             "</effect>\n"
119         "</inkscape-extension>\n", label, id, menu? menu : menuname, menu_tooltip? menu_tooltip : label);
120     // clang-format on
121 
122 	// FIXME: Bad hack: since we pull out a single filter node out of SVG file and
123 	// serialize it, it loses the namespace declarations from the root, so we must provide
124 	// one right here for our inkscape attributes
125 	node->setAttribute("xmlns:inkscape", SP_INKSCAPE_NS_URI);
126 
127 	mywriter writer;
128 	sp_repr_write_stream(node, writer, 0, FALSE, g_quark_from_static_string("svg"), 0, 0);
129 
130     Inkscape::Extension::build_from_mem(xml_str, new Filter(g_strdup(writer.c_str())));
131 	g_free(xml_str);
132     return;
133 }
134 
135 }; /* namespace Filter */
136 }; /* namespace Internal */
137 }; /* namespace Extension */
138 }; /* namespace Inkscape */
139 
140