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