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