1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** \file
3  * SVG <gaussianBlur> implementation.
4  *
5  */
6 /*
7  * Authors:
8  *   Hugo Rodrigues <haa.rodrigues@gmail.com>
9  *   Niko Kiirala <niko@kiirala.com>
10  *   Abhishek Sharma
11  *
12  * Copyright (C) 2006,2007 Authors
13  *
14  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15  */
16 
17 #include "gaussian-blur.h"
18 
19 #include "attributes.h"
20 
21 #include "display/nr-filter.h"
22 #include "display/nr-filter-gaussian.h"
23 
24 #include "svg/svg.h"
25 
26 #include "xml/repr.h"
27 
SPGaussianBlur()28 SPGaussianBlur::SPGaussianBlur() : SPFilterPrimitive() {
29 }
30 
31 SPGaussianBlur::~SPGaussianBlur() = default;
32 
33 /**
34  * Reads the Inkscape::XML::Node, and initializes SPGaussianBlur variables.  For this to get called,
35  * our name must be associated with a repr via "sp_object_type_register".  Best done through
36  * sp-object-repr.cpp's repr_name_entries array.
37  */
build(SPDocument * document,Inkscape::XML::Node * repr)38 void SPGaussianBlur::build(SPDocument *document, Inkscape::XML::Node *repr) {
39 	SPFilterPrimitive::build(document, repr);
40 
41     this->readAttr(SPAttr::STDDEVIATION);
42 }
43 
44 /**
45  * Drops any allocated memory.
46  */
release()47 void SPGaussianBlur::release() {
48 	SPFilterPrimitive::release();
49 }
50 
51 /**
52  * Sets a specific value in the SPGaussianBlur.
53  */
set(SPAttr key,gchar const * value)54 void SPGaussianBlur::set(SPAttr key, gchar const *value) {
55     switch(key) {
56         case SPAttr::STDDEVIATION:
57             this->stdDeviation.set(value);
58             this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
59             break;
60         default:
61         	SPFilterPrimitive::set(key, value);
62             break;
63     }
64 }
65 
66 /**
67  * Receives update notifications.
68  */
update(SPCtx * ctx,guint flags)69 void SPGaussianBlur::update(SPCtx *ctx, guint flags) {
70     if (flags & SP_OBJECT_MODIFIED_FLAG) {
71         this->readAttr(SPAttr::STDDEVIATION);
72     }
73 
74     SPFilterPrimitive::update(ctx, flags);
75 }
76 
77 /**
78  * Writes its settings to an incoming repr object, if any.
79  */
write(Inkscape::XML::Document * doc,Inkscape::XML::Node * repr,guint flags)80 Inkscape::XML::Node* SPGaussianBlur::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
81     /* TODO: Don't just clone, but create a new repr node and write all
82      * relevant values into it */
83     if (!repr) {
84         repr = this->getRepr()->duplicate(doc);
85     }
86 
87     SPFilterPrimitive::write(doc, repr, flags);
88 
89     return repr;
90 }
91 
sp_gaussianBlur_setDeviation(SPGaussianBlur * blur,float num)92 void  sp_gaussianBlur_setDeviation(SPGaussianBlur *blur, float num)
93 {
94     blur->stdDeviation.setNumber(num);
95 }
96 
sp_gaussianBlur_setDeviation(SPGaussianBlur * blur,float num,float optnum)97 void  sp_gaussianBlur_setDeviation(SPGaussianBlur *blur, float num, float optnum)
98 {
99     blur->stdDeviation.setNumber(num);
100     blur->stdDeviation.setOptNumber(optnum);
101 }
102 
build_renderer(Inkscape::Filters::Filter * filter)103 void SPGaussianBlur::build_renderer(Inkscape::Filters::Filter* filter) {
104     int handle = filter->add_primitive(Inkscape::Filters::NR_FILTER_GAUSSIANBLUR);
105     Inkscape::Filters::FilterPrimitive *nr_primitive = filter->get_primitive(handle);
106     Inkscape::Filters::FilterGaussian *nr_blur = dynamic_cast<Inkscape::Filters::FilterGaussian*>(nr_primitive);
107 
108     this->renderer_common(nr_primitive);
109 
110     gfloat num = this->stdDeviation.getNumber();
111 
112     if (num >= 0.0) {
113         gfloat optnum = this->stdDeviation.getOptNumber();
114 
115         if(optnum >= 0.0) {
116             nr_blur->set_deviation((double) num, (double) optnum);
117         } else {
118             nr_blur->set_deviation((double) num);
119         }
120     }
121 }
122 
123 /* Calculate the region taken up by gaussian blur
124  *
125  * @param region The original shape's region or previous primitive's region output.
126  */
calculate_region(Geom::Rect region)127 Geom::Rect SPGaussianBlur::calculate_region(Geom::Rect region)
128 {
129     double x = this->stdDeviation.getNumber();
130     double y = this->stdDeviation.getOptNumber();
131     if (y == -1.0)
132         y = x;
133     // If not within the default 10% margin (see
134     // http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion), specify margins
135     // The 2.4 is an empirical coefficient: at that distance the cutoff is practically invisible
136     // (the opacity at 2.4 * radius is about 3e-3)
137     region.expandBy(2.4 * x, 2.4 * y);
138     return region;
139 }
140 
141 /*
142   Local Variables:
143   mode:c++
144   c-file-style:"stroustrup"
145   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
146   indent-tabs-mode:nil
147   fill-column:99
148   End:
149 */
150 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
151