Code

r19136@shi: ted | 2008-04-24 19:44:01 -0700
authorgouldtj <gouldtj@users.sourceforge.net>
Sat, 26 Apr 2008 04:22:42 +0000 (04:22 +0000)
committergouldtj <gouldtj@users.sourceforge.net>
Sat, 26 Apr 2008 04:22:42 +0000 (04:22 +0000)
 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
src/extension/init.cpp
src/extension/internal/Makefile_insert
src/extension/internal/filter/filter-all.cpp
src/extension/internal/filter/filter-file.cpp [new file with mode: 0644]
src/extension/internal/filter/filter.cpp
src/extension/internal/filter/filter.h
src/extension/system.cpp
src/path-prefix.h

index fd124043f402c62534164e6dbc2b024fc8be2fa7..8f44328c42d0379a0bc9ab4c1a375efbd6c22a63 100644 (file)
@@ -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
index a1d88d7ec2e6de6e725cda674fefcb84e438da50..649a654712b8fc9d5dbea2c62760dbc8ed462f86 100644 (file)
@@ -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;
 }
 
 
index bca2b0a6d9dc28fadf3709e72447e24f386e7fc1..73303ffca1b1abdd058fa7d5d2ac029b931fb615 100644 (file)
@@ -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
 
index 917730e2c51c616d5466eee4cfc710c1c954dd9f..08bef9f742e019bba137dc9dc75ba3dc8cc7534d 100644 (file)
@@ -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 (file)
index 0000000..e4f9118
--- /dev/null
@@ -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 */
+
index e87290ab4dfb752f5d1966e7b2d55cad01ba961c..b2a55b6e6154a9c1522378bd133ad66185f32408 100644 (file)
@@ -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);
                }
     }
 
index 851beb833dae5366278bad3588e8f36315d87f5b..28924988de66c001292c5340a480f061de6624b4 100644 (file)
@@ -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 */
index d66655a511f409ee8ac8f175361bcf33a9aae018..cd70042b6e758d2918956fe0fa2268817a95927c 100644 (file)
@@ -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)
index a6ad95188ff754468e3743035a27813a7a3e8cf3..72c21ca55d84e3c94638aefea388fe13cec07eae 100644 (file)
@@ -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"