acb3aca02946b448f61114e60c68e1d2d51b7f9a
[WebKit-https.git] / Source / WebCore / svg / SVGFEMorphologyElement.cpp
1 /*
2  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "SVGFEMorphologyElement.h"
22
23 #include "FilterEffect.h"
24 #include "SVGFilterBuilder.h"
25 #include "SVGNames.h"
26 #include "SVGParserUtilities.h"
27 #include <wtf/IsoMallocInlines.h>
28
29 namespace WebCore {
30
31 WTF_MAKE_ISO_ALLOCATED_IMPL(SVGFEMorphologyElement);
32
33 // Animated property definitions
34 DEFINE_ANIMATED_STRING(SVGFEMorphologyElement, SVGNames::inAttr, In1, in1)
35 DEFINE_ANIMATED_ENUMERATION(SVGFEMorphologyElement, SVGNames::operatorAttr, SVGOperator, svgOperator, MorphologyOperatorType)
36 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEMorphologyElement, SVGNames::radiusAttr, radiusXIdentifier(), RadiusX, radiusX)
37 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEMorphologyElement, SVGNames::radiusAttr, radiusYIdentifier(), RadiusY, radiusY)
38
39 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEMorphologyElement)
40     REGISTER_LOCAL_ANIMATED_PROPERTY(in1)
41     REGISTER_LOCAL_ANIMATED_PROPERTY(svgOperator)
42     REGISTER_LOCAL_ANIMATED_PROPERTY(radiusX)
43     REGISTER_LOCAL_ANIMATED_PROPERTY(radiusY)
44     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
45 END_REGISTER_ANIMATED_PROPERTIES
46
47 inline SVGFEMorphologyElement::SVGFEMorphologyElement(const QualifiedName& tagName, Document& document)
48     : SVGFilterPrimitiveStandardAttributes(tagName, document)
49     , m_svgOperator(FEMORPHOLOGY_OPERATOR_ERODE)
50 {
51     ASSERT(hasTagName(SVGNames::feMorphologyTag));
52     registerAnimatedPropertiesForSVGFEMorphologyElement();
53 }
54
55 Ref<SVGFEMorphologyElement> SVGFEMorphologyElement::create(const QualifiedName& tagName, Document& document)
56 {
57     return adoptRef(*new SVGFEMorphologyElement(tagName, document));
58 }
59
60 const AtomicString& SVGFEMorphologyElement::radiusXIdentifier()
61 {
62     static NeverDestroyed<AtomicString> s_identifier("SVGRadiusX", AtomicString::ConstructFromLiteral);
63     return s_identifier;
64 }
65
66 const AtomicString& SVGFEMorphologyElement::radiusYIdentifier()
67 {
68     static NeverDestroyed<AtomicString> s_identifier("SVGRadiusY", AtomicString::ConstructFromLiteral);
69     return s_identifier;
70 }
71
72 void SVGFEMorphologyElement::setRadius(float x, float y)
73 {
74     setRadiusXBaseValue(x);
75     setRadiusYBaseValue(y);
76     invalidate();
77 }
78
79 void SVGFEMorphologyElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
80 {
81     if (name == SVGNames::operatorAttr) {
82         MorphologyOperatorType propertyValue = SVGPropertyTraits<MorphologyOperatorType>::fromString(value);
83         if (propertyValue > 0)
84             setSVGOperatorBaseValue(propertyValue);
85         return;
86     }
87
88     if (name == SVGNames::inAttr) {
89         setIn1BaseValue(value);
90         return;
91     }
92
93     if (name == SVGNames::radiusAttr) {
94         float x, y;
95         if (parseNumberOptionalNumber(value, x, y)) {
96             setRadiusXBaseValue(x);
97             setRadiusYBaseValue(y);
98         }
99         return;
100     }
101
102     SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
103 }
104
105 bool SVGFEMorphologyElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName)
106 {
107     FEMorphology* morphology = static_cast<FEMorphology*>(effect);
108     if (attrName == SVGNames::operatorAttr)
109         return morphology->setMorphologyOperator(svgOperator());
110     if (attrName == SVGNames::radiusAttr) {
111         // Both setRadius functions should be evaluated separately.
112         bool isRadiusXChanged = morphology->setRadiusX(radiusX());
113         bool isRadiusYChanged = morphology->setRadiusY(radiusY());
114         return isRadiusXChanged || isRadiusYChanged;
115     }
116
117     ASSERT_NOT_REACHED();
118     return false;
119 }
120
121 void SVGFEMorphologyElement::svgAttributeChanged(const QualifiedName& attrName)
122 {
123     if (attrName == SVGNames::operatorAttr || attrName == SVGNames::radiusAttr) {
124         InstanceInvalidationGuard guard(*this);
125         primitiveAttributeChanged(attrName);
126         return;
127     }
128
129     if (attrName == SVGNames::inAttr) {
130         InstanceInvalidationGuard guard(*this);
131         invalidate();
132         return;
133     }
134
135     SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
136 }
137
138 RefPtr<FilterEffect> SVGFEMorphologyElement::build(SVGFilterBuilder* filterBuilder, Filter& filter)
139 {
140     auto input1 = filterBuilder->getEffectById(in1());
141     float xRadius = radiusX();
142     float yRadius = radiusY();
143
144     if (!input1)
145         return nullptr;
146
147     if (xRadius < 0 || yRadius < 0)
148         return nullptr;
149
150     RefPtr<FilterEffect> effect = FEMorphology::create(filter, svgOperator(), xRadius, yRadius);
151     effect->inputEffects().append(input1);
152     return effect;
153 }
154
155 } // namespace WebCore