Have Document::accessSVGExtensions() return a reference
[WebKit-https.git] / Source / WebCore / svg / SVGPolyElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "SVGPolyElement.h"
23
24 #include "Attribute.h"
25 #include "Document.h"
26 #include "FloatPoint.h"
27 #include "RenderSVGPath.h"
28 #include "RenderSVGResource.h"
29 #include "SVGAnimatedPointList.h"
30 #include "SVGElementInstance.h"
31 #include "SVGNames.h"
32 #include "SVGParserUtilities.h"
33 #include <wtf/NeverDestroyed.h>
34
35 namespace WebCore {
36
37 // Define custom animated property 'points'.
38 const SVGPropertyInfo* SVGPolyElement::pointsPropertyInfo()
39 {
40     static const SVGPropertyInfo* s_propertyInfo = 0;
41     if (!s_propertyInfo) {
42         s_propertyInfo = new SVGPropertyInfo(AnimatedPoints,
43                                              PropertyIsReadWrite,
44                                              SVGNames::pointsAttr,
45                                              SVGNames::pointsAttr.localName(),
46                                              &SVGPolyElement::synchronizePoints,
47                                              &SVGPolyElement::lookupOrCreatePointsWrapper);
48     }
49     return s_propertyInfo;
50 }
51
52 // Animated property definitions
53 DEFINE_ANIMATED_BOOLEAN(SVGPolyElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
54
55 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPolyElement)
56     REGISTER_LOCAL_ANIMATED_PROPERTY(points)
57     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
58     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
59 END_REGISTER_ANIMATED_PROPERTIES
60
61 SVGPolyElement::SVGPolyElement(const QualifiedName& tagName, Document& document)
62     : SVGGraphicsElement(tagName, document)
63 {
64     registerAnimatedPropertiesForSVGPolyElement();    
65 }
66
67 bool SVGPolyElement::isSupportedAttribute(const QualifiedName& attrName)
68 {
69     static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes;
70     if (supportedAttributes.get().isEmpty()) {
71         SVGLangSpace::addSupportedAttributes(supportedAttributes);
72         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
73         supportedAttributes.get().add(SVGNames::pointsAttr);
74     }
75     return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName);
76 }
77
78 void SVGPolyElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
79 {
80     if (!isSupportedAttribute(name)) {
81         SVGGraphicsElement::parseAttribute(name, value);
82         return;
83     }
84
85     if (name == SVGNames::pointsAttr) {
86         SVGPointList newList;
87         if (!pointsListFromSVGData(newList, value))
88             document().accessSVGExtensions().reportError("Problem parsing points=\"" + value + "\"");
89
90         if (SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo()))
91             static_cast<SVGAnimatedPointList*>(wrapper)->detachListWrappers(newList.size());
92
93         m_points.value = newList;
94         return;
95     }
96
97     if (SVGLangSpace::parseAttribute(name, value))
98         return;
99     if (SVGExternalResourcesRequired::parseAttribute(name, value))
100         return;
101
102     ASSERT_NOT_REACHED();
103 }
104
105 void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName)
106 {
107     if (!isSupportedAttribute(attrName)) {
108         SVGGraphicsElement::svgAttributeChanged(attrName);
109         return;
110     }
111
112     SVGElementInstance::InvalidationGuard invalidationGuard(this);
113
114     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
115     if (!renderer)
116         return;
117
118     if (attrName == SVGNames::pointsAttr) {
119         renderer->setNeedsShapeUpdate();
120         RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
121         return;
122     }
123
124     if (SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
125         RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
126         return;
127     }
128
129     ASSERT_NOT_REACHED();
130 }
131
132 void SVGPolyElement::synchronizePoints(SVGElement* contextElement)
133 {
134     ASSERT(contextElement);
135     SVGPolyElement& ownerType = toSVGPolyElement(*contextElement);
136     if (!ownerType.m_points.shouldSynchronize)
137         return;
138     ownerType.m_points.synchronize(&ownerType, pointsPropertyInfo()->attributeName, ownerType.m_points.value.valueAsString());
139 }
140
141 PassRefPtr<SVGAnimatedProperty> SVGPolyElement::lookupOrCreatePointsWrapper(SVGElement* contextElement)
142 {
143     ASSERT(contextElement);
144     SVGPolyElement& ownerType = toSVGPolyElement(*contextElement);
145     return SVGAnimatedProperty::lookupOrCreateWrapper<SVGPolyElement, SVGAnimatedPointList, SVGPointList>
146         (&ownerType, pointsPropertyInfo(), ownerType.m_points.value);
147 }
148
149 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::points()
150 {
151     m_points.shouldSynchronize = true;
152     return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->baseVal());
153 }
154
155 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::animatedPoints()
156 {
157     m_points.shouldSynchronize = true;
158     return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal());
159 }
160
161 bool isSVGPolyElement(const Node& node)
162 {
163     return node.hasTagName(SVGNames::polygonTag) || node.hasTagName(SVGNames::polylineTag);
164 }
165
166 }