Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25
26 #include "core/svg/SVGElement.h"
27
28 #include "bindings/core/v8/ScriptEventListener.h"
29 #include "core/HTMLNames.h"
30 #include "core/SVGNames.h"
31 #include "core/XLinkNames.h"
32 #include "core/XMLNames.h"
33 #include "core/css/CSSCursorImageValue.h"
34 #include "core/css/parser/CSSParser.h"
35 #include "core/css/resolver/StyleResolver.h"
36 #include "core/dom/Document.h"
37 #include "core/dom/ElementTraversal.h"
38 #include "core/dom/shadow/ShadowRoot.h"
39 #include "core/events/Event.h"
40 #include "core/frame/Settings.h"
41 #include "core/html/HTMLElement.h"
42 #include "core/rendering/RenderObject.h"
43 #include "core/rendering/svg/RenderSVGResourceContainer.h"
44 #include "core/svg/SVGCursorElement.h"
45 #include "core/svg/SVGDocumentExtensions.h"
46 #include "core/svg/SVGElementRareData.h"
47 #include "core/svg/SVGGraphicsElement.h"
48 #include "core/svg/SVGSVGElement.h"
49 #include "core/svg/SVGTitleElement.h"
50 #include "core/svg/SVGUseElement.h"
51
52 #include "wtf/TemporaryChange.h"
53
54 namespace blink {
55
56 using namespace HTMLNames;
57 using namespace SVGNames;
58
59 SVGElement::SVGElement(const QualifiedName& tagName, Document& document, ConstructionType constructionType)
60     : Element(tagName, &document, constructionType)
61 #if ENABLE(ASSERT)
62     , m_inRelativeLengthClientsInvalidation(false)
63 #endif
64     , m_SVGRareData(nullptr)
65     , m_className(SVGAnimatedString::create(this, HTMLNames::classAttr, SVGString::create()))
66 {
67     addToPropertyMap(m_className);
68     setHasCustomStyleCallbacks();
69 }
70
71 SVGElement::~SVGElement()
72 {
73     ASSERT(inDocument() || !hasRelativeLengths());
74
75     // The below teardown is all handled by weak pointer processing in oilpan.
76 #if !ENABLE(OILPAN)
77     if (hasSVGRareData()) {
78         if (SVGCursorElement* cursorElement = svgRareData()->cursorElement())
79             cursorElement->removeReferencedElement(this);
80         if (CSSCursorImageValue* cursorImageValue = svgRareData()->cursorImageValue())
81             cursorImageValue->removeReferencedElement(this);
82
83         // With Oilpan, either removedFrom has been called or the document is dead
84         // as well and there is no reason to clear out the references.
85         rebuildAllIncomingReferences();
86         removeAllIncomingReferences();
87     }
88 #endif
89 }
90
91 void SVGElement::detach(const AttachContext& context)
92 {
93     Element::detach(context);
94     if (SVGElement* element = correspondingElement())
95         element->removeInstanceMapping(this);
96 }
97
98 void SVGElement::attach(const AttachContext& context)
99 {
100     Element::attach(context);
101     if (SVGElement* element = correspondingElement())
102         element->mapInstanceToElement(this);
103 }
104
105 short SVGElement::tabIndex() const
106 {
107     if (supportsFocus())
108         return Element::tabIndex();
109     return -1;
110 }
111
112 void SVGElement::willRecalcStyle(StyleRecalcChange change)
113 {
114     if (!hasSVGRareData())
115         return;
116     // If the style changes because of a regular property change (not induced by SMIL animations themselves)
117     // reset the "computed style without SMIL style properties", so the base value change gets reflected.
118     if (change > NoChange || needsStyleRecalc())
119         svgRareData()->setNeedsOverrideComputedStyleUpdate();
120 }
121
122 void SVGElement::buildPendingResourcesIfNeeded()
123 {
124     Document& document = this->document();
125     if (!needsPendingResourceHandling() || !inDocument() || inUseShadowTree())
126         return;
127
128     SVGDocumentExtensions& extensions = document.accessSVGExtensions();
129     AtomicString resourceId = getIdAttribute();
130     if (!extensions.hasPendingResource(resourceId))
131         return;
132
133     // Mark pending resources as pending for removal.
134     extensions.markPendingResourcesForRemoval(resourceId);
135
136     // Rebuild pending resources for each client of a pending resource that is being removed.
137     while (Element* clientElement = extensions.removeElementFromPendingResourcesForRemoval(resourceId)) {
138         ASSERT(clientElement->hasPendingResources());
139         if (clientElement->hasPendingResources()) {
140             // FIXME: Ideally we'd always resolve pending resources async instead of inside
141             // insertedInto and svgAttributeChanged. For now we only do it for <use> since
142             // that would stamp out DOM.
143             if (isSVGUseElement(clientElement))
144                 toSVGUseElement(clientElement)->invalidateShadowTree();
145             else
146                 clientElement->buildPendingResource();
147             extensions.clearHasPendingResourcesIfPossible(clientElement);
148         }
149     }
150 }
151
152 SVGElementRareData* SVGElement::ensureSVGRareData()
153 {
154     if (hasSVGRareData())
155         return svgRareData();
156
157     m_SVGRareData = adoptPtrWillBeNoop(new SVGElementRareData(this));
158     return m_SVGRareData.get();
159 }
160
161 bool SVGElement::isOutermostSVGSVGElement() const
162 {
163     if (!isSVGSVGElement(*this))
164         return false;
165
166     // Element may not be in the document, pretend we're outermost for viewport(), getCTM(), etc.
167     if (!parentNode())
168         return true;
169
170     // We act like an outermost SVG element, if we're a direct child of a <foreignObject> element.
171     if (isSVGForeignObjectElement(*parentNode()))
172         return true;
173
174     // If we're living in a shadow tree, we're a <svg> element that got created as replacement
175     // for a <symbol> element or a cloned <svg> element in the referenced tree. In that case
176     // we're always an inner <svg> element.
177     if (inUseShadowTree() && parentOrShadowHostElement() && parentOrShadowHostElement()->isSVGElement())
178         return false;
179
180     // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
181     return !parentNode()->isSVGElement();
182 }
183
184 void SVGElement::reportAttributeParsingError(SVGParsingError error, const QualifiedName& name, const AtomicString& value)
185 {
186     if (error == NoError)
187         return;
188
189     String errorString = "<" + tagName() + "> attribute " + name.toString() + "=\"" + value + "\"";
190     SVGDocumentExtensions& extensions = document().accessSVGExtensions();
191
192     if (error == NegativeValueForbiddenError) {
193         extensions.reportError("Invalid negative value for " + errorString);
194         return;
195     }
196
197     if (error == ParsingAttributeFailedError) {
198         extensions.reportError("Invalid value for " + errorString);
199         return;
200     }
201
202     ASSERT_NOT_REACHED();
203 }
204
205 String SVGElement::title() const
206 {
207     // According to spec, we should not return titles when hovering over root <svg> elements (those
208     // <title> elements are the title of the document, not a tooltip) so we instantly return.
209     if (isOutermostSVGSVGElement())
210         return String();
211
212     if (inUseShadowTree()) {
213         String useTitle(shadowHost()->title());
214         if (!useTitle.isEmpty())
215             return useTitle;
216     }
217
218     // If we aren't an instance in a <use> or the <use> title was not found, then find the first
219     // <title> child of this element.
220     // If a title child was found, return the text contents.
221     if (Element* titleElement = Traversal<SVGTitleElement>::firstChild(*this))
222         return titleElement->innerText();
223
224     // Otherwise return a null/empty string.
225     return String();
226 }
227
228 bool SVGElement::instanceUpdatesBlocked() const
229 {
230     return hasSVGRareData() && svgRareData()->instanceUpdatesBlocked();
231 }
232
233 void SVGElement::setInstanceUpdatesBlocked(bool value)
234 {
235     if (hasSVGRareData())
236         svgRareData()->setInstanceUpdatesBlocked(value);
237 }
238
239 AffineTransform SVGElement::localCoordinateSpaceTransform(CTMScope) const
240 {
241     // To be overriden by SVGGraphicsElement (or as special case SVGTextElement and SVGPatternElement)
242     return AffineTransform();
243 }
244
245 Node::InsertionNotificationRequest SVGElement::insertedInto(ContainerNode* rootParent)
246 {
247     Element::insertedInto(rootParent);
248     updateRelativeLengthsInformation();
249     buildPendingResourcesIfNeeded();
250     return InsertionDone;
251 }
252
253 void SVGElement::removedFrom(ContainerNode* rootParent)
254 {
255     bool wasInDocument = rootParent->inDocument();
256
257     if (wasInDocument && hasRelativeLengths()) {
258         // The root of the subtree being removed should take itself out from its parent's relative
259         // length set. For the other nodes in the subtree we don't need to do anything: they will
260         // get their own removedFrom() notification and just clear their sets.
261         if (rootParent->isSVGElement() && !parentNode()) {
262             ASSERT(toSVGElement(rootParent)->m_elementsWithRelativeLengths.contains(this));
263             toSVGElement(rootParent)->updateRelativeLengthsInformation(false, this);
264         }
265
266         m_elementsWithRelativeLengths.clear();
267     }
268
269     ASSERT_WITH_SECURITY_IMPLICATION(!rootParent->isSVGElement() || !toSVGElement(rootParent)->m_elementsWithRelativeLengths.contains(this));
270
271     Element::removedFrom(rootParent);
272
273     if (wasInDocument) {
274         rebuildAllIncomingReferences();
275         removeAllIncomingReferences();
276     }
277
278     invalidateInstances();
279 }
280
281 void SVGElement::childrenChanged(const ChildrenChange& change)
282 {
283     Element::childrenChanged(change);
284
285     // Invalidate all instances associated with us.
286     if (!change.byParser)
287         invalidateInstances();
288 }
289
290 void mapAttributeToCSSProperty(HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap, const QualifiedName& attrName)
291 {
292     CSSPropertyID propertyId = cssPropertyID(attrName.localName());
293     ASSERT(propertyId > 0);
294     propertyNameToIdMap->set(attrName.localName().impl(), propertyId);
295 }
296
297 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName)
298 {
299     if (!attrName.namespaceURI().isNull())
300         return CSSPropertyInvalid;
301
302     static HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap = 0;
303     if (!propertyNameToIdMap) {
304         propertyNameToIdMap = new HashMap<StringImpl*, CSSPropertyID>;
305         // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes
306         mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr);
307         mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr);
308         mapAttributeToCSSProperty(propertyNameToIdMap, buffered_renderingAttr);
309         mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr);
310         mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr);
311         mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr);
312         mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::colorAttr);
313         mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr);
314         mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr);
315         mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr);
316         mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr);
317         mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::directionAttr);
318         mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr);
319         mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr);
320         mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr);
321         mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr);
322         mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr);
323         mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr);
324         mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr);
325         mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr);
326         mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr);
327         mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr);
328         mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr);
329         mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr);
330         mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr);
331         mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr);
332         mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr);
333         mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr);
334         mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr);
335         mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr);
336         mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr);
337         mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr);
338         mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr);
339         mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr);
340         mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr);
341         mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr);
342         mapAttributeToCSSProperty(propertyNameToIdMap, mask_typeAttr);
343         mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr);
344         mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr);
345         mapAttributeToCSSProperty(propertyNameToIdMap, paint_orderAttr);
346         mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr);
347         mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr);
348         mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr);
349         mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr);
350         mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr);
351         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr);
352         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr);
353         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr);
354         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr);
355         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr);
356         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr);
357         mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr);
358         mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr);
359         mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr);
360         mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr);
361         mapAttributeToCSSProperty(propertyNameToIdMap, transform_originAttr);
362         mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr);
363         mapAttributeToCSSProperty(propertyNameToIdMap, vector_effectAttr);
364         mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr);
365         mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr);
366         mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr);
367     }
368
369     return propertyNameToIdMap->get(attrName.localName().impl());
370 }
371
372 void SVGElement::updateRelativeLengthsInformation(bool clientHasRelativeLengths, SVGElement* clientElement)
373 {
374     ASSERT(clientElement);
375
376     // If we're not yet in a document, this function will be called again from insertedInto(). Do nothing now.
377     if (!inDocument())
378         return;
379
380     // An element wants to notify us that its own relative lengths state changed.
381     // Register it in the relative length map, and register us in the parent relative length map.
382     // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
383     for (ContainerNode* currentNode = this; currentNode && currentNode->isSVGElement(); currentNode = currentNode->parentNode()) {
384         SVGElement* currentElement = toSVGElement(currentNode);
385         ASSERT(!currentElement->m_inRelativeLengthClientsInvalidation);
386
387         bool hadRelativeLengths = currentElement->hasRelativeLengths();
388         if (clientHasRelativeLengths)
389             currentElement->m_elementsWithRelativeLengths.add(clientElement);
390         else
391             currentElement->m_elementsWithRelativeLengths.remove(clientElement);
392
393         // If the relative length state hasn't changed, we can stop propagating the notification.
394         if (hadRelativeLengths == currentElement->hasRelativeLengths())
395             return;
396
397         clientElement = currentElement;
398         clientHasRelativeLengths = clientElement->hasRelativeLengths();
399     }
400
401     // Register root SVG elements for top level viewport change notifications.
402     if (isSVGSVGElement(*clientElement)) {
403         SVGDocumentExtensions& svgExtensions = accessDocumentSVGExtensions();
404         if (clientElement->hasRelativeLengths())
405             svgExtensions.addSVGRootWithRelativeLengthDescendents(toSVGSVGElement(clientElement));
406         else
407             svgExtensions.removeSVGRootWithRelativeLengthDescendents(toSVGSVGElement(clientElement));
408     }
409 }
410
411 void SVGElement::invalidateRelativeLengthClients(SubtreeLayoutScope* layoutScope)
412 {
413     if (!inDocument())
414         return;
415
416     ASSERT(!m_inRelativeLengthClientsInvalidation);
417 #if ENABLE(ASSERT)
418     TemporaryChange<bool> inRelativeLengthClientsInvalidationChange(m_inRelativeLengthClientsInvalidation, true);
419 #endif
420
421     RenderObject* renderer = this->renderer();
422     if (renderer && selfHasRelativeLengths()) {
423         if (renderer->isSVGResourceContainer())
424             toRenderSVGResourceContainer(renderer)->invalidateCacheAndMarkForLayout(layoutScope);
425         else
426             renderer->setNeedsLayoutAndFullPaintInvalidation(MarkContainingBlockChain, layoutScope);
427     }
428
429     WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::iterator end = m_elementsWithRelativeLengths.end();
430     for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::iterator it = m_elementsWithRelativeLengths.begin(); it != end; ++it) {
431         if (*it != this)
432             (*it)->invalidateRelativeLengthClients(layoutScope);
433     }
434 }
435
436 SVGSVGElement* SVGElement::ownerSVGElement() const
437 {
438     ContainerNode* n = parentOrShadowHostNode();
439     while (n) {
440         if (isSVGSVGElement(*n))
441             return toSVGSVGElement(n);
442
443         n = n->parentOrShadowHostNode();
444     }
445
446     return 0;
447 }
448
449 SVGElement* SVGElement::viewportElement() const
450 {
451     // This function needs shadow tree support - as RenderSVGContainer uses this function
452     // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise.
453     ContainerNode* n = parentOrShadowHostNode();
454     while (n) {
455         if (isSVGSVGElement(*n) || isSVGImageElement(*n) || isSVGSymbolElement(*n))
456             return toSVGElement(n);
457
458         n = n->parentOrShadowHostNode();
459     }
460
461     return 0;
462 }
463
464 SVGDocumentExtensions& SVGElement::accessDocumentSVGExtensions()
465 {
466     // This function is provided for use by SVGAnimatedProperty to avoid
467     // global inclusion of core/dom/Document.h in SVG code.
468     return document().accessSVGExtensions();
469 }
470
471 void SVGElement::mapInstanceToElement(SVGElement* instance)
472 {
473     ASSERT(instance);
474     ASSERT(instance->inUseShadowTree());
475
476     WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instances = ensureSVGRareData()->elementInstances();
477     ASSERT(!instances.contains(instance));
478
479     instances.add(instance);
480 }
481
482 void SVGElement::removeInstanceMapping(SVGElement* instance)
483 {
484     ASSERT(instance);
485     ASSERT(instance->inUseShadowTree());
486
487     if (!hasSVGRareData())
488         return;
489
490     WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instances = svgRareData()->elementInstances();
491
492     instances.remove(instance);
493 }
494
495 static WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& emptyInstances()
496 {
497     DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> > >, emptyInstances, (adoptPtrWillBeNoop(new WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >())));
498     return *emptyInstances;
499 }
500
501 const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& SVGElement::instancesForElement() const
502 {
503     if (!hasSVGRareData())
504         return emptyInstances();
505     return svgRareData()->elementInstances();
506 }
507
508 bool SVGElement::getBoundingBox(FloatRect& rect)
509 {
510     if (!isSVGGraphicsElement())
511         return false;
512
513     rect = toSVGGraphicsElement(this)->getBBox();
514     return true;
515 }
516
517 void SVGElement::setCursorElement(SVGCursorElement* cursorElement)
518 {
519     SVGElementRareData* rareData = ensureSVGRareData();
520     if (SVGCursorElement* oldCursorElement = rareData->cursorElement()) {
521         if (cursorElement == oldCursorElement)
522             return;
523         oldCursorElement->removeReferencedElement(this);
524     }
525     rareData->setCursorElement(cursorElement);
526 }
527
528 #if !ENABLE(OILPAN)
529 void SVGElement::cursorElementRemoved()
530 {
531     svgRareData()->setCursorElement(0);
532 }
533 #endif
534
535 void SVGElement::setCursorImageValue(CSSCursorImageValue* cursorImageValue)
536 {
537     SVGElementRareData* rareData = ensureSVGRareData();
538 #if !ENABLE(OILPAN)
539     if (CSSCursorImageValue* oldCursorImageValue = rareData->cursorImageValue()) {
540         if (cursorImageValue == oldCursorImageValue)
541             return;
542         oldCursorImageValue->removeReferencedElement(this);
543     }
544 #endif
545     rareData->setCursorImageValue(cursorImageValue);
546 }
547
548 #if !ENABLE(OILPAN)
549 void SVGElement::cursorImageValueRemoved()
550 {
551     svgRareData()->setCursorImageValue(0);
552 }
553 #endif
554
555 SVGElement* SVGElement::correspondingElement()
556 {
557     ASSERT(!hasSVGRareData() || !svgRareData()->correspondingElement() || containingShadowRoot());
558     return hasSVGRareData() ? svgRareData()->correspondingElement() : 0;
559 }
560
561 SVGUseElement* SVGElement::correspondingUseElement() const
562 {
563     if (ShadowRoot* root = containingShadowRoot()) {
564         if (isSVGUseElement(root->host()) && (root->type() == ShadowRoot::UserAgentShadowRoot))
565             return toSVGUseElement(root->host());
566     }
567     return 0;
568 }
569
570 void SVGElement::setCorrespondingElement(SVGElement* correspondingElement)
571 {
572     ensureSVGRareData()->setCorrespondingElement(correspondingElement);
573 }
574
575 bool SVGElement::inUseShadowTree() const
576 {
577     return correspondingUseElement();
578 }
579
580 void SVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
581 {
582     if (name == HTMLNames::classAttr) {
583         // SVG animation has currently requires special storage of values so we set
584         // the className here. svgAttributeChanged actually causes the resulting
585         // style updates (instead of Element::parseAttribute). We don't
586         // tell Element about the change to avoid parsing the class list twice
587         SVGParsingError parseError = NoError;
588         m_className->setBaseValueAsString(value, parseError);
589         reportAttributeParsingError(parseError, name, value);
590     } else if (name.matches(XMLNames::langAttr) || name.matches(XMLNames::spaceAttr)) {
591     } else if (name == tabindexAttr) {
592         Element::parseAttribute(name, value);
593     } else {
594         // standard events
595         const AtomicString& eventName = HTMLElement::eventNameForAttributeName(name);
596         if (!eventName.isNull())
597             setAttributeEventListener(eventName, createAttributeEventListener(this, name, value, eventParameterName()));
598         else
599             Element::parseAttribute(name, value);
600     }
601 }
602
603 void SVGElement::parseAttributeNew(const QualifiedName& name, const AtomicString& value)
604 {
605     RefPtr<SVGAnimatedPropertyBase> property = propertyFromAttribute(name);
606     if (property) {
607         SVGParsingError parseError = NoError;
608         property->setBaseValueAsString(value, parseError);
609         reportAttributeParsingError(parseError, name, value);
610
611         return;
612     }
613
614     SVGElement::parseAttribute(name, value);
615 }
616
617 typedef HashMap<QualifiedName, AnimatedPropertyType> AttributeToPropertyTypeMap;
618 AnimatedPropertyType SVGElement::animatedPropertyTypeForCSSAttribute(const QualifiedName& attributeName)
619 {
620     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, cssPropertyMap, ());
621
622     if (cssPropertyMap.isEmpty()) {
623         // Fill the map for the first use.
624         cssPropertyMap.set(alignment_baselineAttr, AnimatedString);
625         cssPropertyMap.set(baseline_shiftAttr, AnimatedString);
626         cssPropertyMap.set(buffered_renderingAttr, AnimatedString);
627         cssPropertyMap.set(clipAttr, AnimatedRect);
628         cssPropertyMap.set(clip_pathAttr, AnimatedString);
629         cssPropertyMap.set(clip_ruleAttr, AnimatedString);
630         cssPropertyMap.set(SVGNames::colorAttr, AnimatedColor);
631         cssPropertyMap.set(color_interpolationAttr, AnimatedString);
632         cssPropertyMap.set(color_interpolation_filtersAttr, AnimatedString);
633         cssPropertyMap.set(color_renderingAttr, AnimatedString);
634         cssPropertyMap.set(cursorAttr, AnimatedString);
635         cssPropertyMap.set(displayAttr, AnimatedString);
636         cssPropertyMap.set(dominant_baselineAttr, AnimatedString);
637         cssPropertyMap.set(fillAttr, AnimatedColor);
638         cssPropertyMap.set(fill_opacityAttr, AnimatedNumber);
639         cssPropertyMap.set(fill_ruleAttr, AnimatedString);
640         cssPropertyMap.set(filterAttr, AnimatedString);
641         cssPropertyMap.set(flood_colorAttr, AnimatedColor);
642         cssPropertyMap.set(flood_opacityAttr, AnimatedNumber);
643         cssPropertyMap.set(font_familyAttr, AnimatedString);
644         cssPropertyMap.set(font_sizeAttr, AnimatedLength);
645         cssPropertyMap.set(font_stretchAttr, AnimatedString);
646         cssPropertyMap.set(font_styleAttr, AnimatedString);
647         cssPropertyMap.set(font_variantAttr, AnimatedString);
648         cssPropertyMap.set(font_weightAttr, AnimatedString);
649         cssPropertyMap.set(image_renderingAttr, AnimatedString);
650         cssPropertyMap.set(letter_spacingAttr, AnimatedLength);
651         cssPropertyMap.set(lighting_colorAttr, AnimatedColor);
652         cssPropertyMap.set(marker_endAttr, AnimatedString);
653         cssPropertyMap.set(marker_midAttr, AnimatedString);
654         cssPropertyMap.set(marker_startAttr, AnimatedString);
655         cssPropertyMap.set(maskAttr, AnimatedString);
656         cssPropertyMap.set(mask_typeAttr, AnimatedString);
657         cssPropertyMap.set(opacityAttr, AnimatedNumber);
658         cssPropertyMap.set(overflowAttr, AnimatedString);
659         cssPropertyMap.set(paint_orderAttr, AnimatedString);
660         cssPropertyMap.set(pointer_eventsAttr, AnimatedString);
661         cssPropertyMap.set(shape_renderingAttr, AnimatedString);
662         cssPropertyMap.set(stop_colorAttr, AnimatedColor);
663         cssPropertyMap.set(stop_opacityAttr, AnimatedNumber);
664         cssPropertyMap.set(strokeAttr, AnimatedColor);
665         cssPropertyMap.set(stroke_dasharrayAttr, AnimatedLengthList);
666         cssPropertyMap.set(stroke_dashoffsetAttr, AnimatedLength);
667         cssPropertyMap.set(stroke_linecapAttr, AnimatedString);
668         cssPropertyMap.set(stroke_linejoinAttr, AnimatedString);
669         cssPropertyMap.set(stroke_miterlimitAttr, AnimatedNumber);
670         cssPropertyMap.set(stroke_opacityAttr, AnimatedNumber);
671         cssPropertyMap.set(stroke_widthAttr, AnimatedLength);
672         cssPropertyMap.set(text_anchorAttr, AnimatedString);
673         cssPropertyMap.set(text_decorationAttr, AnimatedString);
674         cssPropertyMap.set(text_renderingAttr, AnimatedString);
675         cssPropertyMap.set(vector_effectAttr, AnimatedString);
676         cssPropertyMap.set(visibilityAttr, AnimatedString);
677         cssPropertyMap.set(word_spacingAttr, AnimatedLength);
678     }
679
680     if (cssPropertyMap.contains(attributeName))
681         return cssPropertyMap.get(attributeName);
682
683     return AnimatedUnknown;
684 }
685
686 void SVGElement::addToPropertyMap(PassRefPtr<SVGAnimatedPropertyBase> passProperty)
687 {
688     RefPtr<SVGAnimatedPropertyBase> property(passProperty);
689     QualifiedName attributeName = property->attributeName();
690     m_attributeToPropertyMap.set(attributeName, property.release());
691 }
692
693 PassRefPtr<SVGAnimatedPropertyBase> SVGElement::propertyFromAttribute(const QualifiedName& attributeName)
694 {
695     AttributeToPropertyMap::iterator it = m_attributeToPropertyMap.find<SVGAttributeHashTranslator>(attributeName);
696     if (it == m_attributeToPropertyMap.end())
697         return nullptr;
698
699     return it->value;
700 }
701
702 bool SVGElement::isAnimatableCSSProperty(const QualifiedName& attrName)
703 {
704     return animatedPropertyTypeForCSSAttribute(attrName) != AnimatedUnknown;
705 }
706
707 bool SVGElement::isPresentationAttribute(const QualifiedName& name) const
708 {
709     return cssPropertyIdForSVGAttributeName(name) > 0;
710 }
711
712 void SVGElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
713 {
714     CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(name);
715     if (propertyID > 0)
716         addPropertyToPresentationAttributeStyle(style, propertyID, value);
717 }
718
719 bool SVGElement::haveLoadedRequiredResources()
720 {
721     for (SVGElement* child = Traversal<SVGElement>::firstChild(*this); child; child = Traversal<SVGElement>::nextSibling(*child)) {
722         if (!child->haveLoadedRequiredResources())
723             return false;
724     }
725     return true;
726 }
727
728 static inline void collectInstancesForSVGElement(SVGElement* element, WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instances)
729 {
730     ASSERT(element);
731     if (element->containingShadowRoot())
732         return;
733
734     ASSERT(!element->instanceUpdatesBlocked());
735
736     instances = element->instancesForElement();
737 }
738
739 bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> prpListener, bool useCapture)
740 {
741     RefPtr<EventListener> listener = prpListener;
742
743     // Add event listener to regular DOM element
744     if (!Node::addEventListener(eventType, listener, useCapture))
745         return false;
746
747     // Add event listener to all shadow tree DOM element instances
748     WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> > instances;
749     collectInstancesForSVGElement(this, instances);
750     const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = instances.end();
751     for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = instances.begin(); it != end; ++it) {
752         bool result = (*it)->Node::addEventListener(eventType, listener, useCapture);
753         ASSERT_UNUSED(result, result);
754     }
755
756     return true;
757 }
758
759 bool SVGElement::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> prpListener, bool useCapture)
760 {
761     RefPtr<EventListener> listener = prpListener;
762
763     // Remove event listener from regular DOM element
764     if (!Node::removeEventListener(eventType, listener, useCapture))
765         return false;
766
767     // Remove event listener from all shadow tree DOM element instances
768     WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> > instances;
769     collectInstancesForSVGElement(this, instances);
770     const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = instances.end();
771     for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = instances.begin(); it != end; ++it) {
772         SVGElement* shadowTreeElement = *it;
773         ASSERT(shadowTreeElement);
774
775         shadowTreeElement->Node::removeEventListener(eventType, listener, useCapture);
776     }
777
778     return true;
779 }
780
781 static bool hasLoadListener(Element* element)
782 {
783     if (element->hasEventListeners(EventTypeNames::load))
784         return true;
785
786     for (element = element->parentOrShadowHostElement(); element; element = element->parentOrShadowHostElement()) {
787         const EventListenerVector& entry = element->getEventListeners(EventTypeNames::load);
788         for (size_t i = 0; i < entry.size(); ++i) {
789             if (entry[i].useCapture)
790                 return true;
791         }
792     }
793
794     return false;
795 }
796
797 bool SVGElement::sendSVGLoadEventIfPossible()
798 {
799     if (!haveLoadedRequiredResources())
800         return false;
801     if ((isStructurallyExternal() || isSVGSVGElement(*this)) && hasLoadListener(this))
802         dispatchEvent(Event::create(EventTypeNames::load));
803     return true;
804 }
805
806 void SVGElement::sendSVGLoadEventToSelfAndAncestorChainIfPossible()
807 {
808     // Let Document::implicitClose() dispatch the 'load' to the outermost SVG root.
809     if (isOutermostSVGSVGElement())
810         return;
811
812     // Save the next parent to dispatch to in case dispatching the event mutates the tree.
813     RefPtrWillBeRawPtr<Element> parent = parentOrShadowHostElement();
814     if (!sendSVGLoadEventIfPossible())
815         return;
816
817     // If document/window 'load' has been sent already, then only deliver to
818     // the element in question.
819     if (document().loadEventFinished())
820         return;
821
822     if (!parent || !parent->isSVGElement())
823         return;
824
825     toSVGElement(parent)->sendSVGLoadEventToSelfAndAncestorChainIfPossible();
826 }
827
828 void SVGElement::sendSVGLoadEventIfPossibleAsynchronously()
829 {
830     svgLoadEventTimer()->startOneShot(0, FROM_HERE);
831 }
832
833 void SVGElement::svgLoadEventTimerFired(Timer<SVGElement>*)
834 {
835     sendSVGLoadEventIfPossible();
836 }
837
838 Timer<SVGElement>* SVGElement::svgLoadEventTimer()
839 {
840     ASSERT_NOT_REACHED();
841     return 0;
842 }
843
844 void SVGElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason)
845 {
846     Element::attributeChanged(name, newValue);
847
848     if (isIdAttributeName(name))
849         rebuildAllIncomingReferences();
850
851     // Changes to the style attribute are processed lazily (see Element::getAttribute() and related methods),
852     // so we don't want changes to the style attribute to result in extra work here.
853     if (name != HTMLNames::styleAttr)
854         svgAttributeChanged(name);
855 }
856
857 void SVGElement::svgAttributeChanged(const QualifiedName& attrName)
858 {
859     CSSPropertyID propId = SVGElement::cssPropertyIdForSVGAttributeName(attrName);
860     if (propId > 0) {
861         invalidateInstances();
862         return;
863     }
864
865     if (attrName == HTMLNames::classAttr) {
866         classAttributeChanged(AtomicString(m_className->currentValue()->value()));
867         invalidateInstances();
868         return;
869     }
870
871     if (isIdAttributeName(attrName)) {
872         RenderObject* object = renderer();
873         // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions
874         if (object && object->isSVGResourceContainer())
875             toRenderSVGResourceContainer(object)->idChanged();
876         if (inDocument())
877             buildPendingResourcesIfNeeded();
878         invalidateInstances();
879         return;
880     }
881 }
882
883 void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) const
884 {
885     if (!elementData() || !elementData()->m_animatedSVGAttributesAreDirty)
886         return;
887
888     if (name == anyQName()) {
889         AttributeToPropertyMap::const_iterator::Values it = m_attributeToPropertyMap.values().begin();
890         AttributeToPropertyMap::const_iterator::Values end = m_attributeToPropertyMap.values().end();
891         for (; it != end; ++it) {
892             if ((*it)->needsSynchronizeAttribute())
893                 (*it)->synchronizeAttribute();
894         }
895
896         elementData()->m_animatedSVGAttributesAreDirty = false;
897     } else {
898         RefPtr<SVGAnimatedPropertyBase> property = m_attributeToPropertyMap.get(name);
899         if (property && property->needsSynchronizeAttribute())
900             property->synchronizeAttribute();
901     }
902 }
903
904 PassRefPtr<RenderStyle> SVGElement::customStyleForRenderer()
905 {
906     if (!correspondingElement())
907         return document().ensureStyleResolver().styleForElement(this);
908
909     RenderStyle* style = 0;
910     if (Element* parent = parentOrShadowHostElement()) {
911         if (RenderObject* renderer = parent->renderer())
912             style = renderer->style();
913     }
914
915     return document().ensureStyleResolver().styleForElement(correspondingElement(), style, DisallowStyleSharing);
916 }
917
918 MutableStylePropertySet* SVGElement::animatedSMILStyleProperties() const
919 {
920     if (hasSVGRareData())
921         return svgRareData()->animatedSMILStyleProperties();
922     return 0;
923 }
924
925 MutableStylePropertySet* SVGElement::ensureAnimatedSMILStyleProperties()
926 {
927     return ensureSVGRareData()->ensureAnimatedSMILStyleProperties();
928 }
929
930 void SVGElement::setUseOverrideComputedStyle(bool value)
931 {
932     if (hasSVGRareData())
933         svgRareData()->setUseOverrideComputedStyle(value);
934 }
935
936 RenderStyle* SVGElement::computedStyle(PseudoId pseudoElementSpecifier)
937 {
938     if (!hasSVGRareData() || !svgRareData()->useOverrideComputedStyle())
939         return Element::computedStyle(pseudoElementSpecifier);
940
941     RenderStyle* parentStyle = 0;
942     if (Element* parent = parentOrShadowHostElement()) {
943         if (RenderObject* renderer = parent->renderer())
944             parentStyle = renderer->style();
945     }
946
947     return svgRareData()->overrideComputedStyle(this, parentStyle);
948 }
949
950 bool SVGElement::hasFocusEventListeners() const
951 {
952     return hasEventListeners(EventTypeNames::focusin) || hasEventListeners(EventTypeNames::focusout)
953         || hasEventListeners(EventTypeNames::focus) || hasEventListeners(EventTypeNames::blur);
954 }
955
956 void SVGElement::invalidateInstances()
957 {
958     if (!inDocument())
959         return;
960
961     if (instanceUpdatesBlocked())
962         return;
963
964     const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& set = instancesForElement();
965     if (set.isEmpty())
966         return;
967
968     // Mark all use elements referencing 'element' for rebuilding
969     const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = set.end();
970     for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = set.begin(); it != end; ++it) {
971         (*it)->setCorrespondingElement(0);
972
973         if (SVGUseElement* element = (*it)->correspondingUseElement()) {
974             ASSERT(element->inDocument());
975             element->invalidateShadowTree();
976         }
977     }
978
979     svgRareData()->elementInstances().clear();
980
981     document().updateRenderTreeIfNeeded();
982 }
983
984 SVGElement::InstanceUpdateBlocker::InstanceUpdateBlocker(SVGElement* targetElement)
985     : m_targetElement(targetElement)
986 {
987     if (m_targetElement)
988         m_targetElement->setInstanceUpdatesBlocked(true);
989 }
990
991 SVGElement::InstanceUpdateBlocker::~InstanceUpdateBlocker()
992 {
993     if (m_targetElement)
994         m_targetElement->setInstanceUpdatesBlocked(false);
995 }
996
997 #if ENABLE(ASSERT)
998 bool SVGElement::isAnimatableAttribute(const QualifiedName& name) const
999 {
1000     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, animatableAttributes, ());
1001
1002     if (animatableAttributes.isEmpty()) {
1003         animatableAttributes.add(XLinkNames::hrefAttr);
1004         animatableAttributes.add(SVGNames::amplitudeAttr);
1005         animatableAttributes.add(SVGNames::azimuthAttr);
1006         animatableAttributes.add(SVGNames::baseFrequencyAttr);
1007         animatableAttributes.add(SVGNames::biasAttr);
1008         animatableAttributes.add(SVGNames::clipPathUnitsAttr);
1009         animatableAttributes.add(SVGNames::cxAttr);
1010         animatableAttributes.add(SVGNames::cyAttr);
1011         animatableAttributes.add(SVGNames::diffuseConstantAttr);
1012         animatableAttributes.add(SVGNames::divisorAttr);
1013         animatableAttributes.add(SVGNames::dxAttr);
1014         animatableAttributes.add(SVGNames::dyAttr);
1015         animatableAttributes.add(SVGNames::edgeModeAttr);
1016         animatableAttributes.add(SVGNames::elevationAttr);
1017         animatableAttributes.add(SVGNames::exponentAttr);
1018         animatableAttributes.add(SVGNames::filterResAttr);
1019         animatableAttributes.add(SVGNames::filterUnitsAttr);
1020         animatableAttributes.add(SVGNames::fxAttr);
1021         animatableAttributes.add(SVGNames::fyAttr);
1022         animatableAttributes.add(SVGNames::gradientTransformAttr);
1023         animatableAttributes.add(SVGNames::gradientUnitsAttr);
1024         animatableAttributes.add(SVGNames::heightAttr);
1025         animatableAttributes.add(SVGNames::in2Attr);
1026         animatableAttributes.add(SVGNames::inAttr);
1027         animatableAttributes.add(SVGNames::interceptAttr);
1028         animatableAttributes.add(SVGNames::k1Attr);
1029         animatableAttributes.add(SVGNames::k2Attr);
1030         animatableAttributes.add(SVGNames::k3Attr);
1031         animatableAttributes.add(SVGNames::k4Attr);
1032         animatableAttributes.add(SVGNames::kernelMatrixAttr);
1033         animatableAttributes.add(SVGNames::kernelUnitLengthAttr);
1034         animatableAttributes.add(SVGNames::lengthAdjustAttr);
1035         animatableAttributes.add(SVGNames::limitingConeAngleAttr);
1036         animatableAttributes.add(SVGNames::markerHeightAttr);
1037         animatableAttributes.add(SVGNames::markerUnitsAttr);
1038         animatableAttributes.add(SVGNames::markerWidthAttr);
1039         animatableAttributes.add(SVGNames::maskContentUnitsAttr);
1040         animatableAttributes.add(SVGNames::maskUnitsAttr);
1041         animatableAttributes.add(SVGNames::methodAttr);
1042         animatableAttributes.add(SVGNames::modeAttr);
1043         animatableAttributes.add(SVGNames::numOctavesAttr);
1044         animatableAttributes.add(SVGNames::offsetAttr);
1045         animatableAttributes.add(SVGNames::operatorAttr);
1046         animatableAttributes.add(SVGNames::orderAttr);
1047         animatableAttributes.add(SVGNames::orientAttr);
1048         animatableAttributes.add(SVGNames::pathLengthAttr);
1049         animatableAttributes.add(SVGNames::patternContentUnitsAttr);
1050         animatableAttributes.add(SVGNames::patternTransformAttr);
1051         animatableAttributes.add(SVGNames::patternUnitsAttr);
1052         animatableAttributes.add(SVGNames::pointsAtXAttr);
1053         animatableAttributes.add(SVGNames::pointsAtYAttr);
1054         animatableAttributes.add(SVGNames::pointsAtZAttr);
1055         animatableAttributes.add(SVGNames::preserveAlphaAttr);
1056         animatableAttributes.add(SVGNames::preserveAspectRatioAttr);
1057         animatableAttributes.add(SVGNames::primitiveUnitsAttr);
1058         animatableAttributes.add(SVGNames::radiusAttr);
1059         animatableAttributes.add(SVGNames::rAttr);
1060         animatableAttributes.add(SVGNames::refXAttr);
1061         animatableAttributes.add(SVGNames::refYAttr);
1062         animatableAttributes.add(SVGNames::resultAttr);
1063         animatableAttributes.add(SVGNames::rotateAttr);
1064         animatableAttributes.add(SVGNames::rxAttr);
1065         animatableAttributes.add(SVGNames::ryAttr);
1066         animatableAttributes.add(SVGNames::scaleAttr);
1067         animatableAttributes.add(SVGNames::seedAttr);
1068         animatableAttributes.add(SVGNames::slopeAttr);
1069         animatableAttributes.add(SVGNames::spacingAttr);
1070         animatableAttributes.add(SVGNames::specularConstantAttr);
1071         animatableAttributes.add(SVGNames::specularExponentAttr);
1072         animatableAttributes.add(SVGNames::spreadMethodAttr);
1073         animatableAttributes.add(SVGNames::startOffsetAttr);
1074         animatableAttributes.add(SVGNames::stdDeviationAttr);
1075         animatableAttributes.add(SVGNames::stitchTilesAttr);
1076         animatableAttributes.add(SVGNames::surfaceScaleAttr);
1077         animatableAttributes.add(SVGNames::tableValuesAttr);
1078         animatableAttributes.add(SVGNames::targetAttr);
1079         animatableAttributes.add(SVGNames::targetXAttr);
1080         animatableAttributes.add(SVGNames::targetYAttr);
1081         animatableAttributes.add(SVGNames::transformAttr);
1082         animatableAttributes.add(SVGNames::typeAttr);
1083         animatableAttributes.add(SVGNames::valuesAttr);
1084         animatableAttributes.add(SVGNames::viewBoxAttr);
1085         animatableAttributes.add(SVGNames::widthAttr);
1086         animatableAttributes.add(SVGNames::x1Attr);
1087         animatableAttributes.add(SVGNames::x2Attr);
1088         animatableAttributes.add(SVGNames::xAttr);
1089         animatableAttributes.add(SVGNames::xChannelSelectorAttr);
1090         animatableAttributes.add(SVGNames::y1Attr);
1091         animatableAttributes.add(SVGNames::y2Attr);
1092         animatableAttributes.add(SVGNames::yAttr);
1093         animatableAttributes.add(SVGNames::yChannelSelectorAttr);
1094         animatableAttributes.add(SVGNames::zAttr);
1095     }
1096
1097     if (name == classAttr)
1098         return true;
1099
1100     return animatableAttributes.contains(name);
1101 }
1102 #endif
1103
1104 SVGElementSet* SVGElement::setOfIncomingReferences() const
1105 {
1106     if (!hasSVGRareData())
1107         return 0;
1108     return &svgRareData()->incomingReferences();
1109 }
1110
1111 void SVGElement::addReferenceTo(SVGElement* targetElement)
1112 {
1113     ASSERT(targetElement);
1114
1115     ensureSVGRareData()->outgoingReferences().add(targetElement);
1116     targetElement->ensureSVGRareData()->incomingReferences().add(this);
1117 }
1118
1119 void SVGElement::rebuildAllIncomingReferences()
1120 {
1121     if (!hasSVGRareData())
1122         return;
1123
1124     const SVGElementSet& incomingReferences = svgRareData()->incomingReferences();
1125
1126     // Iterate on a snapshot as |incomingReferences| may be altered inside loop.
1127     WillBeHeapVector<RawPtrWillBeMember<SVGElement> > incomingReferencesSnapshot;
1128     copyToVector(incomingReferences, incomingReferencesSnapshot);
1129
1130     // Force rebuilding the |sourceElement| so it knows about this change.
1131     for (WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::iterator it = incomingReferencesSnapshot.begin(), itEnd = incomingReferencesSnapshot.end(); it != itEnd; ++it) {
1132         SVGElement* sourceElement = *it;
1133
1134         // Before rebuilding |sourceElement| ensure it was not removed from under us.
1135         if (incomingReferences.contains(sourceElement))
1136             sourceElement->svgAttributeChanged(XLinkNames::hrefAttr);
1137     }
1138 }
1139
1140 void SVGElement::removeAllIncomingReferences()
1141 {
1142     if (!hasSVGRareData())
1143         return;
1144
1145     SVGElementSet& incomingReferences = svgRareData()->incomingReferences();
1146     for (SVGElementSet::iterator it = incomingReferences.begin(), itEnd = incomingReferences.end(); it != itEnd; ++it) {
1147         SVGElement* sourceElement = *it;
1148         ASSERT(sourceElement->hasSVGRareData());
1149         sourceElement->ensureSVGRareData()->outgoingReferences().remove(this);
1150     }
1151     incomingReferences.clear();
1152 }
1153
1154 void SVGElement::removeAllOutgoingReferences()
1155 {
1156     if (!hasSVGRareData())
1157         return;
1158
1159     SVGElementSet& outgoingReferences = svgRareData()->outgoingReferences();
1160     for (SVGElementSet::iterator it = outgoingReferences.begin(), itEnd = outgoingReferences.end(); it != itEnd; ++it) {
1161         SVGElement* targetElement = *it;
1162         ASSERT(targetElement->hasSVGRareData());
1163         targetElement->ensureSVGRareData()->incomingReferences().remove(this);
1164     }
1165     outgoingReferences.clear();
1166 }
1167
1168 void SVGElement::trace(Visitor* visitor)
1169 {
1170 #if ENABLE(OILPAN)
1171     visitor->trace(m_elementsWithRelativeLengths);
1172     visitor->trace(m_SVGRareData);
1173 #endif
1174     Element::trace(visitor);
1175 }
1176
1177 const AtomicString& SVGElement::eventParameterName()
1178 {
1179     DEFINE_STATIC_LOCAL(const AtomicString, evtString, ("evt", AtomicString::ConstructFromLiteral));
1180     return evtString;
1181 }
1182
1183 } // namespace blink