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