1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** \file
3 * SVG <feMorphology> implementation.
4 *
5 */
6 /*
7 * Authors:
8 * Felipe Sanches <juca@members.fsf.org>
9 * Hugo Rodrigues <haa.rodrigues@gmail.com>
10 * Abhishek Sharma
11 *
12 * Copyright (C) 2006 Hugo Rodrigues
13 *
14 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15 */
16
17 #include <cstring>
18
19 #include "attributes.h"
20 #include "svg/svg.h"
21 #include "morphology.h"
22 #include "xml/repr.h"
23 #include "display/nr-filter.h"
24
SPFeMorphology()25 SPFeMorphology::SPFeMorphology() : SPFilterPrimitive() {
26 this->Operator = Inkscape::Filters::MORPHOLOGY_OPERATOR_ERODE;
27
28 //Setting default values:
29 this->radius.set("0");
30 }
31
32 SPFeMorphology::~SPFeMorphology() = default;
33
34 /**
35 * Reads the Inkscape::XML::Node, and initializes SPFeMorphology variables. For this to get called,
36 * our name must be associated with a repr via "sp_object_type_register". Best done through
37 * sp-object-repr.cpp's repr_name_entries array.
38 */
build(SPDocument * document,Inkscape::XML::Node * repr)39 void SPFeMorphology::build(SPDocument *document, Inkscape::XML::Node *repr) {
40 SPFilterPrimitive::build(document, repr);
41
42 /*LOAD ATTRIBUTES FROM REPR HERE*/
43 this->readAttr(SPAttr::OPERATOR);
44 this->readAttr(SPAttr::RADIUS);
45 }
46
47 /**
48 * Drops any allocated memory.
49 */
release()50 void SPFeMorphology::release() {
51 SPFilterPrimitive::release();
52 }
53
sp_feMorphology_read_operator(gchar const * value)54 static Inkscape::Filters::FilterMorphologyOperator sp_feMorphology_read_operator(gchar const *value){
55 if (!value) {
56 return Inkscape::Filters::MORPHOLOGY_OPERATOR_ERODE; //erode is default
57 }
58
59 switch(value[0]){
60 case 'e':
61 if (strncmp(value, "erode", 5) == 0) {
62 return Inkscape::Filters::MORPHOLOGY_OPERATOR_ERODE;
63 }
64 break;
65 case 'd':
66 if (strncmp(value, "dilate", 6) == 0) {
67 return Inkscape::Filters::MORPHOLOGY_OPERATOR_DILATE;
68 }
69 break;
70 }
71
72 return Inkscape::Filters::MORPHOLOGY_OPERATOR_ERODE; //erode is default
73 }
74
75 /**
76 * Sets a specific value in the SPFeMorphology.
77 */
set(SPAttr key,gchar const * value)78 void SPFeMorphology::set(SPAttr key, gchar const *value) {
79 Inkscape::Filters::FilterMorphologyOperator read_operator;
80
81 switch(key) {
82 /*DEAL WITH SETTING ATTRIBUTES HERE*/
83 case SPAttr::OPERATOR:
84 read_operator = sp_feMorphology_read_operator(value);
85
86 if (read_operator != this->Operator){
87 this->Operator = read_operator;
88 this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
89 }
90 break;
91 case SPAttr::RADIUS:
92 this->radius.set(value);
93
94 //From SVG spec: If <y-radius> is not provided, it defaults to <x-radius>.
95 if (this->radius.optNumIsSet() == false) {
96 this->radius.setOptNumber(this->radius.getNumber());
97 }
98
99 this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
100 break;
101 default:
102 SPFilterPrimitive::set(key, value);
103 break;
104 }
105
106 }
107
108 /**
109 * Receives update notifications.
110 */
update(SPCtx * ctx,guint flags)111 void SPFeMorphology::update(SPCtx *ctx, guint flags) {
112 if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
113 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
114
115 /* do something to trigger redisplay, updates? */
116
117 }
118
119 SPFilterPrimitive::update(ctx, flags);
120 }
121
122 /**
123 * Writes its settings to an incoming repr object, if any.
124 */
write(Inkscape::XML::Document * doc,Inkscape::XML::Node * repr,guint flags)125 Inkscape::XML::Node* SPFeMorphology::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
126 /* TODO: Don't just clone, but create a new repr node and write all
127 * relevant values into it */
128 if (!repr) {
129 repr = this->getRepr()->duplicate(doc);
130 }
131
132 SPFilterPrimitive::write(doc, repr, flags);
133
134 return repr;
135 }
136
build_renderer(Inkscape::Filters::Filter * filter)137 void SPFeMorphology::build_renderer(Inkscape::Filters::Filter* filter) {
138 g_assert(filter != nullptr);
139
140 int primitive_n = filter->add_primitive(Inkscape::Filters::NR_FILTER_MORPHOLOGY);
141 Inkscape::Filters::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
142 Inkscape::Filters::FilterMorphology *nr_morphology = dynamic_cast<Inkscape::Filters::FilterMorphology*>(nr_primitive);
143 g_assert(nr_morphology != nullptr);
144
145 this->renderer_common(nr_primitive);
146
147 nr_morphology->set_operator(this->Operator);
148 nr_morphology->set_xradius( this->radius.getNumber() );
149 nr_morphology->set_yradius( this->radius.getOptNumber() );
150 }
151
152 /*
153 Local Variables:
154 mode:c++
155 c-file-style:"stroustrup"
156 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
157 indent-tabs-mode:nil
158 fill-column:99
159 End:
160 */
161 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
162