Improve use of NeverDestroyed
[WebKit-https.git] / Source / WebCore / svg / SVGFilterPrimitiveStandardAttributes.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "SVGFilterPrimitiveStandardAttributes.h"
24
25 #include "FilterEffect.h"
26 #include "RenderSVGResourceFilterPrimitive.h"
27 #include "SVGElement.h"
28 #include "SVGFilterBuilder.h"
29 #include "SVGLengthValue.h"
30 #include "SVGNames.h"
31 #include "SVGUnitTypes.h"
32 #include <wtf/NeverDestroyed.h>
33
34 namespace WebCore {
35
36 // Animated property definitions
37 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::xAttr, X, x)
38 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::yAttr, Y, y)
39 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::widthAttr, Width, width)
40 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::heightAttr, Height, height)
41 DEFINE_ANIMATED_STRING(SVGFilterPrimitiveStandardAttributes, SVGNames::resultAttr, Result, result)
42
43 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
44     REGISTER_LOCAL_ANIMATED_PROPERTY(x)
45     REGISTER_LOCAL_ANIMATED_PROPERTY(y)
46     REGISTER_LOCAL_ANIMATED_PROPERTY(width)
47     REGISTER_LOCAL_ANIMATED_PROPERTY(height)
48     REGISTER_LOCAL_ANIMATED_PROPERTY(result)
49     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
50 END_REGISTER_ANIMATED_PROPERTIES
51
52 SVGFilterPrimitiveStandardAttributes::SVGFilterPrimitiveStandardAttributes(const QualifiedName& tagName, Document& document)
53     : SVGElement(tagName, document)
54     , m_x(LengthModeWidth, "0%")
55     , m_y(LengthModeHeight, "0%")
56     , m_width(LengthModeWidth, "100%")
57     , m_height(LengthModeHeight, "100%")
58 {
59     // Spec: If the x/y attribute is not specified, the effect is as if a value of "0%" were specified.
60     // Spec: If the width/height attribute is not specified, the effect is as if a value of "100%" were specified.
61     registerAnimatedPropertiesForSVGFilterPrimitiveStandardAttributes();
62 }
63
64 bool SVGFilterPrimitiveStandardAttributes::isSupportedAttribute(const QualifiedName& attrName)
65 {
66     static const auto supportedAttributes = makeNeverDestroyed(HashSet<QualifiedName> {
67         SVGNames::xAttr,
68         SVGNames::yAttr,
69         SVGNames::widthAttr,
70         SVGNames::heightAttr,
71         SVGNames::resultAttr,
72     });
73     return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
74 }
75
76 void SVGFilterPrimitiveStandardAttributes::parseAttribute(const QualifiedName& name, const AtomicString& value)
77 {
78     SVGParsingError parseError = NoError;
79
80     if (name == SVGNames::xAttr)
81         setXBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError));
82     else if (name == SVGNames::yAttr)
83         setYBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError));
84     else if (name == SVGNames::widthAttr)
85         setWidthBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError));
86     else if (name == SVGNames::heightAttr)
87         setHeightBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError));
88     else if (name == SVGNames::resultAttr)
89         setResultBaseValue(value);
90
91     reportAttributeParsingError(parseError, name, value);
92
93     SVGElement::parseAttribute(name, value);
94 }
95
96 bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&)
97 {
98     // When all filters support this method, it will be changed to a pure virtual method.
99     ASSERT_NOT_REACHED();
100     return false;
101 }
102
103 void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
104 {
105     if (!isSupportedAttribute(attrName)) {
106         SVGElement::svgAttributeChanged(attrName);
107         return;
108     }
109
110     InstanceInvalidationGuard guard(*this);
111     invalidate();
112 }
113
114 void SVGFilterPrimitiveStandardAttributes::childrenChanged(const ChildChange& change)
115 {
116     SVGElement::childrenChanged(change);
117
118     if (change.source == ChildChangeSourceParser)
119         return;
120     invalidate();
121 }
122
123 void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(FilterEffect* filterEffect) const
124 {
125     ASSERT(filterEffect);
126     if (!filterEffect)
127         return;
128
129     if (hasAttribute(SVGNames::xAttr))
130         filterEffect->setHasX(true);
131     if (hasAttribute(SVGNames::yAttr))
132         filterEffect->setHasY(true);
133     if (hasAttribute(SVGNames::widthAttr))
134         filterEffect->setHasWidth(true);
135     if (hasAttribute(SVGNames::heightAttr))
136         filterEffect->setHasHeight(true);
137 }
138
139 RenderPtr<RenderElement> SVGFilterPrimitiveStandardAttributes::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
140 {
141     return createRenderer<RenderSVGResourceFilterPrimitive>(*this, WTFMove(style));
142 }
143
144 bool SVGFilterPrimitiveStandardAttributes::rendererIsNeeded(const RenderStyle& style)
145 {
146     if (parentNode() && (parentNode()->hasTagName(SVGNames::filterTag)))
147         return SVGElement::rendererIsNeeded(style);
148
149     return false;
150 }
151
152 void invalidateFilterPrimitiveParent(SVGElement* element)
153 {
154     if (!element)
155         return;
156
157     ContainerNode* parent = element->parentNode();
158
159     if (!parent)
160         return;
161
162     RenderElement* renderer = parent->renderer();
163     if (!renderer || !renderer->isSVGResourceFilterPrimitive())
164         return;
165
166     RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, false);
167 }
168
169 }