Improve use of NeverDestroyed
[WebKit-https.git] / Source / WebCore / svg / SVGPatternElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
5  * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "SVGPatternElement.h"
25
26 #include "AffineTransform.h"
27 #include "Document.h"
28 #include "FloatConversion.h"
29 #include "GraphicsContext.h"
30 #include "ImageBuffer.h"
31 #include "PatternAttributes.h"
32 #include "RenderSVGContainer.h"
33 #include "RenderSVGResourcePattern.h"
34 #include "SVGFitToViewBox.h"
35 #include "SVGGraphicsElement.h"
36 #include "SVGNames.h"
37 #include "SVGRenderSupport.h"
38 #include "SVGStringList.h"
39 #include "SVGTransformable.h"
40 #include "XLinkNames.h"
41 #include <wtf/NeverDestroyed.h>
42
43 namespace WebCore {
44
45 // Animated property definitions
46 DEFINE_ANIMATED_LENGTH(SVGPatternElement, SVGNames::xAttr, X, x)
47 DEFINE_ANIMATED_LENGTH(SVGPatternElement, SVGNames::yAttr, Y, y)
48 DEFINE_ANIMATED_LENGTH(SVGPatternElement, SVGNames::widthAttr, Width, width)
49 DEFINE_ANIMATED_LENGTH(SVGPatternElement, SVGNames::heightAttr, Height, height)
50 DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternUnitsAttr, PatternUnits, patternUnits, SVGUnitTypes::SVGUnitType)
51 DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternContentUnitsAttr, PatternContentUnits, patternContentUnits, SVGUnitTypes::SVGUnitType)
52 DEFINE_ANIMATED_TRANSFORM_LIST(SVGPatternElement, SVGNames::patternTransformAttr, PatternTransform, patternTransform) 
53 DEFINE_ANIMATED_STRING(SVGPatternElement, XLinkNames::hrefAttr, Href, href)
54 DEFINE_ANIMATED_BOOLEAN(SVGPatternElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
55 DEFINE_ANIMATED_RECT(SVGPatternElement, SVGNames::viewBoxAttr, ViewBox, viewBox)
56 DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGPatternElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio) 
57
58 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPatternElement)
59     REGISTER_LOCAL_ANIMATED_PROPERTY(x)
60     REGISTER_LOCAL_ANIMATED_PROPERTY(y)
61     REGISTER_LOCAL_ANIMATED_PROPERTY(width)
62     REGISTER_LOCAL_ANIMATED_PROPERTY(height)
63     REGISTER_LOCAL_ANIMATED_PROPERTY(patternUnits)
64     REGISTER_LOCAL_ANIMATED_PROPERTY(patternContentUnits)
65     REGISTER_LOCAL_ANIMATED_PROPERTY(patternTransform)
66     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
67     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
68     REGISTER_LOCAL_ANIMATED_PROPERTY(viewBox)
69     REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio) 
70     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
71     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
72 END_REGISTER_ANIMATED_PROPERTIES
73
74 inline SVGPatternElement::SVGPatternElement(const QualifiedName& tagName, Document& document)
75     : SVGElement(tagName, document)
76     , m_x(LengthModeWidth)
77     , m_y(LengthModeHeight)
78     , m_width(LengthModeWidth)
79     , m_height(LengthModeHeight)
80     , m_patternUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
81     , m_patternContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
82 {
83     ASSERT(hasTagName(SVGNames::patternTag));
84     registerAnimatedPropertiesForSVGPatternElement();
85 }
86
87 Ref<SVGPatternElement> SVGPatternElement::create(const QualifiedName& tagName, Document& document)
88 {
89     return adoptRef(*new SVGPatternElement(tagName, document));
90 }
91
92 bool SVGPatternElement::isSupportedAttribute(const QualifiedName& attrName)
93 {
94     static const auto supportedAttributes = makeNeverDestroyed([] {
95         HashSet<QualifiedName> set;
96         SVGURIReference::addSupportedAttributes(set);
97         SVGTests::addSupportedAttributes(set);
98         SVGLangSpace::addSupportedAttributes(set);
99         SVGExternalResourcesRequired::addSupportedAttributes(set);
100         SVGFitToViewBox::addSupportedAttributes(set);
101         set.add({
102             SVGNames::patternUnitsAttr, SVGNames::patternContentUnitsAttr, SVGNames::patternTransformAttr,
103             SVGNames::xAttr, SVGNames::yAttr, SVGNames::widthAttr, SVGNames::heightAttr,
104         });
105         return set;
106     }());
107     return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
108 }
109
110 void SVGPatternElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
111 {
112     if (name == SVGNames::patternUnitsAttr) {
113         auto propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
114         if (propertyValue > 0)
115             setPatternUnitsBaseValue(propertyValue);
116         return;
117     }
118     if (name == SVGNames::patternContentUnitsAttr) {
119         auto propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
120         if (propertyValue > 0)
121             setPatternContentUnitsBaseValue(propertyValue);
122         return;
123     }
124     if (name == SVGNames::patternTransformAttr) {
125         SVGTransformListValues newList;
126         newList.parse(value);
127         detachAnimatedPatternTransformListWrappers(newList.size());
128         setPatternTransformBaseValue(newList);
129         return;
130     }
131
132     SVGParsingError parseError = NoError;
133
134     if (name == SVGNames::xAttr)
135         setXBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError));
136     else if (name == SVGNames::yAttr)
137         setYBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError));
138     else if (name == SVGNames::widthAttr)
139         setWidthBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
140     else if (name == SVGNames::heightAttr)
141         setHeightBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
142
143     reportAttributeParsingError(parseError, name, value);
144
145     SVGElement::parseAttribute(name, value);
146     SVGURIReference::parseAttribute(name, value);
147     SVGTests::parseAttribute(name, value);
148     SVGExternalResourcesRequired::parseAttribute(name, value);
149     SVGFitToViewBox::parseAttribute(this, name, value);
150 }
151
152 void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName)
153 {
154     if (!isSupportedAttribute(attrName)) {
155         SVGElement::svgAttributeChanged(attrName);
156         return;
157     }
158
159     InstanceInvalidationGuard guard(*this);
160
161     if (attrName == SVGNames::xAttr
162         || attrName == SVGNames::yAttr
163         || attrName == SVGNames::widthAttr
164         || attrName == SVGNames::heightAttr) {
165         invalidateSVGPresentationAttributeStyle();
166         return;
167     }
168
169     if (RenderObject* object = renderer())
170         object->setNeedsLayout();
171 }
172
173 void SVGPatternElement::childrenChanged(const ChildChange& change)
174 {
175     SVGElement::childrenChanged(change);
176
177     if (change.source == ChildChangeSourceParser)
178         return;
179
180     if (RenderObject* object = renderer())
181         object->setNeedsLayout();
182 }
183
184 RenderPtr<RenderElement> SVGPatternElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
185 {
186     return createRenderer<RenderSVGResourcePattern>(*this, WTFMove(style));
187 }
188
189 void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
190 {
191     if (!attributes.hasX() && hasAttribute(SVGNames::xAttr))
192         attributes.setX(x());
193
194     if (!attributes.hasY() && hasAttribute(SVGNames::yAttr))
195         attributes.setY(y());
196
197     if (!attributes.hasWidth() && hasAttribute(SVGNames::widthAttr))
198         attributes.setWidth(width());
199
200     if (!attributes.hasHeight() && hasAttribute(SVGNames::heightAttr))
201         attributes.setHeight(height());
202
203     if (!attributes.hasViewBox() && hasAttribute(SVGNames::viewBoxAttr) && viewBoxIsValid())
204         attributes.setViewBox(viewBox());
205
206     if (!attributes.hasPreserveAspectRatio() && hasAttribute(SVGNames::preserveAspectRatioAttr))
207         attributes.setPreserveAspectRatio(preserveAspectRatio());
208
209     if (!attributes.hasPatternUnits() && hasAttribute(SVGNames::patternUnitsAttr))
210         attributes.setPatternUnits(patternUnits());
211
212     if (!attributes.hasPatternContentUnits() && hasAttribute(SVGNames::patternContentUnitsAttr))
213         attributes.setPatternContentUnits(patternContentUnits());
214
215     if (!attributes.hasPatternTransform() && hasAttribute(SVGNames::patternTransformAttr)) {
216         AffineTransform transform;
217         patternTransform().concatenate(transform);
218         attributes.setPatternTransform(transform);
219     }
220
221     if (!attributes.hasPatternContentElement() && childElementCount())
222         attributes.setPatternContentElement(this);
223 }
224
225 AffineTransform SVGPatternElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
226 {
227     AffineTransform matrix;
228     patternTransform().concatenate(matrix);
229     return matrix;
230 }
231
232 Ref<SVGStringList> SVGPatternElement::requiredFeatures()
233 {
234     return SVGTests::requiredFeatures(*this);
235 }
236
237 Ref<SVGStringList> SVGPatternElement::requiredExtensions()
238
239     return SVGTests::requiredExtensions(*this);
240 }
241
242 Ref<SVGStringList> SVGPatternElement::systemLanguage()
243 {
244     return SVGTests::systemLanguage(*this);
245 }
246
247 }