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