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