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