Code

Merge further bbox work
[inkscape.git] / src / filter-chemistry.cpp
1 #define __SP_FILTER_CHEMISTRY_C__
3 /*
4  * Various utility methods for filters
5  *
6  * Authors:
7  *   Hugo Rodrigues
8  *   bulia byak
9  *
10  * Copyright (C) 2006 authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
16 #include "style.h"
17 #include "document-private.h"
18 #include "desktop-style.h"
20 #include "sp-filter.h"
21 #include "sp-gaussian-blur.h"
22 #include "svg/css-ostringstream.h"
24 #include "xml/repr.h"
26 /**
27  * Creates a filter with blur primitive of specified radius for an item with the given matrix expansion, width and height
28  */
29 SPFilter *
30 new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion, double expansionX, double expansionY, double width, double height)
31 {
32     g_return_val_if_fail(document != NULL, NULL);
34     SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
36     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
38     // create a new filter
39     Inkscape::XML::Node *repr;
40     repr = xml_doc->createElement("svg:filter");
41     repr->setAttribute("inkscape:collect", "always");
43     double rx = radius * (expansionY != 0? (expansion / expansionY) : 1);
44     double ry = radius * (expansionX != 0? (expansion / expansionX) : 1);
46     if (width != 0 && height != 0 && (2.4 * rx > width * 0.1 || 2.4 * ry > height * 0.1)) {
47         // If not within the default 10% margin (see
48         // http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion), specify margins
49         // The 2.4 is an empirical coefficient: at that distance the cutoff is practically invisible 
50         // (the opacity at 2.4*radius is about 3e-3)
51         double xmargin = 2.4 * (rx) / width;
52         double ymargin = 2.4 * (ry) / height;
54         // TODO: set it in UserSpaceOnUse instead?
55         sp_repr_set_svg_double(repr, "x", -xmargin);
56         sp_repr_set_svg_double(repr, "width", 1 + 2 * xmargin);
57         sp_repr_set_svg_double(repr, "y", -ymargin);
58         sp_repr_set_svg_double(repr, "height", 1 + 2 * ymargin);
59     }
61     //create feGaussianBlur node
62     Inkscape::XML::Node *b_repr;
63     b_repr = xml_doc->createElement("svg:feGaussianBlur");
64     b_repr->setAttribute("inkscape:collect", "always");
65     
66     double stdDeviation = radius;
67     if (expansion != 0)
68         stdDeviation /= expansion;
70     //set stdDeviation attribute
71     sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
72     
73     //set feGaussianBlur as child of filter node
74     repr->appendChild(b_repr);
75     Inkscape::GC::release(b_repr);
76     
77     // Append the new filter node to defs
78     SP_OBJECT_REPR(defs)->appendChild(repr);
79     Inkscape::GC::release(repr);
81     // get corresponding object
82     SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
83     SPGaussianBlur *b = SP_GAUSSIANBLUR( document->getObjectByRepr(b_repr) );
84     
85     g_assert(f != NULL);
86     g_assert(SP_IS_FILTER(f));
87     g_assert(b != NULL);
88     g_assert(SP_IS_GAUSSIANBLUR(b));
90     return f;
91 }
93 /**
94  * Creates a filter with blur primitive of specified radius for the given item
95  */
96 SPFilter *
97 new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble radius)
98 {
99     NR::Maybe<NR::Rect> const r = sp_item_bbox_desktop(item);
101     double width;
102     double height;
103     if (r) {
104         width = r->extent(NR::X);
105         height= r->extent(NR::Y);
106     } else {
107         width = height = 0;
108     }
110     NR::Matrix i2d = sp_item_i2d_affine (item);
112     return (new_filter_gaussian_blur (document, radius, i2d.expansion(), i2d.expansionX(), i2d.expansionY(), width, height));
115 void remove_filter (SPObject *item, bool recursive)
117         SPCSSAttr *css = sp_repr_css_attr_new ();
118         sp_repr_css_unset_property (css, "filter");
119         if (recursive)
120                 sp_repr_css_change_recursive(SP_OBJECT_REPR(item), css, "style");
121         else
122                 sp_repr_css_change (SP_OBJECT_REPR(item), css, "style");
123       sp_repr_css_attr_unref (css);
126 /*
127   Local Variables:
128   mode:c++
129   c-file-style:"stroustrup"
130   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
131   indent-tabs-mode:nil
132   fill-column:99
133   End:
134 */
135 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :