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