Separate render tree updating from style resolve
[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, 2014 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 #ifndef SVGElement_h
24 #define SVGElement_h
25
26 #include "CSSPropertyNames.h"
27 #include "SVGAnimatedString.h"
28 #include "SVGLangSpace.h"
29 #include "SVGLocatable.h"
30 #include "SVGNames.h"
31 #include "SVGParsingError.h"
32 #include "SVGPropertyInfo.h"
33 #include "StyledElement.h"
34 #include "Timer.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/HashSet.h>
37
38 namespace WebCore {
39
40 class AffineTransform;
41 class CSSCursorImageValue;
42 class CSSStyleDeclaration;
43 class CSSValue;
44 class Document;
45 class SVGAttributeToPropertyMap;
46 class SVGCursorElement;
47 class SVGDocumentExtensions;
48 class SVGElementRareData;
49 class SVGSVGElement;
50 class SVGUseElement;
51
52 void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName);
53
54 class SVGElement : public StyledElement, public SVGLangSpace {
55 public:
56     bool isOutermostSVGSVGElement() const;
57
58     String xmlbase() const;
59     void setXmlbase(const String&, ExceptionCode&);
60
61     SVGSVGElement* ownerSVGElement() const;
62     SVGElement* viewportElement() const;
63
64     String title() const override;
65     static bool isAnimatableCSSProperty(const QualifiedName&);
66     bool isPresentationAttributeWithSVGDOM(const QualifiedName&);
67     bool isKnownAttribute(const QualifiedName&);
68     RefPtr<CSSValue> getPresentationAttribute(const String& name);
69     virtual bool supportsMarkers() const { return false; }
70     bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
71     virtual bool needsPendingResourceHandling() const { return true; }
72     bool instanceUpdatesBlocked() const;
73     void setInstanceUpdatesBlocked(bool);
74     virtual AffineTransform localCoordinateSpaceTransform(SVGLocatable::CTMScope) const;
75
76     virtual bool isSVGGraphicsElement() const { return false; }
77     virtual bool isFilterEffect() const { return false; }
78     virtual bool isGradientStop() const { return false; }
79     virtual bool isTextContent() const { return false; }
80     virtual bool isSMILElement() const { return false; }
81
82     // For SVGTests
83     virtual bool isValid() const { return true; }
84
85     virtual void svgAttributeChanged(const QualifiedName&);
86
87     Vector<AnimatedPropertyType> animatedPropertyTypesForAttribute(const QualifiedName&);
88
89     void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
90     void sendSVGLoadEventIfPossibleAsynchronously();
91     void svgLoadEventTimerFired();
92     virtual Timer* svgLoadEventTimer();
93
94     virtual AffineTransform* supplementalTransform() { return 0; }
95
96     void invalidateSVGAttributes() { ensureUniqueElementData().setAnimatedSVGAttributesAreDirty(true); }
97     void invalidateSVGPresentationAttributeStyle()
98     {
99         ensureUniqueElementData().setPresentationAttributeStyleIsDirty(true);
100         // Trigger style recalculation for "elements as resource" (e.g. referenced by feImage).
101         setNeedsStyleRecalc(InlineStyleChange);
102     }
103
104     // The instances of an element are clones made in shadow trees to implement <use>.
105     const HashSet<SVGElement*>& instances() const;
106
107     bool getBoundingBox(FloatRect&, SVGLocatable::StyleUpdateStrategy = SVGLocatable::AllowStyleUpdate);
108
109     void setCursorElement(SVGCursorElement*);
110     void cursorElementRemoved();
111     void setCursorImageValue(CSSCursorImageValue*);
112     void cursorImageValueRemoved();
113
114     SVGElement* correspondingElement() const;
115     SVGUseElement* correspondingUseElement() const;
116
117     void setCorrespondingElement(SVGElement*);
118
119     void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
120     static void synchronizeAllAnimatedSVGAttribute(SVGElement*);
121  
122     Optional<ElementStyle> resolveCustomStyle(RenderStyle& parentStyle, RenderStyle* shadowHostStyle) override;
123
124     static void synchronizeRequiredFeatures(SVGElement* contextElement);
125     static void synchronizeRequiredExtensions(SVGElement* contextElement);
126     static void synchronizeSystemLanguage(SVGElement* contextElement);
127
128     virtual void synchronizeRequiredFeatures() { }
129     virtual void synchronizeRequiredExtensions() { }
130     virtual void synchronizeSystemLanguage() { }
131
132     static QualifiedName animatableAttributeForName(const AtomicString&);
133 #ifndef NDEBUG
134     bool isAnimatableAttribute(const QualifiedName&) const;
135 #endif
136
137     MutableStyleProperties* animatedSMILStyleProperties() const;
138     MutableStyleProperties& ensureAnimatedSMILStyleProperties();
139     void setUseOverrideComputedStyle(bool);
140
141     virtual bool haveLoadedRequiredResources();
142
143     bool addEventListener(const AtomicString& eventType, RefPtr<EventListener>&&, bool useCapture) override;
144     bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) override;
145     bool hasFocusEventListeners() const;
146
147 #if ENABLE(CSS_REGIONS)
148     bool shouldMoveToFlowThread(const RenderStyle&) const override;
149 #endif
150
151     bool hasTagName(const SVGQualifiedName& name) const { return hasLocalName(name.localName()); }
152     int tabIndex() const override;
153
154     void callClearTarget() { clearTarget(); }
155
156     class InstanceUpdateBlocker;
157
158 protected:
159     SVGElement(const QualifiedName&, Document&);
160     virtual ~SVGElement();
161
162     bool isMouseFocusable() const override;
163     bool supportsFocus() const override { return false; }
164
165     bool rendererIsNeeded(const RenderStyle&) override;
166     void parseAttribute(const QualifiedName&, const AtomicString&) override;
167
168     void finishParsingChildren() override;
169     void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
170     bool childShouldCreateRenderer(const Node&) const override;
171
172     SVGElementRareData& ensureSVGRareData();
173
174     void reportAttributeParsingError(SVGParsingError, const QualifiedName&, const AtomicString&);
175     static CSSPropertyID cssPropertyIdForSVGAttributeName(const QualifiedName&);
176
177     bool isPresentationAttribute(const QualifiedName&) const override;
178     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;
179     InsertionNotificationRequest insertedInto(ContainerNode&) override;
180     void removedFrom(ContainerNode&) override;
181     void childrenChanged(const ChildChange&) override;
182     virtual bool selfHasRelativeLengths() const { return false; }
183     void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); }
184     void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*);
185
186     bool willRecalcStyle(Style::Change) override;
187
188     class InstanceInvalidationGuard;
189
190 private:
191     RenderStyle* computedStyle(PseudoId = NOPSEUDO) final;
192
193     virtual bool isSupported(StringImpl* feature, StringImpl* version) const;
194
195     virtual void clearTarget() { }
196
197     void buildPendingResourcesIfNeeded();
198     void accessKeyAction(bool sendMouseEvents) override;
199
200 #ifndef NDEBUG
201     virtual bool filterOutAnimatableAttribute(const QualifiedName&) const;
202 #endif
203
204     void invalidateInstances();
205
206     std::unique_ptr<SVGElementRareData> m_svgRareData;
207
208     HashSet<SVGElement*> m_elementsWithRelativeLengths;
209
210     BEGIN_DECLARE_ANIMATED_PROPERTIES_BASE(SVGElement)
211         DECLARE_ANIMATED_STRING(ClassName, className)
212     END_DECLARE_ANIMATED_PROPERTIES
213
214 };
215
216 class SVGElement::InstanceInvalidationGuard {
217 public:
218     InstanceInvalidationGuard(SVGElement&);
219     ~InstanceInvalidationGuard();
220 private:
221     SVGElement& m_element;
222 };
223
224 class SVGElement::InstanceUpdateBlocker {
225 public:
226     InstanceUpdateBlocker(SVGElement&);
227     ~InstanceUpdateBlocker();
228 private:
229     SVGElement& m_element;
230 };
231
232 struct SVGAttributeHashTranslator {
233     static unsigned hash(const QualifiedName& key)
234     {
235         if (key.hasPrefix()) {
236             QualifiedNameComponents components = { nullAtom.impl(), key.localName().impl(), key.namespaceURI().impl() };
237             return hashComponents(components);
238         }
239         return DefaultHash<QualifiedName>::Hash::hash(key);
240     }
241     static bool equal(const QualifiedName& a, const QualifiedName& b) { return a.matches(b); }
242 };
243
244 inline SVGElement::InstanceInvalidationGuard::InstanceInvalidationGuard(SVGElement& element)
245     : m_element(element)
246 {
247 }
248
249 inline SVGElement::InstanceInvalidationGuard::~InstanceInvalidationGuard()
250 {
251     m_element.invalidateInstances();
252 }
253
254 inline SVGElement::InstanceUpdateBlocker::InstanceUpdateBlocker(SVGElement& element)
255     : m_element(element)
256 {
257     m_element.setInstanceUpdatesBlocked(true);
258 }
259
260 inline SVGElement::InstanceUpdateBlocker::~InstanceUpdateBlocker()
261 {
262     m_element.setInstanceUpdatesBlocked(false);
263 }
264
265 inline bool Node::hasTagName(const SVGQualifiedName& name) const
266 {
267     return isSVGElement() && downcast<SVGElement>(*this).hasTagName(name);
268 }
269
270 } // namespace WebCore
271
272 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::SVGElement)
273     static bool isType(const WebCore::Node& node) { return node.isSVGElement(); }
274 SPECIALIZE_TYPE_TRAITS_END()
275
276 #include "SVGElementTypeHelpers.h"
277
278 #endif