summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2008-04-26 04:22:42 +0000
committergouldtj <gouldtj@users.sourceforge.net>2008-04-26 04:22:42 +0000
commite90c2cad99eabd6f02978f4e2666a1fa228e93c9 (patch)
tree925f14d7c206dc2d9e411d809c1f7cfc72e85899 /src
parentDocumentation, always more :) (diff)
downloadinkscape-e90c2cad99eabd6f02978f4e2666a1fa228e93c9.tar.gz
inkscape-e90c2cad99eabd6f02978f4e2666a1fa228e93c9.zip
r19136@shi: ted | 2008-04-24 19:44:01 -0700
Basis for reading filters out of SVG files in system and personal directories. r19137@shi: ted | 2008-04-24 20:45:27 -0700 Removing a TODO r19138@shi: ted | 2008-04-24 20:55:50 -0700 Filling this out some. Now we're looking through the files and finding the filters in it. r19139@shi: ted | 2008-04-24 22:07:55 -0700 Changing to build filename, really amazing that it's worked before. r19140@shi: ted | 2008-04-24 22:43:57 -0700 My own crazy writer. Output streams are stupid C++-isms. char * works just fine. r19154@shi: ted | 2008-04-24 22:56:05 -0700 Cleaning up the XML transfer. Pretty happy with it now. r19155@shi: ted | 2008-04-24 23:00:11 -0700 Don't need to set up that string for translation because it's getting placed inside a structure that gets thrown gettext already. r19156@shi: ted | 2008-04-25 17:12:40 -0700 OMG! Stacking seems to be working. Now it's very easy to test the cooling on your CPU using Inkscape. That's going to have to be a feature in the release notes. r19166@shi: ted | 2008-04-25 21:00:34 -0700 Adding in filter-file.cpp (bzr r5522)
Diffstat (limited to 'src')
-rw-r--r--src/extension/init.cpp5
-rw-r--r--src/extension/internal/Makefile_insert1
-rw-r--r--src/extension/internal/filter/filter-all.cpp5
-rw-r--r--src/extension/internal/filter/filter-file.cpp165
-rw-r--r--src/extension/internal/filter/filter.cpp50
-rw-r--r--src/extension/internal/filter/filter.h9
-rw-r--r--src/extension/system.cpp2
-rw-r--r--src/path-prefix.h4
8 files changed, 234 insertions, 7 deletions
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index a1d88d7ec..649a65471 100644
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
@@ -320,7 +320,6 @@ build_module_from_dir(gchar const *dirname)
gchar *filename;
while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
-
if (strlen(filename) < strlen(SP_MODULE_EXTENSION)) {
continue;
}
@@ -329,12 +328,14 @@ build_module_from_dir(gchar const *dirname)
continue;
}
- gchar *pathname = g_strdup_printf("%s/%s", dirname, filename);
+ gchar *pathname = g_build_filename(dirname, filename, NULL);
build_from_file(pathname);
g_free(pathname);
}
g_dir_close(directory);
+
+ return;
}
diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert
index bca2b0a6d..73303ffca 100644
--- a/src/extension/internal/Makefile_insert
+++ b/src/extension/internal/Makefile_insert
@@ -140,6 +140,7 @@ extension_internal_libinternal_a_SOURCES = \
$(extension_internal_image_magick_sources) \
\
extension/internal/filter/filter-all.cpp \
+ extension/internal/filter/filter-file.cpp \
extension/internal/filter/filter.cpp \
extension/internal/filter/filter.h
diff --git a/src/extension/internal/filter/filter-all.cpp b/src/extension/internal/filter/filter-all.cpp
index 917730e2c..08bef9f74 100644
--- a/src/extension/internal/filter/filter-all.cpp
+++ b/src/extension/internal/filter/filter-all.cpp
@@ -70,6 +70,11 @@ Filter::filters_all (void )
Speckle::init();
Zebra::init();
+
+ /* This should always be last, don't put stuff below this
+ * line. */
+ Filter::filters_all_files();
+
return;
}
diff --git a/src/extension/internal/filter/filter-file.cpp b/src/extension/internal/filter/filter-file.cpp
new file mode 100644
index 000000000..e4f911843
--- /dev/null
+++ b/src/extension/internal/filter/filter-file.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2008 Authors:
+ * Ted Gould <ted@gould.cx>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "filter.h"
+
+#include "io/sys.h"
+#include "io/inkscapestream.h"
+
+/* Directory includes */
+#include "path-prefix.h"
+#include "inkscape.h"
+
+/* Extension */
+#include "extension/extension.h"
+#include "extension/system.h"
+
+/* System includes */
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+namespace Filter {
+
+void
+Filter::filters_all_files (void)
+{
+ filters_load_dir(INKSCAPE_FILTERDIR, _("Bundled"));
+ filters_load_dir(profile_path("filters"), _("Personal"));
+
+ return;
+}
+
+#define INKSCAPE_FILTER_FILE ".svg"
+
+void
+Filter::filters_load_dir (gchar * dirname, gchar * menuname)
+{
+ if (!dirname) {
+ g_warning(_("Null external module directory name. Filters will not be loaded."));
+ return;
+ }
+
+ if (!Glib::file_test(std::string(dirname), Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_DIR)) {
+ return;
+ }
+
+ GError *err;
+ GDir *directory = g_dir_open(dirname, 0, &err);
+ if (!directory) {
+ gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
+ g_warning(_("Modules directory (%s) is unavailable. External modules in that directory will not be loaded."), safeDir);
+ g_free(safeDir);
+ return;
+ }
+
+ gchar *filename;
+ while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
+ if (strlen(filename) < strlen(INKSCAPE_FILTER_FILE)) {
+ continue;
+ }
+
+ if (strcmp(INKSCAPE_FILTER_FILE, filename + (strlen(filename) - strlen(INKSCAPE_FILTER_FILE)))) {
+ continue;
+ }
+
+ gchar *pathname = g_build_filename(dirname, filename, NULL);
+ filters_load_file(pathname, menuname);
+ g_free(pathname);
+ }
+
+ g_dir_close(directory);
+
+ return;
+}
+
+void
+Filter::filters_load_file (gchar * filename, gchar * menuname)
+{
+ Inkscape::XML::Document *doc = sp_repr_read_file(filename, INKSCAPE_EXTENSION_URI);
+ if (doc == NULL) {
+ g_warning("File (%s) is not parseable as XML. Ignored.", filename);
+ return;
+ }
+
+ Inkscape::XML::Node * root = doc->root();
+ if (strcmp(root->name(), "svg:svg")) {
+ Inkscape::GC::release(doc);
+ g_warning("File (%s) is not SVG. Ignored.", filename);
+ return;
+ }
+
+ for (Inkscape::XML::Node * child = root->firstChild();
+ child != NULL; child = child->next()) {
+ if (!strcmp(child->name(), "svg:defs")) {
+ for (Inkscape::XML::Node * defs = child->firstChild();
+ defs != NULL; defs = defs->next()) {
+ if (!strcmp(defs->name(), "svg:filter")) {
+ filters_load_node(defs, menuname);
+ } // oh! a filter
+ } //defs
+ } // is defs
+ } // children of root
+
+ Inkscape::GC::release(doc);
+ return;
+}
+
+#include "extension/internal/clear-n_.h"
+
+class mywriter : public Inkscape::IO::BasicWriter {
+ Glib::ustring _str;
+public:
+ void close(void);
+ void flush(void);
+ void put (gunichar ch);
+ gchar const * c_str (void) { return _str.c_str(); }
+};
+
+void mywriter::close (void) { return; }
+void mywriter::flush (void) { return; }
+void mywriter::put (gunichar ch) { _str += ch; }
+
+
+void
+Filter::filters_load_node (Inkscape::XML::Node * node, gchar * menuname)
+{
+ gchar const * label = node->attribute("inkscape:label");
+ gchar const * id = node->attribute("id");
+
+ if (label == NULL) {
+ label = id;
+ }
+
+ gchar * xml_str = g_strdup_printf(
+ "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
+ "<name>%s</name>\n"
+ "<id>org.inkscape.effect.filter.%s</id>\n"
+ "<effect>\n"
+ "<object-type>all</object-type>\n"
+ "<effects-menu>\n"
+ "<submenu name=\"" N_("Filter") "\">\n"
+ "<submenu name=\"%s\"/>\n"
+ "</submenu>\n"
+ "</effects-menu>\n"
+ "</effect>\n"
+ "</inkscape-extension>\n", label, id, menuname);
+
+ mywriter writer;
+ sp_repr_write_stream(node, writer, 0, FALSE, g_quark_from_static_string("svg"), 0, 0);
+
+ Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(g_strdup(writer.c_str())));
+ g_free(xml_str);
+ return;
+}
+
+}; /* namespace Filter */
+}; /* namespace Internal */
+}; /* namespace Extension */
+}; /* namespace Inkscape */
+
diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp
index e87290ab4..b2a55b6e6 100644
--- a/src/extension/internal/filter/filter.cpp
+++ b/src/extension/internal/filter/filter.cpp
@@ -71,7 +71,7 @@ Filter::get_filter (Inkscape::Extension::Extension * ext) {
}
void
-Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc)
+Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar * srcGraphic, gchar * srcGraphicAlpha)
{
if (from == NULL) return;
@@ -82,6 +82,16 @@ Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Ink
//printf("Attribute List: %s\n", attr);
if (!strcmp(attr, "id")) continue; // nope, don't copy that one!
to->setAttribute(attr, from->attribute(attr));
+
+ if (!strcmp(attr, "in") || !strcmp(attr, "in2") || !strcmp(attr, "in3")) {
+ if (srcGraphic != NULL && !strcmp(from->attribute(attr), "SourceGraphic")) {
+ to->setAttribute(attr, srcGraphic);
+ }
+
+ if (srcGraphicAlpha != NULL && !strcmp(from->attribute(attr), "SourceAlpha")) {
+ to->setAttribute(attr, srcGraphicAlpha);
+ }
+ }
}
// for each child call recursively
@@ -92,12 +102,19 @@ Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Ink
Inkscape::XML::Node * to_child = doc->createElement(name.c_str());
to->appendChild(to_child);
- merge_filters(to_child, from_child, doc);
+ merge_filters(to_child, from_child, doc, srcGraphic, srcGraphicAlpha);
+
+ if (from_child == from->firstChild() && !strcmp("filter", from->name()) && srcGraphic != NULL && to_child->attribute("in") == NULL) {
+ to_child->setAttribute("in", srcGraphic);
+ }
}
return;
}
+#define FILTER_SRC_GRAPHIC "fbSourceGraphic"
+#define FILTER_SRC_GRAPHIC_ALPHA "fbSourceGraphicAlpha"
+
void
Filter::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache)
{
@@ -129,6 +146,35 @@ Filter::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *d
sp_repr_css_set_property(css, "filter", url.c_str());
sp_repr_css_set(node, css, "style");
+ } else {
+ if (strncmp(filter, "url(#", strlen("url(#")) || filter[strlen(filter) - 1] != ')') {
+ // This is not url(#id) -- we can't handle it
+ continue;
+ }
+
+ gchar * lfilter = g_strndup(filter + 5, strlen(filter) - 6);
+ Inkscape::XML::Node * filternode = NULL;
+ for (Inkscape::XML::Node * child = defsrepr->firstChild(); child != NULL; child = child->next()) {
+ if (!strcmp(lfilter, child->attribute("id"))) {
+ filternode = child;
+ break;
+ }
+ }
+ g_free(lfilter);
+
+ if (filternode == NULL) {
+ continue;
+ }
+
+ filternode->lastChild()->setAttribute("result", FILTER_SRC_GRAPHIC);
+
+ Inkscape::XML::Node * alpha = xmldoc->createElement("svg:feColorMatrix");
+ alpha->setAttribute("result", FILTER_SRC_GRAPHIC_ALPHA);
+ alpha->setAttribute("in", FILTER_SRC_GRAPHIC); // not required, but we're being explicit
+ alpha->setAttribute("values", "0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0");
+ filternode->appendChild(alpha);
+
+ merge_filters(filternode, get_filter(module)->root(), xmldoc, FILTER_SRC_GRAPHIC, FILTER_SRC_GRAPHIC_ALPHA);
}
}
diff --git a/src/extension/internal/filter/filter.h b/src/extension/internal/filter/filter.h
index 851beb833..28924988d 100644
--- a/src/extension/internal/filter/filter.h
+++ b/src/extension/internal/filter/filter.h
@@ -25,7 +25,7 @@ protected:
private:
Inkscape::XML::Document * get_filter (Inkscape::Extension::Extension * ext);
- void merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc);
+ void merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar * srcGraphic = NULL, gchar * srcGraphicAlpha = NULL);
public:
Filter();
@@ -38,6 +38,13 @@ public:
static void filter_init(gchar const * id, gchar const * name, gchar const * tip, gchar const * filter);
static void filters_all(void);
+
+ /* File loader related */
+ static void filters_all_files(void);
+ static void filters_load_dir(gchar * filename, gchar * menuname);
+ static void filters_load_file(gchar * filename, gchar * menuname);
+ static void filters_load_node(Inkscape::XML::Node * node, gchar * menuname);
+
};
}; /* namespace Filter */
diff --git a/src/extension/system.cpp b/src/extension/system.cpp
index d66655a51..cd70042b6 100644
--- a/src/extension/system.cpp
+++ b/src/extension/system.cpp
@@ -495,8 +495,6 @@ build_from_reprdoc(Inkscape::XML::Document *doc, Implementation::Implementation
Extension *
build_from_file(gchar const *filename)
{
- /* TODO: Need to define namespace here, need to write the
- DTD in general for this stuff */
Inkscape::XML::Document *doc = sp_repr_read_file(filename, INKSCAPE_EXTENSION_URI);
Extension *ext = build_from_reprdoc(doc, NULL);
if (ext != NULL)
diff --git a/src/path-prefix.h b/src/path-prefix.h
index a6ad95188..72c21ca55 100644
--- a/src/path-prefix.h
+++ b/src/path-prefix.h
@@ -25,6 +25,7 @@ extern "C" {
# define INKSCAPE_BINDDIR BR_DATADIR( "/inkscape/bind" )
# define INKSCAPE_EXAMPLESDIR BR_DATADIR( "/inkscape/examples" )
# define INKSCAPE_EXTENSIONDIR BR_DATADIR( "/inkscape/extensions" )
+# define INKSCAPE_FILTERDIR BR_DATADIR( "/inkscape/filters" )
# define INKSCAPE_GRADIENTSDIR BR_DATADIR( "/inkscape/gradients" )
# define INKSCAPE_KEYSDIR BR_DATADIR( "/inkscape/keys" )
# define INKSCAPE_PIXMAPDIR BR_DATADIR( "/inkscape/icons" )
@@ -46,6 +47,7 @@ extern "C" {
# define INKSCAPE_BINDDIR "share\\bind"
# define INKSCAPE_EXAMPLESDIR "share\\examples"
# define INKSCAPE_EXTENSIONDIR "share\\extensions"
+# define INKSCAPE_FILTERDIR "share\\filters"
# define INKSCAPE_GRADIENTSDIR "share\\gradients"
# define INKSCAPE_KEYSDIR "share\\keys"
# define INKSCAPE_PIXMAPDIR "share\\icons"
@@ -66,6 +68,7 @@ extern "C" {
# define INKSCAPE_BINDDIR "Contents/Resources/bind"
# define INKSCAPE_EXAMPLESDIR "Contents/Resources/examples"
# define INKSCAPE_EXTENSIONDIR "Contents/Resources/extensions"
+# define INKSCAPE_FILTERDIR "Contents/Resources/filters"
# define INKSCAPE_GRADIENTSDIR "Contents/Resources/gradients"
# define INKSCAPE_KEYSDIR "Contents/Resources/keys"
# define INKSCAPE_PIXMAPDIR "Contents/Resources/icons"
@@ -86,6 +89,7 @@ extern "C" {
# define INKSCAPE_BINDDIR INKSCAPE_DATADIR "/inkscape/bind"
# define INKSCAPE_EXAMPLESDIR INKSCAPE_DATADIR "/inkscape/examples"
# define INKSCAPE_EXTENSIONDIR INKSCAPE_DATADIR "/inkscape/extensions"
+# define INKSCAPE_FILTERDIR INKSCAPE_DATADIR "/inkscape/filters"
# define INKSCAPE_GRADIENTSDIR INKSCAPE_DATADIR "/inkscape/gradients"
# define INKSCAPE_KEYSDIR INKSCAPE_DATADIR "/inkscape/keys"
# define INKSCAPE_PIXMAPDIR INKSCAPE_DATADIR "/inkscape/icons"