~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/extension/internal/filter/filter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Authors:
 
3
 *   Ted Gould <ted@gould.cx>
 
4
 *
 
5
 * Copyright (C) 2008 Authors
 
6
 *
 
7
 * Released under GNU GPL, read the file 'COPYING' for more information
 
8
 */
 
9
 
 
10
#include "desktop.h"
 
11
#include "selection.h"
 
12
#include "document-private.h"
 
13
#include "sp-item.h"
 
14
#include "util/glib-list-iterators.h"
 
15
#include "extension/extension.h"
 
16
#include "extension/effect.h"
 
17
#include "extension/system.h"
 
18
#include "xml/repr.h"
 
19
#include "xml/simple-node.h"
 
20
#include "xml/attribute-record.h"
 
21
 
 
22
#include "filter.h"
 
23
 
 
24
namespace Inkscape {
 
25
namespace Extension {
 
26
namespace Internal {
 
27
namespace Filter {
 
28
 
 
29
Filter::Filter() :
 
30
                Inkscape::Extension::Implementation::Implementation(),
 
31
                _filter(NULL) {
 
32
        return;
 
33
}
 
34
 
 
35
Filter::Filter(gchar const * filter) :
 
36
                Inkscape::Extension::Implementation::Implementation(),
 
37
                _filter(filter) {
 
38
        return;
 
39
}
 
40
 
 
41
Filter::~Filter (void) {
 
42
        if (_filter != NULL) {
 
43
                _filter = NULL;
 
44
        }
 
45
 
 
46
        return;
 
47
}
 
48
 
 
49
bool
 
50
Filter::load (Inkscape::Extension::Extension *module)
 
51
{
 
52
        return true;
 
53
}
 
54
 
 
55
Inkscape::Extension::Implementation::ImplementationDocumentCache *
 
56
Filter::newDocCache (Inkscape::Extension::Extension * ext, Inkscape::UI::View::View * doc)
 
57
{
 
58
        return NULL;
 
59
}
 
60
 
 
61
gchar const *
 
62
Filter::get_filter_text (Inkscape::Extension::Extension * ext)
 
63
{
 
64
        return _filter;
 
65
}
 
66
 
 
67
Inkscape::XML::Document *
 
68
Filter::get_filter (Inkscape::Extension::Extension * ext) {
 
69
        gchar const * filter = get_filter_text(ext);
 
70
        return sp_repr_read_mem(filter, strlen(filter), NULL);
 
71
}
 
72
 
 
73
void 
 
74
Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar * srcGraphic, gchar * srcGraphicAlpha)
 
75
{
 
76
        if (from == NULL) return;
 
77
 
 
78
        // copy attributes
 
79
    for ( Inkscape::Util::List<Inkscape::XML::AttributeRecord const> iter = from->attributeList() ;
 
80
          iter ; ++iter ) {
 
81
                gchar const * attr = g_quark_to_string(iter->key);
 
82
                //printf("Attribute List: %s\n", attr);
 
83
                if (!strcmp(attr, "id")) continue; // nope, don't copy that one!
 
84
                to->setAttribute(attr, from->attribute(attr));
 
85
 
 
86
                if (!strcmp(attr, "in") || !strcmp(attr, "in2") || !strcmp(attr, "in3")) {
 
87
                        if (srcGraphic != NULL && !strcmp(from->attribute(attr), "SourceGraphic")) {
 
88
                                to->setAttribute(attr, srcGraphic);
 
89
                        }
 
90
 
 
91
                        if (srcGraphicAlpha != NULL && !strcmp(from->attribute(attr), "SourceAlpha")) {
 
92
                                to->setAttribute(attr, srcGraphicAlpha);
 
93
                        }
 
94
                }
 
95
        }
 
96
 
 
97
        // for each child call recursively
 
98
        for (Inkscape::XML::Node * from_child = from->firstChild();
 
99
                  from_child != NULL ; from_child = from_child->next()) {
 
100
                Glib::ustring name = "svg:";
 
101
                name += from_child->name();
 
102
                
 
103
                Inkscape::XML::Node * to_child = doc->createElement(name.c_str());
 
104
                to->appendChild(to_child);
 
105
                merge_filters(to_child, from_child, doc, srcGraphic, srcGraphicAlpha);
 
106
 
 
107
                if (from_child == from->firstChild() && !strcmp("filter", from->name()) && srcGraphic != NULL && to_child->attribute("in") == NULL) {
 
108
                        to_child->setAttribute("in", srcGraphic);
 
109
                }
 
110
    Inkscape::GC::release(to_child);
 
111
        }
 
112
}
 
113
 
 
114
#define FILTER_SRC_GRAPHIC       "fbSourceGraphic"
 
115
#define FILTER_SRC_GRAPHIC_ALPHA "fbSourceGraphicAlpha"
 
116
 
 
117
void
 
118
Filter::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache)
 
119
{
 
120
        Inkscape::XML::Document *filterdoc = get_filter(module);
 
121
        if (filterdoc == NULL) {
 
122
                return; // could not parse the XML source of the filter; typically parser will stderr a warning
 
123
        }
 
124
 
 
125
        //printf("Calling filter effect\n");
 
126
    Inkscape::Selection * selection = ((SPDesktop *)document)->selection;
 
127
 
 
128
    using Inkscape::Util::GSListConstIterator;
 
129
    // TODO need to properly refcount the items, at least
 
130
    std::list<SPItem *> items;
 
131
    items.insert<GSListConstIterator<SPItem *> >(items.end(), selection->itemList(), NULL);
 
132
 
 
133
        Inkscape::XML::Document * xmldoc = sp_document_repr_doc(document->doc());
 
134
        Inkscape::XML::Node * defsrepr = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(document->doc()));
 
135
 
 
136
    for(std::list<SPItem *>::iterator item = items.begin();
 
137
            item != items.end(); item++) {
 
138
        SPItem * spitem = *item;
 
139
                Inkscape::XML::Node * node = SP_OBJECT_REPR(spitem);
 
140
 
 
141
                SPCSSAttr * css = sp_repr_css_attr(node, "style");
 
142
                gchar const * filter = sp_repr_css_property(css, "filter", NULL);
 
143
 
 
144
                if (filter == NULL) {
 
145
 
 
146
                        Inkscape::XML::Node * newfilterroot = xmldoc->createElement("svg:filter");
 
147
                        defsrepr->appendChild(newfilterroot);
 
148
 
 
149
                        Glib::ustring url = "url(#"; url += newfilterroot->attribute("id"); url += ")";
 
150
 
 
151
                        merge_filters(newfilterroot, filterdoc->root(), xmldoc);
 
152
  
 
153
      Inkscape::GC::release(newfilterroot);
 
154
 
 
155
                        sp_repr_css_set_property(css, "filter", url.c_str());
 
156
                        sp_repr_css_set(node, css, "style");
 
157
                } else {
 
158
                        if (strncmp(filter, "url(#", strlen("url(#")) || filter[strlen(filter) - 1] != ')') {
 
159
                                // This is not url(#id) -- we can't handle it
 
160
                                continue;
 
161
                        }
 
162
 
 
163
                        gchar * lfilter = g_strndup(filter + 5, strlen(filter) - 6);
 
164
                        Inkscape::XML::Node * filternode = NULL;
 
165
                        for (Inkscape::XML::Node * child = defsrepr->firstChild(); child != NULL; child = child->next()) {
 
166
                                if (!strcmp(lfilter, child->attribute("id"))) {
 
167
                                        filternode = child;
 
168
                                        break;
 
169
                                }
 
170
                        }
 
171
                        g_free(lfilter);
 
172
 
 
173
                        if (filternode == NULL) {
 
174
                                continue;
 
175
                        }
 
176
 
 
177
                        filternode->lastChild()->setAttribute("result", FILTER_SRC_GRAPHIC);
 
178
 
 
179
                        Inkscape::XML::Node * alpha = xmldoc->createElement("svg:feColorMatrix");
 
180
                        alpha->setAttribute("result", FILTER_SRC_GRAPHIC_ALPHA);
 
181
                        alpha->setAttribute("in", FILTER_SRC_GRAPHIC); // not required, but we're being explicit
 
182
                        alpha->setAttribute("values", "0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0");
 
183
                        filternode->appendChild(alpha);
 
184
 
 
185
                        merge_filters(filternode, filterdoc->root(), xmldoc, FILTER_SRC_GRAPHIC, FILTER_SRC_GRAPHIC_ALPHA);
 
186
 
 
187
      Inkscape::GC::release(alpha);
 
188
                }
 
189
    }
 
190
 
 
191
    return;
 
192
}
 
193
 
 
194
#include "extension/internal/clear-n_.h"
 
195
 
 
196
void
 
197
Filter::filter_init (gchar const * id, gchar const * name, gchar const * submenu, gchar const * tip, gchar const * filter)
 
198
{
 
199
        gchar * xml_str = g_strdup_printf(
 
200
        "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
 
201
            "<name>%s</name>\n"
 
202
            "<id>org.inkscape.effect.filter.%s</id>\n"
 
203
            "<effect>\n"
 
204
                "<object-type>all</object-type>\n"
 
205
                "<effects-menu>\n"
 
206
                    "<submenu name=\"" N_("Filters") "\" />\n"
 
207
                                                        "<submenu name=\"%s\"/>\n"
 
208
                "</effects-menu>\n"
 
209
                "<menu-tip>%s</menu-tip>\n"
 
210
            "</effect>\n"
 
211
        "</inkscape-extension>\n", name, id, submenu, tip);
 
212
    Inkscape::Extension::build_from_mem(xml_str, new Filter::Filter(filter));
 
213
        g_free(xml_str);
 
214
    return;
 
215
}
 
216
 
 
217
}; /* namespace Filter */
 
218
}; /* namespace Internal */
 
219
}; /* namespace Extension */
 
220
}; /* namespace Inkscape */
 
221