Add an argument indicating the type of insertion to Node::insertedInto
[WebKit-https.git] / Source / WebCore / svg / SVGElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org>
4  * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
7  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
8  * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "SVGElement.h"
28
29 #include "CSSPropertyParser.h"
30 #include "DeprecatedCSSOMValue.h"
31 #include "Document.h"
32 #include "ElementIterator.h"
33 #include "Event.h"
34 #include "EventNames.h"
35 #include "HTMLElement.h"
36 #include "HTMLNames.h"
37 #include "HTMLParserIdioms.h"
38 #include "RenderObject.h"
39 #include "RenderSVGResource.h"
40 #include "RenderSVGResourceFilter.h"
41 #include "RenderSVGResourceMasker.h"
42 #include "SVGDocumentExtensions.h"
43 #include "SVGElementRareData.h"
44 #include "SVGGraphicsElement.h"
45 #include "SVGImageElement.h"
46 #include "SVGNames.h"
47 #include "SVGRenderStyle.h"
48 #include "SVGRenderSupport.h"
49 #include "SVGSVGElement.h"
50 #include "SVGTitleElement.h"
51 #include "SVGUseElement.h"
52 #include "ShadowRoot.h"
53 #include "XLinkNames.h"
54 #include "XMLNames.h"
55 #include <wtf/Assertions.h>
56 #include <wtf/HashMap.h>
57 #include <wtf/NeverDestroyed.h>
58 #include <wtf/StdLibExtras.h>
59 #include <wtf/text/WTFString.h>
60
61
62 namespace WebCore {
63
64 // Animated property definitions
65 DEFINE_ANIMATED_STRING(SVGElement, HTMLNames::classAttr, ClassName, className)
66
67 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGElement)
68     REGISTER_LOCAL_ANIMATED_PROPERTY(className)
69 END_REGISTER_ANIMATED_PROPERTIES
70
71 static NEVER_INLINE HashMap<AtomicStringImpl*, CSSPropertyID> createAttributeNameToCSSPropertyIDMap()
72 {
73     using namespace HTMLNames;
74     using namespace SVGNames;
75
76     // This list should include all base CSS and SVG CSS properties which are exposed as SVG XML attributes.
77     static const QualifiedName* const attributeNames[] = {
78         &alignment_baselineAttr,
79         &baseline_shiftAttr,
80         &buffered_renderingAttr,
81         &clipAttr,
82         &clip_pathAttr,
83         &clip_ruleAttr,
84         &SVGNames::colorAttr,
85         &color_interpolationAttr,
86         &color_interpolation_filtersAttr,
87         &color_profileAttr,
88         &color_renderingAttr,
89         &cursorAttr,
90         &cxAttr,
91         &cyAttr,
92         &SVGNames::directionAttr,
93         &displayAttr,
94         &dominant_baselineAttr,
95         &enable_backgroundAttr,
96         &fillAttr,
97         &fill_opacityAttr,
98         &fill_ruleAttr,
99         &filterAttr,
100         &flood_colorAttr,
101         &flood_opacityAttr,
102         &font_familyAttr,
103         &font_sizeAttr,
104         &font_stretchAttr,
105         &font_styleAttr,
106         &font_variantAttr,
107         &font_weightAttr,
108         &glyph_orientation_horizontalAttr,
109         &glyph_orientation_verticalAttr,
110         &image_renderingAttr,
111         &SVGNames::heightAttr,
112         &kerningAttr,
113         &letter_spacingAttr,
114         &lighting_colorAttr,
115         &marker_endAttr,
116         &marker_midAttr,
117         &marker_startAttr,
118         &maskAttr,
119         &mask_typeAttr,
120         &opacityAttr,
121         &overflowAttr,
122         &paint_orderAttr,
123         &pointer_eventsAttr,
124         &rAttr,
125         &rxAttr,
126         &ryAttr,
127         &shape_renderingAttr,
128         &stop_colorAttr,
129         &stop_opacityAttr,
130         &strokeAttr,
131         &stroke_dasharrayAttr,
132         &stroke_dashoffsetAttr,
133         &stroke_linecapAttr,
134         &stroke_linejoinAttr,
135         &stroke_miterlimitAttr,
136         &stroke_opacityAttr,
137         &stroke_widthAttr,
138         &text_anchorAttr,
139         &text_decorationAttr,
140         &text_renderingAttr,
141         &unicode_bidiAttr,
142         &vector_effectAttr,
143         &visibilityAttr,
144         &SVGNames::widthAttr,
145         &word_spacingAttr,
146         &writing_modeAttr,
147         &xAttr,
148         &yAttr,
149     };
150
151     HashMap<AtomicStringImpl*, CSSPropertyID> map;
152
153     for (auto& name : attributeNames) {
154         const AtomicString& localName = name->localName();
155         map.add(localName.impl(), cssPropertyID(localName));
156     }
157
158     // FIXME: When CSS supports "transform-origin" this special case can be removed,
159     // and we can add transform_originAttr to the table above instead.
160     map.add(transform_originAttr.localName().impl(), CSSPropertyTransformOrigin);
161
162     return map;
163 }
164
165 static NEVER_INLINE HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType> createAttributeNameToAnimatedPropertyTypeMap()
166 {
167     using namespace HTMLNames;
168     using namespace SVGNames;
169
170     struct TableEntry {
171         const QualifiedName& attributeName;
172         AnimatedPropertyType type;
173     };
174
175     static const TableEntry table[] = {
176         { alignment_baselineAttr, AnimatedString },
177         { baseline_shiftAttr, AnimatedString },
178         { buffered_renderingAttr, AnimatedString },
179         { clipAttr, AnimatedRect },
180         { clip_pathAttr, AnimatedString },
181         { clip_ruleAttr, AnimatedString },
182         { SVGNames::colorAttr, AnimatedColor },
183         { color_interpolationAttr, AnimatedString },
184         { color_interpolation_filtersAttr, AnimatedString },
185         { color_profileAttr, AnimatedString },
186         { color_renderingAttr, AnimatedString },
187         { cursorAttr, AnimatedString },
188         { displayAttr, AnimatedString },
189         { dominant_baselineAttr, AnimatedString },
190         { fillAttr, AnimatedColor },
191         { fill_opacityAttr, AnimatedNumber },
192         { fill_ruleAttr, AnimatedString },
193         { filterAttr, AnimatedString },
194         { flood_colorAttr, AnimatedColor },
195         { flood_opacityAttr, AnimatedNumber },
196         { font_familyAttr, AnimatedString },
197         { font_sizeAttr, AnimatedLength },
198         { font_stretchAttr, AnimatedString },
199         { font_styleAttr, AnimatedString },
200         { font_variantAttr, AnimatedString },
201         { font_weightAttr, AnimatedString },
202         { image_renderingAttr, AnimatedString },
203         { kerningAttr, AnimatedLength },
204         { letter_spacingAttr, AnimatedLength },
205         { lighting_colorAttr, AnimatedColor },
206         { marker_endAttr, AnimatedString },
207         { marker_midAttr, AnimatedString },
208         { marker_startAttr, AnimatedString },
209         { maskAttr, AnimatedString },
210         { mask_typeAttr, AnimatedString },
211         { opacityAttr, AnimatedNumber },
212         { overflowAttr, AnimatedString },
213         { paint_orderAttr, AnimatedString },
214         { pointer_eventsAttr, AnimatedString },
215         { shape_renderingAttr, AnimatedString },
216         { stop_colorAttr, AnimatedColor },
217         { stop_opacityAttr, AnimatedNumber },
218         { strokeAttr, AnimatedColor },
219         { stroke_dasharrayAttr, AnimatedLengthList },
220         { stroke_dashoffsetAttr, AnimatedLength },
221         { stroke_linecapAttr, AnimatedString },
222         { stroke_linejoinAttr, AnimatedString },
223         { stroke_miterlimitAttr, AnimatedNumber },
224         { stroke_opacityAttr, AnimatedNumber },
225         { stroke_widthAttr, AnimatedLength },
226         { text_anchorAttr, AnimatedString },
227         { text_decorationAttr, AnimatedString },
228         { text_renderingAttr, AnimatedString },
229         { vector_effectAttr, AnimatedString },
230         { visibilityAttr, AnimatedString },
231         { word_spacingAttr, AnimatedLength },
232     };
233
234     HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType> map;
235     for (auto& entry : table)
236         map.add(entry.attributeName.impl(), entry.type);
237     return map;
238 }
239
240 static const HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& attributeNameToAnimatedPropertyTypeMap()
241 {
242     static const auto map = makeNeverDestroyed(createAttributeNameToAnimatedPropertyTypeMap());
243     return map;
244 }
245
246 static NEVER_INLINE HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType> createCSSPropertyWithSVGDOMNameToAnimatedPropertyTypeMap()
247 {
248     using namespace HTMLNames;
249     using namespace SVGNames;
250
251     struct TableEntry {
252         const QualifiedName& attributeName;
253         AnimatedPropertyType type;
254     };
255
256     static const TableEntry table[] = {
257         { cxAttr, AnimatedLength },
258         { cyAttr, AnimatedLength },
259         { rAttr, AnimatedLength },
260         { rxAttr, AnimatedLength },
261         { ryAttr, AnimatedLength },
262         { SVGNames::heightAttr, AnimatedLength },
263         { SVGNames::widthAttr, AnimatedLength },
264         { xAttr, AnimatedLength },
265         { yAttr, AnimatedLength },
266     };
267
268     HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType> map;
269     for (auto& entry : table)
270         map.add(entry.attributeName.impl(), entry.type);
271     return map;
272 }
273
274 static inline const HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap()
275 {
276     static const auto map = makeNeverDestroyed(createCSSPropertyWithSVGDOMNameToAnimatedPropertyTypeMap());
277     return map;
278 }
279
280 SVGElement::SVGElement(const QualifiedName& tagName, Document& document)
281     : StyledElement(tagName, document, CreateSVGElement)
282 {
283     registerAnimatedPropertiesForSVGElement();
284 }
285
286 SVGElement::~SVGElement()
287 {
288     if (m_svgRareData) {
289         for (SVGElement* instance : m_svgRareData->instances())
290             instance->m_svgRareData->setCorrespondingElement(nullptr);
291         if (SVGElement* correspondingElement = m_svgRareData->correspondingElement())
292             correspondingElement->m_svgRareData->instances().remove(this);
293
294         m_svgRareData = nullptr;
295     }
296     document().accessSVGExtensions().rebuildAllElementReferencesForTarget(*this);
297     document().accessSVGExtensions().removeAllElementReferencesForTarget(this);
298 }
299
300 int SVGElement::tabIndex() const
301 {
302     if (supportsFocus())
303         return Element::tabIndex();
304     return -1;
305 }
306
307 void SVGElement::willRecalcStyle(Style::Change change)
308 {
309     if (!m_svgRareData || styleResolutionShouldRecompositeLayer())
310         return;
311     // If the style changes because of a regular property change (not induced by SMIL animations themselves)
312     // reset the "computed style without SMIL style properties", so the base value change gets reflected.
313     if (change > Style::NoChange || needsStyleRecalc())
314         m_svgRareData->setNeedsOverrideComputedStyleUpdate();
315 }
316
317 SVGElementRareData& SVGElement::ensureSVGRareData()
318 {
319     if (!m_svgRareData)
320         m_svgRareData = std::make_unique<SVGElementRareData>();
321     return *m_svgRareData;
322 }
323
324 bool SVGElement::isOutermostSVGSVGElement() const
325 {
326     if (!is<SVGSVGElement>(*this))
327         return false;
328
329     // If we're living in a shadow tree, we're a <svg> element that got created as replacement
330     // for a <symbol> element or a cloned <svg> element in the referenced tree. In that case
331     // we're always an inner <svg> element.
332     if (isInShadowTree() && parentOrShadowHostElement() && parentOrShadowHostElement()->isSVGElement())
333         return false;
334
335     // Element may not be in the document, pretend we're outermost for viewport(), getCTM(), etc.
336     if (!parentNode())
337         return true;
338
339     // We act like an outermost SVG element, if we're a direct child of a <foreignObject> element.
340     if (parentNode()->hasTagName(SVGNames::foreignObjectTag))
341         return true;
342
343     // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
344     return !parentNode()->isSVGElement();
345 }
346
347 void SVGElement::reportAttributeParsingError(SVGParsingError error, const QualifiedName& name, const AtomicString& value)
348 {
349     if (error == NoError)
350         return;
351
352     String errorString = "<" + tagName() + "> attribute " + name.toString() + "=\"" + value + "\"";
353     SVGDocumentExtensions& extensions = document().accessSVGExtensions();
354
355     if (error == NegativeValueForbiddenError) {
356         extensions.reportError("Invalid negative value for " + errorString);
357         return;
358     }
359
360     if (error == ParsingAttributeFailedError) {
361         extensions.reportError("Invalid value for " + errorString);
362         return;
363     }
364
365     ASSERT_NOT_REACHED();
366 }
367
368 void SVGElement::removedFrom(ContainerNode& rootParent)
369 {
370     bool wasInDocument = rootParent.isConnected();
371     if (wasInDocument)
372         updateRelativeLengthsInformation(false, this);
373
374     StyledElement::removedFrom(rootParent);
375
376     if (wasInDocument) {
377         document().accessSVGExtensions().clearTargetDependencies(*this);
378         document().accessSVGExtensions().removeAllElementReferencesForTarget(this);
379     }
380     invalidateInstances();
381 }
382
383 SVGSVGElement* SVGElement::ownerSVGElement() const
384 {
385     ContainerNode* node = parentOrShadowHostNode();
386     while (node) {
387         if (is<SVGSVGElement>(*node))
388             return downcast<SVGSVGElement>(node);
389
390         node = node->parentOrShadowHostNode();
391     }
392
393     return nullptr;
394 }
395
396 SVGElement* SVGElement::viewportElement() const
397 {
398     // This function needs shadow tree support - as RenderSVGContainer uses this function
399     // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise.
400     ContainerNode* node = parentOrShadowHostNode();
401     while (node) {
402         if (is<SVGSVGElement>(*node) || is<SVGImageElement>(*node) || node->hasTagName(SVGNames::symbolTag))
403             return downcast<SVGElement>(node);
404
405         node = node->parentOrShadowHostNode();
406     }
407
408     return nullptr;
409 }
410  
411 const HashSet<SVGElement*>& SVGElement::instances() const
412 {
413     if (!m_svgRareData) {
414         static NeverDestroyed<HashSet<SVGElement*>> emptyInstances;
415         return emptyInstances;
416     }
417     return m_svgRareData->instances();
418 }
419
420 bool SVGElement::getBoundingBox(FloatRect& rect, SVGLocatable::StyleUpdateStrategy styleUpdateStrategy)
421 {
422     if (is<SVGGraphicsElement>(*this)) {
423         rect = downcast<SVGGraphicsElement>(*this).getBBox(styleUpdateStrategy);
424         return true;
425     }
426     return false;
427 }
428
429 SVGElement* SVGElement::correspondingElement() const
430 {
431     return m_svgRareData ? m_svgRareData->correspondingElement() : nullptr;
432 }
433
434 SVGUseElement* SVGElement::correspondingUseElement() const
435 {
436     auto* root = containingShadowRoot();
437     if (!root)
438         return nullptr;
439     if (root->mode() != ShadowRootMode::UserAgent)
440         return nullptr;
441     auto* host = root->host();
442     if (!is<SVGUseElement>(host))
443         return nullptr;
444     return &downcast<SVGUseElement>(*host);
445 }
446
447 void SVGElement::setCorrespondingElement(SVGElement* correspondingElement)
448 {
449     if (m_svgRareData) {
450         if (SVGElement* oldCorrespondingElement = m_svgRareData->correspondingElement())
451             oldCorrespondingElement->m_svgRareData->instances().remove(this);
452     }
453     if (m_svgRareData || correspondingElement)
454         ensureSVGRareData().setCorrespondingElement(correspondingElement);
455     if (correspondingElement)
456         correspondingElement->ensureSVGRareData().instances().add(this);
457 }
458
459 void SVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
460 {
461     if (name == HTMLNames::classAttr) {
462         setClassNameBaseValue(value);
463         return;
464     }
465
466     if (name == HTMLNames::tabindexAttr) {
467         if (value.isEmpty())
468             clearTabIndexExplicitlyIfNeeded();
469         else if (auto optionalTabIndex = parseHTMLInteger(value))
470             setTabIndexExplicitly(optionalTabIndex.value());
471         return;
472     }
473
474     auto& eventName = HTMLElement::eventNameForEventHandlerAttribute(name);
475     if (!eventName.isNull()) {
476         setAttributeEventListener(eventName, name, value);
477         return;
478     }
479
480     SVGLangSpace::parseAttribute(name, value);
481 }
482
483 Vector<AnimatedPropertyType> SVGElement::animatedPropertyTypesForAttribute(const QualifiedName& attributeName)
484 {
485     auto types = localAttributeToPropertyMap().types(attributeName);
486     if (!types.isEmpty())
487         return types;
488
489     {
490         auto& map = attributeNameToAnimatedPropertyTypeMap();
491         auto it = map.find(attributeName.impl());
492         if (it != map.end()) {
493             types.append(it->value);
494             return types;
495         }
496     }
497
498     {
499         auto& map = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
500         auto it = map.find(attributeName.impl());
501         if (it != map.end()) {
502             types.append(it->value);
503             return types;
504         }
505     }
506
507     return types;
508 }
509
510 bool SVGElement::haveLoadedRequiredResources()
511 {
512     for (auto& child : childrenOfType<SVGElement>(*this)) {
513         if (!child.haveLoadedRequiredResources())
514             return false;
515     }
516     return true;
517 }
518
519 bool SVGElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
520 {   
521     // Add event listener to regular DOM element
522     if (!Node::addEventListener(eventType, listener.copyRef(), options))
523         return false;
524
525     if (containingShadowRoot())
526         return true;
527
528     // Add event listener to all shadow tree DOM element instances
529     ASSERT(!instanceUpdatesBlocked());
530     for (auto* instance : instances()) {
531         ASSERT(instance->correspondingElement() == this);
532         bool result = instance->Node::addEventListener(eventType, listener.copyRef(), options);
533         ASSERT_UNUSED(result, result);
534     }
535
536     return true;
537 }
538
539 bool SVGElement::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
540 {
541     if (containingShadowRoot())
542         return Node::removeEventListener(eventType, listener, options);
543
544     // EventTarget::removeEventListener creates a Ref around the given EventListener
545     // object when creating a temporary RegisteredEventListener object used to look up the
546     // event listener in a cache. If we want to be able to call removeEventListener() multiple
547     // times on different nodes, we have to delay its immediate destruction, which would happen
548     // after the first call below.
549     Ref<EventListener> protector(listener);
550
551     // Remove event listener from regular DOM element
552     if (!Node::removeEventListener(eventType, listener, options))
553         return false;
554
555     // Remove event listener from all shadow tree DOM element instances
556     ASSERT(!instanceUpdatesBlocked());
557     for (auto& instance : instances()) {
558         ASSERT(instance->correspondingElement() == this);
559
560         if (instance->Node::removeEventListener(eventType, listener, options))
561             continue;
562
563         // This case can only be hit for event listeners created from markup
564         ASSERT(listener.wasCreatedFromMarkup());
565
566         // If the event listener 'listener' has been created from markup and has been fired before
567         // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
568         // has been created (read: it's not 0 anymore). During shadow tree creation, the event
569         // listener DOM attribute has been cloned, and another event listener has been setup in
570         // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
571         // and tryRemoveEventListener() above will fail. Work around that very rare problem.
572         ASSERT(instance->eventTargetData());
573         instance->eventTargetData()->eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
574     }
575
576     return true;
577 }
578
579 static bool hasLoadListener(Element* element)
580 {
581     if (element->hasEventListeners(eventNames().loadEvent))
582         return true;
583
584     for (element = element->parentOrShadowHostElement(); element; element = element->parentOrShadowHostElement()) {
585         if (element->hasCapturingEventListeners(eventNames().loadEvent))
586             return true;
587     }
588
589     return false;
590 }
591
592 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents)
593 {
594     if (!isConnected() || !document().frame())
595         return;
596
597     RefPtr<SVGElement> currentTarget = this;
598     while (currentTarget && currentTarget->haveLoadedRequiredResources()) {
599         RefPtr<Element> parent;
600         if (sendParentLoadEvents)
601             parent = currentTarget->parentOrShadowHostElement(); // save the next parent to dispatch too incase dispatching the event changes the tree
602         if (hasLoadListener(currentTarget.get()))
603             currentTarget->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
604         currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>();
605         SVGElement* element = currentTarget.get();
606         if (!element || !element->isOutermostSVGSVGElement())
607             continue;
608
609         // Consider <svg onload="foo()"><image xlink:href="foo.png" externalResourcesRequired="true"/></svg>.
610         // If foo.png is not yet loaded, the first SVGLoad event will go to the <svg> element, sent through
611         // Document::implicitClose(). Then the SVGLoad event will fire for <image>, once its loaded.
612         ASSERT(sendParentLoadEvents);
613
614         // If the load event was not sent yet by Document::implicitClose(), but the <image> from the example
615         // above, just appeared, don't send the SVGLoad event to the outermost <svg>, but wait for the document
616         // to be "ready to render", first.
617         if (!document().loadEventFinished())
618             break;
619     }
620 }
621
622 void SVGElement::sendSVGLoadEventIfPossibleAsynchronously()
623 {
624     svgLoadEventTimer()->startOneShot(0_s);
625 }
626
627 void SVGElement::svgLoadEventTimerFired()
628 {
629     sendSVGLoadEventIfPossible();
630 }
631
632 Timer* SVGElement::svgLoadEventTimer()
633 {
634     ASSERT_NOT_REACHED();
635     return nullptr;
636 }
637
638 void SVGElement::finishParsingChildren()
639 {
640     StyledElement::finishParsingChildren();
641
642     // The outermost SVGSVGElement SVGLoad event is fired through Document::dispatchWindowLoadEvent.
643     if (isOutermostSVGSVGElement())
644         return;
645
646     // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>)
647     // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish
648     sendSVGLoadEventIfPossible();
649
650     // Notify all the elements which have references to this element to rebuild their shadow and render
651     // trees, e.g. a <use> element references a target element before this target element is defined.
652     invalidateInstances();
653 }
654
655 bool SVGElement::childShouldCreateRenderer(const Node& child) const
656 {
657     if (!child.isSVGElement())
658         return false;
659     auto& svgChild = downcast<SVGElement>(child);
660
661     static const QualifiedName* const invalidTextContent[] {
662 #if ENABLE(SVG_FONTS)
663         &SVGNames::altGlyphTag,
664 #endif
665         &SVGNames::textPathTag,
666         &SVGNames::trefTag,
667         &SVGNames::tspanTag,
668     };
669     auto& name = svgChild.localName();
670     for (auto* tag : invalidTextContent) {
671         if (name == tag->localName())
672             return false;
673     }
674
675     return svgChild.isValid();
676 }
677
678 void SVGElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
679 {
680     StyledElement::attributeChanged(name, oldValue, newValue);
681
682     if (name == HTMLNames::idAttr)
683         document().accessSVGExtensions().rebuildAllElementReferencesForTarget(*this);
684
685     // Changes to the style attribute are processed lazily (see Element::getAttribute() and related methods),
686     // so we don't want changes to the style attribute to result in extra work here.
687     if (name != HTMLNames::styleAttr)
688         svgAttributeChanged(name);
689 }
690
691 void SVGElement::synchronizeAllAnimatedSVGAttribute(SVGElement* svgElement)
692 {
693     ASSERT(svgElement->elementData());
694     ASSERT(svgElement->elementData()->animatedSVGAttributesAreDirty());
695
696     svgElement->localAttributeToPropertyMap().synchronizeProperties(*svgElement);
697     svgElement->elementData()->setAnimatedSVGAttributesAreDirty(false);
698 }
699
700 void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) const
701 {
702     if (!elementData() || !elementData()->animatedSVGAttributesAreDirty())
703         return;
704
705     SVGElement* nonConstThis = const_cast<SVGElement*>(this);
706     if (name == anyQName())
707         synchronizeAllAnimatedSVGAttribute(nonConstThis);
708     else
709         nonConstThis->localAttributeToPropertyMap().synchronizeProperty(*nonConstThis, name);
710 }
711
712 void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement)
713 {
714     ASSERT(contextElement);
715     contextElement->synchronizeRequiredFeatures();
716 }
717
718 void SVGElement::synchronizeRequiredExtensions(SVGElement* contextElement)
719 {
720     ASSERT(contextElement);
721     contextElement->synchronizeRequiredExtensions();
722 }
723
724 void SVGElement::synchronizeSystemLanguage(SVGElement* contextElement)
725 {
726     ASSERT(contextElement);
727     contextElement->synchronizeSystemLanguage();
728 }
729
730 std::optional<ElementStyle> SVGElement::resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle*)
731 {
732     // If the element is in a <use> tree we get the style from the definition tree.
733     if (auto* styleElement = this->correspondingElement())
734         return styleElement->resolveStyle(&parentStyle);
735
736     return resolveStyle(&parentStyle);
737 }
738
739 MutableStyleProperties* SVGElement::animatedSMILStyleProperties() const
740 {
741     if (m_svgRareData)
742         return m_svgRareData->animatedSMILStyleProperties();
743     return 0;
744 }
745
746 MutableStyleProperties& SVGElement::ensureAnimatedSMILStyleProperties()
747 {
748     return ensureSVGRareData().ensureAnimatedSMILStyleProperties();
749 }
750
751 void SVGElement::setUseOverrideComputedStyle(bool value)
752 {
753     if (m_svgRareData)
754         m_svgRareData->setUseOverrideComputedStyle(value);
755 }
756
757 const RenderStyle* SVGElement::computedStyle(PseudoId pseudoElementSpecifier)
758 {
759     if (!m_svgRareData || !m_svgRareData->useOverrideComputedStyle())
760         return Element::computedStyle(pseudoElementSpecifier);
761
762     const RenderStyle* parentStyle = nullptr;
763     if (Element* parent = parentOrShadowHostElement()) {
764         if (auto renderer = parent->renderer())
765             parentStyle = &renderer->style();
766     }
767
768     return m_svgRareData->overrideComputedStyle(*this, parentStyle);
769 }
770
771 QualifiedName SVGElement::animatableAttributeForName(const AtomicString& localName)
772 {
773     static const auto animatableAttributes = makeNeverDestroyed([] {
774         static const QualifiedName* const names[] = {
775             &HTMLNames::classAttr,
776             &SVGNames::amplitudeAttr,
777             &SVGNames::azimuthAttr,
778             &SVGNames::baseFrequencyAttr,
779             &SVGNames::biasAttr,
780             &SVGNames::clipPathUnitsAttr,
781             &SVGNames::cxAttr,
782             &SVGNames::cyAttr,
783             &SVGNames::diffuseConstantAttr,
784             &SVGNames::divisorAttr,
785             &SVGNames::dxAttr,
786             &SVGNames::dyAttr,
787             &SVGNames::edgeModeAttr,
788             &SVGNames::elevationAttr,
789             &SVGNames::exponentAttr,
790             &SVGNames::externalResourcesRequiredAttr,
791             &SVGNames::filterResAttr,
792             &SVGNames::filterUnitsAttr,
793             &SVGNames::fxAttr,
794             &SVGNames::fyAttr,
795             &SVGNames::gradientTransformAttr,
796             &SVGNames::gradientUnitsAttr,
797             &SVGNames::heightAttr,
798             &SVGNames::in2Attr,
799             &SVGNames::inAttr,
800             &SVGNames::interceptAttr,
801             &SVGNames::k1Attr,
802             &SVGNames::k2Attr,
803             &SVGNames::k3Attr,
804             &SVGNames::k4Attr,
805             &SVGNames::kernelMatrixAttr,
806             &SVGNames::kernelUnitLengthAttr,
807             &SVGNames::lengthAdjustAttr,
808             &SVGNames::limitingConeAngleAttr,
809             &SVGNames::markerHeightAttr,
810             &SVGNames::markerUnitsAttr,
811             &SVGNames::markerWidthAttr,
812             &SVGNames::maskContentUnitsAttr,
813             &SVGNames::maskUnitsAttr,
814             &SVGNames::methodAttr,
815             &SVGNames::modeAttr,
816             &SVGNames::numOctavesAttr,
817             &SVGNames::offsetAttr,
818             &SVGNames::operatorAttr,
819             &SVGNames::orderAttr,
820             &SVGNames::orientAttr,
821             &SVGNames::pathLengthAttr,
822             &SVGNames::patternContentUnitsAttr,
823             &SVGNames::patternTransformAttr,
824             &SVGNames::patternUnitsAttr,
825             &SVGNames::pointsAtXAttr,
826             &SVGNames::pointsAtYAttr,
827             &SVGNames::pointsAtZAttr,
828             &SVGNames::preserveAlphaAttr,
829             &SVGNames::preserveAspectRatioAttr,
830             &SVGNames::primitiveUnitsAttr,
831             &SVGNames::radiusAttr,
832             &SVGNames::rAttr,
833             &SVGNames::refXAttr,
834             &SVGNames::refYAttr,
835             &SVGNames::resultAttr,
836             &SVGNames::rotateAttr,
837             &SVGNames::rxAttr,
838             &SVGNames::ryAttr,
839             &SVGNames::scaleAttr,
840             &SVGNames::seedAttr,
841             &SVGNames::slopeAttr,
842             &SVGNames::spacingAttr,
843             &SVGNames::specularConstantAttr,
844             &SVGNames::specularExponentAttr,
845             &SVGNames::spreadMethodAttr,
846             &SVGNames::startOffsetAttr,
847             &SVGNames::stdDeviationAttr,
848             &SVGNames::stitchTilesAttr,
849             &SVGNames::surfaceScaleAttr,
850             &SVGNames::tableValuesAttr,
851             &SVGNames::targetAttr,
852             &SVGNames::targetXAttr,
853             &SVGNames::targetYAttr,
854             &SVGNames::transformAttr,
855             &SVGNames::typeAttr,
856             &SVGNames::valuesAttr,
857             &SVGNames::viewBoxAttr,
858             &SVGNames::widthAttr,
859             &SVGNames::x1Attr,
860             &SVGNames::x2Attr,
861             &SVGNames::xAttr,
862             &SVGNames::xChannelSelectorAttr,
863             &SVGNames::y1Attr,
864             &SVGNames::y2Attr,
865             &SVGNames::yAttr,
866             &SVGNames::yChannelSelectorAttr,
867             &SVGNames::zAttr,
868             &XLinkNames::hrefAttr,
869         };
870         HashMap<AtomicString, QualifiedName> map;
871         for (auto& name : names) {
872             auto addResult = map.add(name->localName(), *name);
873             ASSERT_UNUSED(addResult, addResult.isNewEntry);
874         }
875         return map;
876     }());
877     return animatableAttributes.get().get(localName);
878 }
879
880 #ifndef NDEBUG
881
882 bool SVGElement::isAnimatableAttribute(const QualifiedName& name) const
883 {
884     if (animatableAttributeForName(name.localName()) == name)
885         return !filterOutAnimatableAttribute(name);
886     return false;
887 }
888
889 bool SVGElement::filterOutAnimatableAttribute(const QualifiedName&) const
890 {
891     return false;
892 }
893
894 #endif
895
896 String SVGElement::title() const
897 {
898     // According to spec, for stand-alone SVG documents we should not return a title when
899     // hovering over the rootmost SVG element (the first <title> element is the title of
900     // the document, not a tooltip) so we instantly return.
901     if (isOutermostSVGSVGElement() && document().topDocument().isSVGDocument())
902         return String();
903     auto firstTitle = childrenOfType<SVGTitleElement>(*this).first();
904     return firstTitle ? const_cast<SVGTitleElement*>(firstTitle)->innerText() : String();
905 }
906
907 bool SVGElement::rendererIsNeeded(const RenderStyle& style)
908 {
909     // http://www.w3.org/TR/SVG/extend.html#PrivateData
910     // Prevent anything other than SVG renderers from appearing in our render tree
911     // Spec: SVG allows inclusion of elements from foreign namespaces anywhere
912     // with the SVG content. In general, the SVG user agent will include the unknown
913     // elements in the DOM but will otherwise ignore unknown elements.
914     if (!parentOrShadowHostElement() || parentOrShadowHostElement()->isSVGElement())
915         return StyledElement::rendererIsNeeded(style);
916
917     return false;
918 }
919
920 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName)
921 {
922     if (!attrName.namespaceURI().isNull())
923         return CSSPropertyInvalid;
924
925     static const auto properties = makeNeverDestroyed(createAttributeNameToCSSPropertyIDMap());
926     return properties.get().get(attrName.localName().impl());
927 }
928
929 bool SVGElement::isAnimatableCSSProperty(const QualifiedName& attributeName)
930 {
931     return attributeNameToAnimatedPropertyTypeMap().contains(attributeName.impl())
932         || cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap().contains(attributeName.impl());
933 }
934
935 bool SVGElement::isPresentationAttributeWithSVGDOM(const QualifiedName& attributeName)
936 {
937     return !localAttributeToPropertyMap().types(attributeName).isEmpty();
938 }
939
940 bool SVGElement::isPresentationAttribute(const QualifiedName& name) const
941 {
942     if (cssPropertyIdForSVGAttributeName(name) > 0)
943         return true;
944     return StyledElement::isPresentationAttribute(name);
945 }
946
947 void SVGElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
948 {
949     CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(name);
950     if (propertyID > 0)
951         addPropertyToPresentationAttributeStyle(style, propertyID, value);
952 }
953
954 bool SVGElement::isKnownAttribute(const QualifiedName& attrName)
955 {
956     return attrName == HTMLNames::idAttr;
957 }
958
959 void SVGElement::svgAttributeChanged(const QualifiedName& attrName)
960 {
961     CSSPropertyID propId = cssPropertyIdForSVGAttributeName(attrName);
962     if (propId > 0) {
963         invalidateInstances();
964         return;
965     }
966
967     if (attrName == HTMLNames::classAttr) {
968         classAttributeChanged(className());
969         invalidateInstances();
970         return;
971     }
972
973     if (attrName == HTMLNames::idAttr) {
974         auto renderer = this->renderer();
975         // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions
976         if (is<RenderSVGResourceContainer>(renderer))
977             downcast<RenderSVGResourceContainer>(*renderer).idChanged();
978         if (isConnected())
979             buildPendingResourcesIfNeeded();
980         invalidateInstances();
981         return;
982     }
983 }
984
985 Node::InsertedIntoResult SVGElement::insertedInto(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
986 {
987     StyledElement::insertedInto(insertionType, parentOfInsertedTree);
988     updateRelativeLengthsInformation();
989     buildPendingResourcesIfNeeded();
990     return InsertedIntoResult::Done;
991 }
992
993 void SVGElement::buildPendingResourcesIfNeeded()
994 {
995     if (!needsPendingResourceHandling() || !isConnected() || isInShadowTree())
996         return;
997
998     SVGDocumentExtensions& extensions = document().accessSVGExtensions();
999     String resourceId = getIdAttribute();
1000     if (!extensions.isIdOfPendingResource(resourceId))
1001         return;
1002
1003     // Mark pending resources as pending for removal.
1004     extensions.markPendingResourcesForRemoval(resourceId);
1005
1006     // Rebuild pending resources for each client of a pending resource that is being removed.
1007     while (Element* clientElement = extensions.removeElementFromPendingResourcesForRemovalMap(resourceId)) {
1008         ASSERT(clientElement->hasPendingResources());
1009         if (clientElement->hasPendingResources()) {
1010             clientElement->buildPendingResource();
1011             extensions.clearHasPendingResourcesIfPossible(clientElement);
1012         }
1013     }
1014 }
1015
1016 void SVGElement::childrenChanged(const ChildChange& change)
1017 {
1018     StyledElement::childrenChanged(change);
1019
1020     if (change.source == ChildChangeSourceParser)
1021         return;
1022     invalidateInstances();
1023 }
1024
1025 RefPtr<DeprecatedCSSOMValue> SVGElement::getPresentationAttribute(const String& name)
1026 {
1027     if (!hasAttributesWithoutUpdate())
1028         return 0;
1029
1030     QualifiedName attributeName(nullAtom(), name, nullAtom());
1031     const Attribute* attribute = findAttributeByName(attributeName);
1032     if (!attribute)
1033         return 0;
1034
1035     RefPtr<MutableStyleProperties> style = MutableStyleProperties::create(SVGAttributeMode);
1036     CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(attribute->name());
1037     style->setProperty(propertyID, attribute->value());
1038     auto cssValue = style->getPropertyCSSValue(propertyID);
1039     if (!cssValue)
1040         return nullptr;
1041     return cssValue->createDeprecatedCSSOMWrapper(style->ensureCSSStyleDeclaration());
1042 }
1043
1044 bool SVGElement::instanceUpdatesBlocked() const
1045 {
1046     return m_svgRareData && m_svgRareData->instanceUpdatesBlocked();
1047 }
1048
1049 void SVGElement::setInstanceUpdatesBlocked(bool value)
1050 {
1051     // Catch any callers that calls setInstanceUpdatesBlocked(true) twice in a row.
1052     // That probably indicates nested use of InstanceUpdateBlocker and a bug.
1053     ASSERT(!value || !instanceUpdatesBlocked());
1054
1055     if (m_svgRareData)
1056         m_svgRareData->setInstanceUpdatesBlocked(value);
1057 }
1058
1059 AffineTransform SVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
1060 {
1061     // To be overriden by SVGGraphicsElement (or as special case SVGTextElement and SVGPatternElement)
1062     return AffineTransform();
1063 }
1064
1065 void SVGElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement* element)
1066 {
1067     // If we're not yet in a document, this function will be called again from insertedInto(). Do nothing now.
1068     if (!isConnected())
1069         return;
1070
1071     // An element wants to notify us that its own relative lengths state changed.
1072     // Register it in the relative length map, and register us in the parent relative length map.
1073     // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
1074
1075     if (hasRelativeLengths)
1076         m_elementsWithRelativeLengths.add(element);
1077     else {
1078         if (!m_elementsWithRelativeLengths.contains(element)) {
1079             // We were never registered. Do nothing.
1080             return;
1081         }
1082
1083         m_elementsWithRelativeLengths.remove(element);
1084     }
1085
1086     if (!element->isSVGGraphicsElement())
1087         return;
1088
1089     // Find first styled parent node, and notify it that we've changed our relative length state.
1090     ContainerNode* node = parentNode();
1091     while (node) {
1092         if (!node->isSVGElement())
1093             break;
1094
1095         // Register us in the parent element map.
1096         downcast<SVGElement>(*node).updateRelativeLengthsInformation(hasRelativeLengths, this);
1097         break;
1098     }
1099 }
1100
1101 bool SVGElement::hasFocusEventListeners() const
1102 {
1103     Element* eventTarget = const_cast<SVGElement*>(this);
1104     return eventTarget->hasEventListeners(eventNames().focusinEvent)
1105         || eventTarget->hasEventListeners(eventNames().focusoutEvent)
1106         || eventTarget->hasEventListeners(eventNames().focusEvent)
1107         || eventTarget->hasEventListeners(eventNames().blurEvent);
1108 }
1109
1110 bool SVGElement::isMouseFocusable() const
1111 {
1112     if (!isFocusable())
1113         return false;
1114     Element* eventTarget = const_cast<SVGElement*>(this);
1115     return hasFocusEventListeners()
1116         || eventTarget->hasEventListeners(eventNames().keydownEvent)
1117         || eventTarget->hasEventListeners(eventNames().keyupEvent)
1118         || eventTarget->hasEventListeners(eventNames().keypressEvent);
1119 }
1120     
1121 void SVGElement::accessKeyAction(bool sendMouseEvents)
1122 {
1123     dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
1124 }
1125
1126 void SVGElement::invalidateInstances()
1127 {
1128     if (instanceUpdatesBlocked())
1129         return;
1130
1131     auto& instances = this->instances();
1132     while (!instances.isEmpty()) {
1133         SVGElement* instance = *instances.begin();
1134         if (SVGUseElement* useElement = instance->correspondingUseElement())
1135             useElement->invalidateShadowTree();
1136         instance->setCorrespondingElement(nullptr);
1137     } while (!instances.isEmpty());
1138 }
1139
1140 }