From 582f966ce046d5be9b46c24d06248c59b9dd630c Mon Sep 17 00:00:00 2001 From: gouldtj Date: Sat, 26 Apr 2008 04:22:42 +0000 Subject: [PATCH 1/1] 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 --- po/POTFILES.in | 1 + src/extension/init.cpp | 5 +- src/extension/internal/Makefile_insert | 1 + src/extension/internal/filter/filter-all.cpp | 5 + src/extension/internal/filter/filter-file.cpp | 165 ++++++++++++++++++ src/extension/internal/filter/filter.cpp | 50 +++++- src/extension/internal/filter/filter.h | 9 +- src/extension/system.cpp | 2 - src/path-prefix.h | 4 + 9 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 src/extension/internal/filter/filter-file.cpp diff --git a/po/POTFILES.in b/po/POTFILES.in index fd124043f..8f44328c4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -97,6 +97,7 @@ src/extension/internal/filter/cutout.h src/extension/internal/filter/drop-shadow.h src/extension/internal/filter/etched-glass.h src/extension/internal/filter/filter.cpp +src/extension/internal/filter/filter-file.cpp src/extension/internal/filter/fire.h src/extension/internal/filter/frost.h src/extension/internal/filter/ink-bleed.h 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 + * + * 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 + +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( + "\n" + "%s\n" + "org.inkscape.effect.filter.%s\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\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" -- 2.30.2