Remove the SVG elements' attributes macros
[WebKit-https.git] / Source / WebCore / svg / SVGElement.h
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  * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
5  * Copyright (C) 2013 Samsung Electronics. 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 #pragma once
24
25 #include "SVGAnimatedString.h"
26 #include "SVGAttributeOwnerProxy.h"
27 #include "SVGLangSpace.h"
28 #include "SVGLocatable.h"
29 #include "SVGNames.h"
30 #include "SVGParsingError.h"
31 #include "StyledElement.h"
32 #include <wtf/HashMap.h>
33 #include <wtf/HashSet.h>
34
35 namespace WebCore {
36
37 class AffineTransform;
38 class CSSStyleDeclaration;
39 class DeprecatedCSSOMValue;
40 class Document;
41 class SVGDocumentExtensions;
42 class SVGElementRareData;
43 class SVGSVGElement;
44 class SVGUseElement;
45
46 void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName);
47
48 class SVGElement : public StyledElement, public SVGLangSpace {
49     WTF_MAKE_ISO_ALLOCATED(SVGElement);
50 public:
51     bool isOutermostSVGSVGElement() const;
52
53     SVGSVGElement* ownerSVGElement() const;
54     SVGElement* viewportElement() const;
55
56     String title() const override;
57     static bool isAnimatableCSSProperty(const QualifiedName&);
58     bool isPresentationAttributeWithSVGDOM(const QualifiedName&);
59     RefPtr<DeprecatedCSSOMValue> getPresentationAttribute(const String& name);
60     virtual bool supportsMarkers() const { return false; }
61     bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
62     virtual bool needsPendingResourceHandling() const { return true; }
63     bool instanceUpdatesBlocked() const;
64     void setInstanceUpdatesBlocked(bool);
65     virtual AffineTransform localCoordinateSpaceTransform(SVGLocatable::CTMScope) const;
66
67     virtual bool isSVGGraphicsElement() const { return false; }
68     virtual bool isFilterEffect() const { return false; }
69     virtual bool isGradientStop() const { return false; }
70     virtual bool isTextContent() const { return false; }
71     virtual bool isSMILElement() const { return false; }
72
73     // For SVGTests
74     virtual bool isValid() const { return true; }
75
76     virtual void svgAttributeChanged(const QualifiedName&);
77
78     Vector<AnimatedPropertyType> animatedPropertyTypesForAttribute(const QualifiedName&);
79
80     void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
81     void sendSVGLoadEventIfPossibleAsynchronously();
82     void svgLoadEventTimerFired();
83     virtual Timer* svgLoadEventTimer();
84
85     virtual AffineTransform* supplementalTransform() { return nullptr; }
86
87     void invalidateSVGAttributes() { ensureUniqueElementData().setAnimatedSVGAttributesAreDirty(true); }
88     void invalidateSVGPresentationAttributeStyle()
89     {
90         ensureUniqueElementData().setPresentationAttributeStyleIsDirty(true);
91         // Trigger style recalculation for "elements as resource" (e.g. referenced by feImage).
92         invalidateStyle();
93     }
94
95     // The instances of an element are clones made in shadow trees to implement <use>.
96     const HashSet<SVGElement*>& instances() const;
97
98     bool getBoundingBox(FloatRect&, SVGLocatable::StyleUpdateStrategy = SVGLocatable::AllowStyleUpdate);
99
100     SVGElement* correspondingElement() const;
101     RefPtr<SVGUseElement> correspondingUseElement() const;
102
103     void setCorrespondingElement(SVGElement*);
104
105     void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
106     static void synchronizeAllAnimatedSVGAttribute(SVGElement*);
107  
108     std::optional<ElementStyle> resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle) override;
109
110     static QualifiedName animatableAttributeForName(const AtomicString&);
111 #ifndef NDEBUG
112     bool isAnimatableAttribute(const QualifiedName&) const;
113 #endif
114
115     MutableStyleProperties* animatedSMILStyleProperties() const;
116     MutableStyleProperties& ensureAnimatedSMILStyleProperties();
117     void setUseOverrideComputedStyle(bool);
118
119     virtual bool haveLoadedRequiredResources();
120
121     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
122     bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
123     bool hasFocusEventListeners() const;
124
125     bool hasTagName(const SVGQualifiedName& name) const { return hasLocalName(name.localName()); }
126     int tabIndex() const override;
127
128     void callClearTarget() { clearTarget(); }
129
130     class InstanceUpdateBlocker;
131     class InstanceInvalidationGuard;
132
133     // The definition of the owner proxy has to match the class inheritance but we are interested in the SVG objects only.
134     using AttributeOwnerProxy = SVGAttributeOwnerProxyImpl<SVGElement, SVGLangSpace>;
135     static auto& attributeRegistry() { return AttributeOwnerProxy::attributeRegistry(); }
136     static bool isKnownAttribute(const QualifiedName& attributeName) { return AttributeOwnerProxy::isKnownAttribute(attributeName); }
137     static void registerAttributes();
138
139     // A super class will override this function to return its owner proxy. The attributes of the super class will
140     // be accessible through the registry of the owner proxy.
141     virtual const SVGAttributeOwnerProxy& attributeOwnerProxy() const { return m_attributeOwnerProxy; }
142
143     // Helper functions which return info for the super class' attributes.
144     void synchronizeAttribute(const QualifiedName& name) { attributeOwnerProxy().synchronizeAttribute(name); }
145     void synchronizeAttributes() { attributeOwnerProxy().synchronizeAttributes(); }
146     Vector<AnimatedPropertyType> animatedTypes(const QualifiedName& attributeName) const { return attributeOwnerProxy().animatedTypes(attributeName); }
147     RefPtr<SVGAnimatedProperty> lookupAnimatedProperty(const SVGAttribute& attribute) const { return attributeOwnerProxy().lookupAnimatedProperty(attribute); }
148     RefPtr<SVGAnimatedProperty> lookupOrCreateAnimatedProperty(const SVGAttribute& attribute) { return attributeOwnerProxy().lookupOrCreateAnimatedProperty(attribute); }
149     Vector<RefPtr<SVGAnimatedProperty>> lookupOrCreateAnimatedProperties(const QualifiedName& name) { return attributeOwnerProxy().lookupOrCreateAnimatedProperties(name); }
150
151     // These are needed for the RenderTree, animation and DOM.
152     const auto& className() const { return m_className.currentValue(attributeOwnerProxy()); }
153     auto classNameAnimated() { return m_className.animatedProperty(attributeOwnerProxy()); }
154
155 protected:
156     SVGElement(const QualifiedName&, Document&);
157     virtual ~SVGElement();
158
159     bool isMouseFocusable() const override;
160     bool supportsFocus() const override { return false; }
161
162     bool rendererIsNeeded(const RenderStyle&) override;
163     void parseAttribute(const QualifiedName&, const AtomicString&) override;
164
165     void finishParsingChildren() override;
166     void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
167     bool childShouldCreateRenderer(const Node&) const override;
168
169     SVGElementRareData& ensureSVGRareData();
170
171     void reportAttributeParsingError(SVGParsingError, const QualifiedName&, const AtomicString&);
172     static CSSPropertyID cssPropertyIdForSVGAttributeName(const QualifiedName&);
173
174     bool isPresentationAttribute(const QualifiedName&) const override;
175     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;
176     InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) override;
177     void removedFromAncestor(RemovalType, ContainerNode&) override;
178     void childrenChanged(const ChildChange&) override;
179     virtual bool selfHasRelativeLengths() const { return false; }
180     void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); }
181     void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*);
182
183     void willRecalcStyle(Style::Change) override;
184
185 private:
186     const RenderStyle* computedStyle(PseudoId = PseudoId::None) final;
187
188     virtual void clearTarget() { }
189
190     void buildPendingResourcesIfNeeded();
191     void accessKeyAction(bool sendMouseEvents) override;
192
193 #ifndef NDEBUG
194     virtual bool filterOutAnimatableAttribute(const QualifiedName&) const;
195 #endif
196
197     void invalidateInstances();
198
199     std::unique_ptr<SVGElementRareData> m_svgRareData;
200
201     HashSet<SVGElement*> m_elementsWithRelativeLengths;
202
203     AttributeOwnerProxy m_attributeOwnerProxy { *this };
204     SVGAnimatedStringAttribute m_className;
205 };
206
207 class SVGElement::InstanceInvalidationGuard {
208 public:
209     InstanceInvalidationGuard(SVGElement&);
210     ~InstanceInvalidationGuard();
211 private:
212     SVGElement& m_element;
213 };
214
215 class SVGElement::InstanceUpdateBlocker {
216 public:
217     InstanceUpdateBlocker(SVGElement&);
218     ~InstanceUpdateBlocker();
219 private:
220     SVGElement& m_element;
221 };
222
223 struct SVGAttributeHashTranslator {
224     static unsigned hash(const QualifiedName& key)
225     {
226         if (key.hasPrefix()) {
227             QualifiedNameComponents components = { nullAtom().impl(), key.localName().impl(), key.namespaceURI().impl() };
228             return hashComponents(components);
229         }
230         return DefaultHash<QualifiedName>::Hash::hash(key);
231     }
232     static bool equal(const QualifiedName& a, const QualifiedName& b) { return a.matches(b); }
233 };
234
235 inline SVGElement::InstanceInvalidationGuard::InstanceInvalidationGuard(SVGElement& element)
236     : m_element(element)
237 {
238 }
239
240 inline SVGElement::InstanceInvalidationGuard::~InstanceInvalidationGuard()
241 {
242     m_element.invalidateInstances();
243 }
244
245 inline SVGElement::InstanceUpdateBlocker::InstanceUpdateBlocker(SVGElement& element)
246     : m_element(element)
247 {
248     m_element.setInstanceUpdatesBlocked(true);
249 }
250
251 inline SVGElement::InstanceUpdateBlocker::~InstanceUpdateBlocker()
252 {
253     m_element.setInstanceUpdatesBlocked(false);
254 }
255
256 inline bool Node::hasTagName(const SVGQualifiedName& name) const
257 {
258     return isSVGElement() && downcast<SVGElement>(*this).hasTagName(name);
259 }
260
261 } // namespace WebCore
262
263 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::SVGElement)
264     static bool isType(const WebCore::Node& node) { return node.isSVGElement(); }
265 SPECIALIZE_TYPE_TRAITS_END()
266
267 #include "SVGElementTypeHelpers.h"