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