1 /*
2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 * Copyright (C) 2009, 2014 Apple Inc. All rights reserved.
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 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_H_
23 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_H_
24
25 #include "base/macros.h"
26 #include "third_party/blink/renderer/core/core_export.h"
27 #include "third_party/blink/renderer/core/dom/element.h"
28 #include "third_party/blink/renderer/core/svg/properties/svg_property_info.h"
29 #include "third_party/blink/renderer/core/svg/svg_parsing_error.h"
30 #include "third_party/blink/renderer/core/svg_names.h"
31 #include "third_party/blink/renderer/platform/heap/handle.h"
32 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
33 #include "third_party/blink/renderer/platform/wtf/casting.h"
34 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
35
36 namespace blink {
37
38 class AffineTransform;
39 class Document;
40 class ElementSMILAnimations;
41 class ExecutionContext;
42 class SVGAnimatedPropertyBase;
43 class SubtreeLayoutScope;
44 class SVGAnimatedString;
45 class SVGElement;
46 class SVGElementRareData;
47 class SVGElementResourceClient;
48 class SVGPropertyBase;
49 class SVGSVGElement;
50 class SVGUseElement;
51
52 typedef HeapHashSet<Member<SVGElement>> SVGElementSet;
53
54 class CORE_EXPORT SVGElement : public Element {
55 DEFINE_WRAPPERTYPEINFO();
56
57 public:
58 ~SVGElement() override;
59
SupportsFocus()60 bool SupportsFocus() const override { return false; }
61
62 bool IsOutermostSVGSVGElement() const;
63
HasTagName(const SVGQualifiedName & name)64 bool HasTagName(const SVGQualifiedName& name) const {
65 return HasLocalName(name.LocalName());
66 }
67
68 String title() const override;
HasRelativeLengths()69 bool HasRelativeLengths() const {
70 return !elements_with_relative_lengths_.IsEmpty();
71 }
72 static bool IsAnimatableCSSProperty(const QualifiedName&);
73
74 enum ApplyMotionTransform {
75 kExcludeMotionTransform,
76 kIncludeMotionTransform
77 };
78 bool HasTransform(ApplyMotionTransform) const;
79 AffineTransform CalculateTransform(ApplyMotionTransform) const;
80
81 enum CTMScope {
82 kNearestViewportScope, // Used by SVGGraphicsElement::getCTM()
83 kScreenScope, // Used by SVGGraphicsElement::getScreenCTM()
84 kAncestorScope // Used by SVGSVGElement::get{Enclosure|Intersection}List()
85 };
86 virtual AffineTransform LocalCoordinateSpaceTransform(CTMScope) const;
87
88 bool InstanceUpdatesBlocked() const;
89 void SetInstanceUpdatesBlocked(bool);
90
91 // Records the SVG element as having a Web Animation on an SVG attribute that
92 // needs applying.
93 void SetWebAnimationsPending();
94 void ApplyActiveWebAnimations();
95
96 void EnsureAttributeAnimValUpdated();
97
98 void SetWebAnimatedAttribute(const QualifiedName& attribute,
99 SVGPropertyBase*);
100 void ClearWebAnimatedAttributes();
101
102 ElementSMILAnimations* GetSMILAnimations();
103 ElementSMILAnimations& EnsureSMILAnimations();
104
105 void SetAnimatedAttribute(const QualifiedName&, SVGPropertyBase*);
106 void ClearAnimatedAttribute(const QualifiedName&);
107
108 SVGSVGElement* ownerSVGElement() const;
109 SVGElement* viewportElement() const;
110
IsSVGGeometryElement()111 virtual bool IsSVGGeometryElement() const { return false; }
IsSVGGraphicsElement()112 virtual bool IsSVGGraphicsElement() const { return false; }
IsFilterEffect()113 virtual bool IsFilterEffect() const { return false; }
IsTextContent()114 virtual bool IsTextContent() const { return false; }
IsTextPositioning()115 virtual bool IsTextPositioning() const { return false; }
IsStructurallyExternal()116 virtual bool IsStructurallyExternal() const { return false; }
117
118 // For SVGTests
IsValid()119 virtual bool IsValid() const { return true; }
120
121 virtual void SvgAttributeChanged(const QualifiedName&);
122 void SvgAttributeBaseValChanged(const QualifiedName&);
123
124 SVGAnimatedPropertyBase* PropertyFromAttribute(
125 const QualifiedName& attribute_name) const;
126 static AnimatedPropertyType AnimatedPropertyTypeForCSSAttribute(
127 const QualifiedName& attribute_name);
128
129 void SendSVGLoadEventToSelfAndAncestorChainIfPossible();
130 bool SendSVGLoadEventIfPossible();
131
AnimateMotionTransform()132 virtual AffineTransform* AnimateMotionTransform() { return nullptr; }
133
InvalidateSVGAttributes()134 void InvalidateSVGAttributes() {
135 EnsureUniqueElementData().SetAnimatedSvgAttributesAreDirty(true);
136 }
InvalidateSVGPresentationAttributeStyle()137 void InvalidateSVGPresentationAttributeStyle() {
138 EnsureUniqueElementData().SetPresentationAttributeStyleIsDirty(true);
139 }
140
141 const HeapHashSet<WeakMember<SVGElement>>& InstancesForElement() const;
142 void MapInstanceToElement(SVGElement*);
143 void RemoveInstanceMapping(SVGElement*);
144
145 SVGElement* CorrespondingElement() const;
146 void SetCorrespondingElement(SVGElement*);
147 SVGUseElement* GeneratingUseElement() const;
148
149 void SynchronizeAnimatedSVGAttribute(const QualifiedName&) const;
150
151 scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() final;
152 bool LayoutObjectIsNeeded(const ComputedStyle&) const override;
153
154 #if DCHECK_IS_ON()
155 virtual bool IsAnimatableAttribute(const QualifiedName&) const;
156 #endif
157
158 MutableCSSPropertyValueSet* AnimatedSMILStyleProperties() const;
159 MutableCSSPropertyValueSet* EnsureAnimatedSMILStyleProperties();
160 void SetUseOverrideComputedStyle(bool);
161
162 virtual bool HaveLoadedRequiredResources();
163
164 void InvalidateRelativeLengthClients(SubtreeLayoutScope* = nullptr);
165
166 void AddToPropertyMap(SVGAnimatedPropertyBase*);
167
className()168 SVGAnimatedString* className() { return class_name_.Get(); }
169
170 bool InUseShadowTree() const;
171
172 void AddReferenceTo(SVGElement*);
173 template <typename InvalidationFunction>
174 void NotifyIncomingReferences(InvalidationFunction&&);
175 void RebuildAllIncomingReferences();
176 void RemoveAllIncomingReferences();
177 void RemoveAllOutgoingReferences();
178
179 SVGElementResourceClient* GetSVGResourceClient();
180 SVGElementResourceClient& EnsureSVGResourceClient();
181
182 class InvalidationGuard {
183 STACK_ALLOCATED();
184
185 public:
InvalidationGuard(SVGElement * element)186 InvalidationGuard(SVGElement* element) : element_(element) {}
~InvalidationGuard()187 ~InvalidationGuard() { element_->InvalidateInstances(); }
188
189 private:
190 SVGElement* element_;
191 DISALLOW_COPY_AND_ASSIGN(InvalidationGuard);
192 };
193
194 class InstanceUpdateBlocker {
195 STACK_ALLOCATED();
196
197 public:
198 InstanceUpdateBlocker(SVGElement* target_element);
199 ~InstanceUpdateBlocker();
200
201 private:
202 SVGElement* target_element_;
203 DISALLOW_COPY_AND_ASSIGN(InstanceUpdateBlocker);
204 };
205
206 void InvalidateInstances();
207 void SetNeedsStyleRecalcForInstances(StyleChangeType,
208 const StyleChangeReasonForTracing&);
209
210 void Trace(Visitor*) override;
211
212 static const AtomicString& EventParameterName();
213
214 bool IsPresentationAttribute(const QualifiedName&) const override;
215
216 bool HasSVGParent() const;
217
218 protected:
219 SVGElement(const QualifiedName&,
220 Document&,
221 ConstructionType = kCreateSVGElement);
222
223 void ParseAttribute(const AttributeModificationParams&) override;
224 void AttributeChanged(const AttributeModificationParams&) override;
225
226 void CollectStyleForPresentationAttribute(
227 const QualifiedName&,
228 const AtomicString&,
229 MutableCSSPropertyValueSet*) override;
230
231 InsertionNotificationRequest InsertedInto(ContainerNode&) override;
232 void RemovedFrom(ContainerNode&) override;
233 void ChildrenChanged(const ChildrenChange&) override;
234
235 void DetachLayoutTree(bool performing_reattach) override;
236
237 static CSSPropertyID CssPropertyIdForSVGAttributeName(const ExecutionContext*,
238 const QualifiedName&);
UpdateRelativeLengthsInformation()239 void UpdateRelativeLengthsInformation() {
240 UpdateRelativeLengthsInformation(SelfHasRelativeLengths(), this);
241 }
242 void UpdateRelativeLengthsInformation(bool has_relative_lengths, SVGElement*);
243 static void MarkForLayoutAndParentResourceInvalidation(LayoutObject&);
244
SelfHasRelativeLengths()245 virtual bool SelfHasRelativeLengths() const { return false; }
246
247 SVGElementSet* SetOfIncomingReferences() const;
248
249 SVGElementRareData* EnsureSVGRareData();
HasSVGRareData()250 inline bool HasSVGRareData() const { return svg_rare_data_; }
SvgRareData()251 inline SVGElementRareData* SvgRareData() const {
252 DCHECK(svg_rare_data_);
253 return svg_rare_data_.Get();
254 }
255
256 void ReportAttributeParsingError(SVGParsingError,
257 const QualifiedName&,
258 const AtomicString&);
259 bool HasFocusEventListeners() const;
260
261 void AddedEventListener(const AtomicString& event_type,
262 RegisteredEventListener&) final;
263 void RemovedEventListener(const AtomicString& event_type,
264 const RegisteredEventListener&) final;
265
266 void AccessKeyAction(bool send_mouse_events) override;
267
268 private:
269 bool IsSVGElement() const =
270 delete; // This will catch anyone doing an unnecessary check.
271 bool IsStyledElement() const =
272 delete; // This will catch anyone doing an unnecessary check.
273
274 const ComputedStyle* EnsureComputedStyle(PseudoId = kPseudoIdNone);
275 const ComputedStyle* VirtualEnsureComputedStyle(
276 PseudoId pseudo_element_specifier = kPseudoIdNone) final {
277 return EnsureComputedStyle(pseudo_element_specifier);
278 }
279 void WillRecalcStyle(const StyleRecalcChange) override;
280 static SVGElementSet& GetDependencyTraversalVisitedSet();
281
282 HeapHashSet<WeakMember<SVGElement>> elements_with_relative_lengths_;
283
284 typedef HeapHashMap<QualifiedName, Member<SVGAnimatedPropertyBase>>
285 AttributeToPropertyMap;
286 AttributeToPropertyMap attribute_to_property_map_;
287
288 #if DCHECK_IS_ON()
289 bool in_relative_length_clients_invalidation_ = false;
290 #endif
291
292 Member<SVGElementRareData> svg_rare_data_;
293 Member<SVGAnimatedString> class_name_;
294 };
295
296 template <typename InvalidationFunction>
NotifyIncomingReferences(InvalidationFunction && invalidation_function)297 void SVGElement::NotifyIncomingReferences(
298 InvalidationFunction&& invalidation_function) {
299 SVGElementSet* dependencies = SetOfIncomingReferences();
300 if (!dependencies)
301 return;
302
303 // We allow cycles in the reference graph in order to avoid expensive
304 // adjustments on changes, so we need to break possible cycles here.
305 SVGElementSet& invalidating_dependencies = GetDependencyTraversalVisitedSet();
306
307 for (SVGElement* element : *dependencies) {
308 if (!element->GetLayoutObject())
309 continue;
310 if (UNLIKELY(!invalidating_dependencies.insert(element).is_new_entry)) {
311 // Reference cycle: we are in process of invalidating this dependant.
312 continue;
313 }
314 invalidation_function(*element);
315 invalidating_dependencies.erase(element);
316 }
317 }
318
319 struct SVGAttributeHashTranslator {
320 STATIC_ONLY(SVGAttributeHashTranslator);
GetHashSVGAttributeHashTranslator321 static unsigned GetHash(const QualifiedName& key) {
322 if (key.HasPrefix()) {
323 QualifiedNameComponents components = {g_null_atom.Impl(),
324 key.LocalName().Impl(),
325 key.NamespaceURI().Impl()};
326 return HashComponents(components);
327 }
328 return DefaultHash<QualifiedName>::Hash::GetHash(key);
329 }
EqualSVGAttributeHashTranslator330 static bool Equal(const QualifiedName& a, const QualifiedName& b) {
331 return a.Matches(b);
332 }
333 };
334
335 template <typename T>
336 bool IsElementOfType(const SVGElement&);
337 template <>
338 inline bool IsElementOfType<const SVGElement>(const SVGElement&) {
339 return true;
340 }
341 template <>
342 inline bool IsElementOfType<const SVGElement>(const Node& node) {
343 return IsA<SVGElement>(node);
344 }
345 template <>
346 struct DowncastTraits<SVGElement> {
347 static bool AllowFrom(const Node& node) { return node.IsSVGElement(); }
348 };
349 inline bool Node::HasTagName(const SVGQualifiedName& name) const {
350 auto* svg_element = DynamicTo<SVGElement>(this);
351 return svg_element && svg_element->HasTagName(name);
352 }
353
354 } // namespace blink
355
356 #include "third_party/blink/renderer/core/svg_element_type_helpers.h"
357
358 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_ELEMENT_H_
359