Code

Pot and Dutch translation update
[inkscape.git] / src / extension / internal / filter / filter.cpp
index e87290ab4dfb752f5d1966e7b2d55cad01ba961c..c2d80b28b4e02dc0d9e235e2d186dc4c2914fcbb 100644 (file)
@@ -70,8 +70,10 @@ Filter::get_filter (Inkscape::Extension::Extension * ext) {
        return sp_repr_read_mem(filter, strlen(filter), NULL);
 }
 
-void 
-Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc)
+void
+Filter::merge_filters( Inkscape::XML::Node * to, Inkscape::XML::Node * from,
+                      Inkscape::XML::Document * doc,
+                      gchar const * srcGraphic, gchar const * srcGraphicAlpha)
 {
        if (from == NULL) return;
 
@@ -82,6 +84,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
@@ -89,18 +101,29 @@ Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Ink
                  from_child != NULL ; from_child = from_child->next()) {
                Glib::ustring name = "svg:";
                name += from_child->name();
-               
+
                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);
 
-       return;
+               if (from_child == from->firstChild() && !strcmp("filter", from->name()) && srcGraphic != NULL && to_child->attribute("in") == NULL) {
+                       to_child->setAttribute("in", srcGraphic);
+               }
+    Inkscape::GC::release(to_child);
+       }
 }
 
+#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)
 {
+       Inkscape::XML::Document *filterdoc = get_filter(module);
+       if (filterdoc == NULL) {
+               return; // could not parse the XML source of the filter; typically parser will stderr a warning
+       }
+
        //printf("Calling filter effect\n");
     Inkscape::Selection * selection = ((SPDesktop *)document)->selection;
 
@@ -121,14 +144,57 @@ Filter::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *d
                gchar const * filter = sp_repr_css_property(css, "filter", NULL);
 
                if (filter == NULL) {
+
                        Inkscape::XML::Node * newfilterroot = xmldoc->createElement("svg:filter");
                        defsrepr->appendChild(newfilterroot);
+
                        Glib::ustring url = "url(#"; url += newfilterroot->attribute("id"); url += ")";
 
-                       merge_filters(newfilterroot, get_filter(module)->root(), xmldoc);
+                       merge_filters(newfilterroot, filterdoc->root(), xmldoc);
+
+      Inkscape::GC::release(newfilterroot);
 
                        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);
+
+                       // no filter
+                       if (filternode == NULL) {
+                               g_warning("no assoziating filter found!");
+                               continue;
+                       }
+
+                       if (filternode->lastChild() == NULL) {
+                // empty filter, we insert
+                merge_filters(filternode, filterdoc->root(), xmldoc);
+                       } else {
+                // existing filter, we merge
+                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, filterdoc->root(), xmldoc, FILTER_SRC_GRAPHIC, FILTER_SRC_GRAPHIC_ALPHA);
+
+                Inkscape::GC::release(alpha);
+                       }
                }
     }
 
@@ -138,7 +204,7 @@ Filter::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *d
 #include "extension/internal/clear-n_.h"
 
 void
-Filter::filter_init (gchar const * id, gchar const * name, gchar const * tip, gchar const * filter)
+Filter::filter_init (gchar const * id, gchar const * name, gchar const * submenu, gchar const * tip, gchar const * filter)
 {
        gchar * xml_str = g_strdup_printf(
         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
@@ -147,12 +213,13 @@ Filter::filter_init (gchar const * id, gchar const * name, gchar const * tip, gc
             "<effect>\n"
                 "<object-type>all</object-type>\n"
                 "<effects-menu>\n"
-                    "<submenu name=\"" N_("Filter") "\" />\n"
+                    "<submenu name=\"" N_("Filters") "\" />\n"
+                                                       "<submenu name=\"%s\"/>\n"
                 "</effects-menu>\n"
                 "<menu-tip>%s</menu-tip>\n"
             "</effect>\n"
-        "</inkscape-extension>\n", name, id, tip);
-    Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(filter));
+        "</inkscape-extension>\n", name, id, submenu, tip);
+    Inkscape::Extension::build_from_mem(xml_str, new Filter(filter));
        g_free(xml_str);
     return;
 }