LCOV - code coverage report
Current view: top level - dom/svg - nsSVGElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 321 1196 26.8 %
Date: 2017-07-14 16:53:18 Functions: 40 128 31.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/ArrayUtils.h"
       8             : #include "mozilla/DebugOnly.h"
       9             : #include "mozilla/Unused.h"
      10             : 
      11             : #include "nsSVGElement.h"
      12             : 
      13             : #include "mozilla/dom/SVGSVGElement.h"
      14             : #include "mozilla/dom/SVGTests.h"
      15             : #include "nsContentUtils.h"
      16             : #include "nsICSSDeclaration.h"
      17             : #include "nsIContentInlines.h"
      18             : #include "nsIDocument.h"
      19             : #include "nsIDOMMutationEvent.h"
      20             : #include "mozilla/InternalMutationEvent.h"
      21             : #include "mozAutoDocUpdate.h"
      22             : #include "nsError.h"
      23             : #include "nsIPresShell.h"
      24             : #include "nsGkAtoms.h"
      25             : #include "nsRuleWalker.h"
      26             : #include "mozilla/css/Declaration.h"
      27             : #include "nsCSSProps.h"
      28             : #include "nsCSSParser.h"
      29             : #include "mozilla/EventListenerManager.h"
      30             : #include "nsLayoutUtils.h"
      31             : #include "nsSVGAnimatedTransformList.h"
      32             : #include "nsSVGLength2.h"
      33             : #include "nsSVGNumber2.h"
      34             : #include "nsSVGNumberPair.h"
      35             : #include "nsSVGInteger.h"
      36             : #include "nsSVGIntegerPair.h"
      37             : #include "nsSVGAngle.h"
      38             : #include "nsSVGBoolean.h"
      39             : #include "nsSVGEnum.h"
      40             : #include "nsSVGViewBox.h"
      41             : #include "nsSVGString.h"
      42             : #include "mozilla/dom/SVGAnimatedEnumeration.h"
      43             : #include "SVGAnimatedNumberList.h"
      44             : #include "SVGAnimatedLengthList.h"
      45             : #include "SVGAnimatedPointList.h"
      46             : #include "SVGAnimatedPathSegList.h"
      47             : #include "SVGContentUtils.h"
      48             : #include "SVGGeometryElement.h"
      49             : #include "nsIFrame.h"
      50             : #include "nsQueryObject.h"
      51             : #include <stdarg.h>
      52             : #include "SVGMotionSMILAttr.h"
      53             : #include "nsAttrValueOrString.h"
      54             : #include "nsSMILAnimationController.h"
      55             : #include "mozilla/dom/SVGElementBinding.h"
      56             : #include "mozilla/DeclarationBlock.h"
      57             : #include "mozilla/DeclarationBlockInlines.h"
      58             : #include "mozilla/Unused.h"
      59             : #include "mozilla/RestyleManager.h"
      60             : #include "mozilla/RestyleManagerInlines.h"
      61             : 
      62             : using namespace mozilla;
      63             : using namespace mozilla::dom;
      64             : 
      65             : // This is needed to ensure correct handling of calls to the
      66             : // vararg-list methods in this file:
      67             : //   nsSVGElement::GetAnimated{Length,Number,Integer}Values
      68             : // See bug 547964 for details:
      69             : static_assert(sizeof(void*) == sizeof(nullptr),
      70             :               "nullptr should be the correct size");
      71             : 
      72             : nsresult
      73           0 : NS_NewSVGElement(Element **aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
      74             : {
      75           0 :   RefPtr<nsSVGElement> it = new nsSVGElement(aNodeInfo);
      76           0 :   nsresult rv = it->Init();
      77             : 
      78           0 :   if (NS_FAILED(rv)) {
      79           0 :     return rv;
      80             :   }
      81             : 
      82           0 :   it.forget(aResult);
      83           0 :   return rv;
      84             : }
      85             : 
      86           0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGElement)
      87             : 
      88             : nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = {
      89             :   {&nsGkAtoms::userSpaceOnUse, SVG_UNIT_TYPE_USERSPACEONUSE},
      90             :   {&nsGkAtoms::objectBoundingBox, SVG_UNIT_TYPE_OBJECTBOUNDINGBOX},
      91             :   {nullptr, 0}
      92             : };
      93             : 
      94         156 : nsSVGElement::nsSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
      95         156 :   : nsSVGElementBase(aNodeInfo)
      96             : {
      97         156 : }
      98             : 
      99           0 : nsSVGElement::~nsSVGElement()
     100             : {
     101           0 :   OwnerDoc()->UnscheduleSVGForPresAttrEvaluation(this);
     102           0 : }
     103             : 
     104             : JSObject*
     105           0 : nsSVGElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
     106             : {
     107           0 :   return SVGElementBinding::Wrap(aCx, this, aGivenProto);
     108             : }
     109             : 
     110             : //----------------------------------------------------------------------
     111             : 
     112             : NS_IMETHODIMP
     113           0 : nsSVGElement::GetSVGClassName(nsISupports** aClassName)
     114             : {
     115           0 :   *aClassName = ClassName().take();
     116           0 :   return NS_OK;
     117             : }
     118             : 
     119             : NS_IMETHODIMP
     120           0 : nsSVGElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
     121             : {
     122           0 :   NS_ADDREF(*aStyle = Style());
     123           0 :   return NS_OK;
     124             : }
     125             : 
     126             : //----------------------------------------------------------------------
     127             : // nsSVGElement methods
     128             : 
     129             : void
     130           0 : nsSVGElement::DidAnimateClass()
     131             : {
     132             :   // For Servo, snapshot the element before we change it.
     133           0 :   nsIPresShell* shell = OwnerDoc()->GetShell();
     134           0 :   if (shell) {
     135           0 :     nsPresContext* presContext = shell->GetPresContext();
     136           0 :     if (presContext && presContext->RestyleManager()->IsServo()) {
     137             :       presContext->RestyleManager()
     138             :                  ->AsServo()
     139           0 :                  ->ClassAttributeWillBeChangedBySMIL(this);
     140             :     }
     141             :   }
     142             : 
     143           0 :   nsAutoString src;
     144           0 :   mClassAttribute.GetAnimValue(src, this);
     145           0 :   if (!mClassAnimAttr) {
     146           0 :     mClassAnimAttr = new nsAttrValue();
     147             :   }
     148           0 :   mClassAnimAttr->ParseAtomArray(src);
     149             : 
     150           0 :   if (shell) {
     151           0 :     shell->RestyleForAnimation(this, eRestyle_Self);
     152             :   }
     153           0 : }
     154             : 
     155             : nsresult
     156         151 : nsSVGElement::Init()
     157             : {
     158             :   // Set up length attributes - can't do this in the constructor
     159             :   // because we can't do a virtual call at that point
     160             : 
     161         151 :   LengthAttributesInfo lengthInfo = GetLengthInfo();
     162             : 
     163             :   uint32_t i;
     164         451 :   for (i = 0; i < lengthInfo.mLengthCount; i++) {
     165         300 :     lengthInfo.Reset(i);
     166             :   }
     167             : 
     168         151 :   NumberAttributesInfo numberInfo = GetNumberInfo();
     169             : 
     170         224 :   for (i = 0; i < numberInfo.mNumberCount; i++) {
     171          73 :     numberInfo.Reset(i);
     172             :   }
     173             : 
     174         151 :   NumberPairAttributesInfo numberPairInfo = GetNumberPairInfo();
     175             : 
     176         151 :   for (i = 0; i < numberPairInfo.mNumberPairCount; i++) {
     177           0 :     numberPairInfo.Reset(i);
     178             :   }
     179             : 
     180         151 :   IntegerAttributesInfo integerInfo = GetIntegerInfo();
     181             : 
     182         151 :   for (i = 0; i < integerInfo.mIntegerCount; i++) {
     183           0 :     integerInfo.Reset(i);
     184             :   }
     185             : 
     186         151 :   IntegerPairAttributesInfo integerPairInfo = GetIntegerPairInfo();
     187             : 
     188         151 :   for (i = 0; i < integerPairInfo.mIntegerPairCount; i++) {
     189           0 :     integerPairInfo.Reset(i);
     190             :   }
     191             : 
     192         151 :   AngleAttributesInfo angleInfo = GetAngleInfo();
     193             : 
     194         151 :   for (i = 0; i < angleInfo.mAngleCount; i++) {
     195           0 :     angleInfo.Reset(i);
     196             :   }
     197             : 
     198         151 :   BooleanAttributesInfo booleanInfo = GetBooleanInfo();
     199             : 
     200         151 :   for (i = 0; i < booleanInfo.mBooleanCount; i++) {
     201           0 :     booleanInfo.Reset(i);
     202             :   }
     203             : 
     204         151 :   EnumAttributesInfo enumInfo = GetEnumInfo();
     205             : 
     206         183 :   for (i = 0; i < enumInfo.mEnumCount; i++) {
     207          32 :     enumInfo.Reset(i);
     208             :   }
     209             : 
     210         151 :   nsSVGViewBox *viewBox = GetViewBox();
     211             : 
     212         151 :   if (viewBox) {
     213          22 :     viewBox->Init();
     214             :   }
     215             : 
     216             :   SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
     217         151 :     GetPreserveAspectRatio();
     218             : 
     219         151 :   if (preserveAspectRatio) {
     220          22 :     preserveAspectRatio->Init();
     221             :   }
     222             : 
     223         151 :   LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
     224             : 
     225         151 :   for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
     226           0 :     lengthListInfo.Reset(i);
     227             :   }
     228             : 
     229         151 :   NumberListAttributesInfo numberListInfo = GetNumberListInfo();
     230             : 
     231         151 :   for (i = 0; i < numberListInfo.mNumberListCount; i++) {
     232           0 :     numberListInfo.Reset(i);
     233             :   }
     234             : 
     235             :   // No need to reset SVGPointList since the default value is always the same
     236             :   // (an empty list).
     237             : 
     238             :   // No need to reset SVGPathData since the default value is always the same
     239             :   // (an empty list).
     240             : 
     241         151 :   StringAttributesInfo stringInfo = GetStringInfo();
     242             : 
     243         209 :   for (i = 0; i < stringInfo.mStringCount; i++) {
     244          58 :     stringInfo.Reset(i);
     245             :   }
     246             : 
     247         151 :   return NS_OK;
     248             : }
     249             : 
     250             : //----------------------------------------------------------------------
     251             : // nsISupports methods
     252             : 
     253        6813 : NS_IMPL_ISUPPORTS_INHERITED(nsSVGElement, nsSVGElementBase,
     254             :                             nsIDOMNode, nsIDOMElement,
     255             :                             nsIDOMSVGElement)
     256             : 
     257             : //----------------------------------------------------------------------
     258             : // Implementation
     259             : 
     260             : //----------------------------------------------------------------------
     261             : // nsIContent methods
     262             : 
     263             : nsresult
     264         156 : nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
     265             :                          nsIContent* aBindingParent,
     266             :                          bool aCompileEventHandlers)
     267             : {
     268         156 :   nsresult rv = nsSVGElementBase::BindToTree(aDocument, aParent,
     269             :                                              aBindingParent,
     270         156 :                                              aCompileEventHandlers);
     271         156 :   NS_ENSURE_SUCCESS(rv, rv);
     272             : 
     273         156 :   if (!MayHaveStyle()) {
     274         156 :     return NS_OK;
     275             :   }
     276           0 :   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
     277             : 
     278           0 :   if (oldVal && oldVal->Type() == nsAttrValue::eCSSDeclaration) {
     279             :     // we need to force a reparse because the baseURI of the document
     280             :     // may have changed, and in particular because we may be clones of
     281             :     // XBL anonymous content now being bound to the document we should
     282             :     // render in and due to the hacky way in which we implement the
     283             :     // interaction of XBL and SVG resources.  Once we have a sane
     284             :     // ownerDocument on XBL anonymous content, this can all go away.
     285           0 :     nsAttrValue attrValue;
     286           0 :     nsAutoString stringValue;
     287           0 :     oldVal->ToString(stringValue);
     288             :     // Force in data doc, since we already have a style rule
     289           0 :     ParseStyleAttribute(stringValue, attrValue, true);
     290             :     // Don't bother going through SetInlineStyleDeclaration; we don't
     291             :     // want to fire off mutation events or document notifications anyway
     292             :     bool oldValueSet;
     293           0 :     rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
     294           0 :                                           &oldValueSet);
     295           0 :     NS_ENSURE_SUCCESS(rv, rv);
     296             :   }
     297             : 
     298           0 :   return NS_OK;
     299             : }
     300             : 
     301             : nsresult
     302         374 : nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     303             :                            const nsAttrValue* aValue,
     304             :                            const nsAttrValue* aOldValue, bool aNotify)
     305             : {
     306             :   // We don't currently use nsMappedAttributes within SVG. If this changes, we
     307             :   // need to be very careful because some nsAttrValues used by SVG point to
     308             :   // member data of SVG elements and if an nsAttrValue outlives the SVG element
     309             :   // whose data it points to (by virtue of being stored in
     310             :   // mAttrsAndChildren->mMappedAttributes, meaning it's shared between
     311             :   // elements), the pointer will dangle. See bug 724680.
     312         374 :   MOZ_ASSERT(!mAttrsAndChildren.HasMappedAttrs(),
     313             :              "Unexpected use of nsMappedAttributes within SVG");
     314             : 
     315             :   // If this is an svg presentation attribute we need to map it into
     316             :   // the content declaration block.
     317             :   // XXX For some reason incremental mapping doesn't work, so for now
     318             :   // just delete the style rule and lazily reconstruct it as needed).
     319         374 :   if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
     320          97 :     mContentDeclarationBlock = nullptr;
     321          97 :     if (OwnerDoc()->GetStyleBackendType() == StyleBackendType::Servo) {
     322           0 :       OwnerDoc()->ScheduleSVGForPresAttrEvaluation(this);
     323             :     }
     324             :   }
     325             : 
     326         374 :   if (IsEventAttributeName(aName) && aValue) {
     327           0 :     MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
     328             :                "Expected string value for script body");
     329           0 :     nsresult rv = SetEventHandler(GetEventNameForAttr(aName),
     330           0 :                                   aValue->GetStringValue());
     331           0 :     NS_ENSURE_SUCCESS(rv, rv);
     332             :   }
     333             : 
     334         374 :   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
     335         374 :                                         aNotify);
     336             : }
     337             : 
     338             : bool
     339         360 : nsSVGElement::ParseAttribute(int32_t aNamespaceID,
     340             :                              nsIAtom* aAttribute,
     341             :                              const nsAString& aValue,
     342             :                              nsAttrValue& aResult)
     343             : {
     344         360 :   nsresult rv = NS_OK;
     345         360 :   bool foundMatch = false;
     346         360 :   bool didSetResult = false;
     347             : 
     348         360 :   if (aNamespaceID == kNameSpaceID_None) {
     349             :     // Check for nsSVGLength2 attribute
     350         312 :     LengthAttributesInfo lengthInfo = GetLengthInfo();
     351             : 
     352             :     uint32_t i;
     353         797 :     for (i = 0; i < lengthInfo.mLengthCount; i++) {
     354         591 :       if (aAttribute == *lengthInfo.mLengthInfo[i].mName) {
     355         106 :         rv = lengthInfo.mLengths[i].SetBaseValueString(aValue, this, false);
     356         106 :         if (NS_FAILED(rv)) {
     357           0 :           lengthInfo.Reset(i);
     358             :         } else {
     359         106 :           aResult.SetTo(lengthInfo.mLengths[i], &aValue);
     360         106 :           didSetResult = true;
     361             :         }
     362         106 :         foundMatch = true;
     363         106 :         break;
     364             :       }
     365             :     }
     366             : 
     367         312 :     if (!foundMatch) {
     368             :       // Check for SVGAnimatedLengthList attribute
     369         206 :       LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
     370         206 :       for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
     371           0 :         if (aAttribute == *lengthListInfo.mLengthListInfo[i].mName) {
     372           0 :           rv = lengthListInfo.mLengthLists[i].SetBaseValueString(aValue);
     373           0 :           if (NS_FAILED(rv)) {
     374           0 :             lengthListInfo.Reset(i);
     375             :           } else {
     376           0 :             aResult.SetTo(lengthListInfo.mLengthLists[i].GetBaseValue(),
     377           0 :                           &aValue);
     378           0 :             didSetResult = true;
     379             :           }
     380           0 :           foundMatch = true;
     381           0 :           break;
     382             :         }
     383             :       }
     384             :     }
     385             : 
     386         312 :     if (!foundMatch) {
     387             :       // Check for SVGAnimatedNumberList attribute
     388         206 :       NumberListAttributesInfo numberListInfo = GetNumberListInfo();
     389         206 :       for (i = 0; i < numberListInfo.mNumberListCount; i++) {
     390           0 :         if (aAttribute == *numberListInfo.mNumberListInfo[i].mName) {
     391           0 :           rv = numberListInfo.mNumberLists[i].SetBaseValueString(aValue);
     392           0 :           if (NS_FAILED(rv)) {
     393           0 :             numberListInfo.Reset(i);
     394             :           } else {
     395           0 :             aResult.SetTo(numberListInfo.mNumberLists[i].GetBaseValue(),
     396           0 :                           &aValue);
     397           0 :             didSetResult = true;
     398             :           }
     399           0 :           foundMatch = true;
     400           0 :           break;
     401             :         }
     402             :       }
     403             :     }
     404             : 
     405         312 :     if (!foundMatch) {
     406             :       // Check for SVGAnimatedPointList attribute
     407         206 :       if (GetPointListAttrName() == aAttribute) {
     408          14 :         SVGAnimatedPointList* pointList = GetAnimatedPointList();
     409          14 :         if (pointList) {
     410          14 :           pointList->SetBaseValueString(aValue);
     411             :           // The spec says we parse everything up to the failure, so we DON'T
     412             :           // need to check the result of SetBaseValueString or call
     413             :           // pointList->ClearBaseValue() if it fails
     414          14 :           aResult.SetTo(pointList->GetBaseValue(), &aValue);
     415          14 :           didSetResult = true;
     416          14 :           foundMatch = true;
     417             :         }
     418             :       }
     419             :     }
     420             : 
     421         312 :     if (!foundMatch) {
     422             :       // Check for SVGAnimatedPathSegList attribute
     423         192 :       if (GetPathDataAttrName() == aAttribute) {
     424          44 :         SVGAnimatedPathSegList* segList = GetAnimPathSegList();
     425          44 :         if (segList) {
     426          44 :           segList->SetBaseValueString(aValue);
     427             :           // The spec says we parse everything up to the failure, so we DON'T
     428             :           // need to check the result of SetBaseValueString or call
     429             :           // segList->ClearBaseValue() if it fails
     430          44 :           aResult.SetTo(segList->GetBaseValue(), &aValue);
     431          44 :           didSetResult = true;
     432          44 :           foundMatch = true;
     433             :         }
     434             :       }
     435             :     }
     436             : 
     437         312 :     if (!foundMatch) {
     438             :       // Check for nsSVGNumber2 attribute
     439         148 :       NumberAttributesInfo numberInfo = GetNumberInfo();
     440         213 :       for (i = 0; i < numberInfo.mNumberCount; i++) {
     441          65 :         if (aAttribute == *numberInfo.mNumberInfo[i].mName) {
     442           0 :           rv = numberInfo.mNumbers[i].SetBaseValueString(aValue, this);
     443           0 :           if (NS_FAILED(rv)) {
     444           0 :             numberInfo.Reset(i);
     445             :           } else {
     446           0 :             aResult.SetTo(numberInfo.mNumbers[i].GetBaseValue(), &aValue);
     447           0 :             didSetResult = true;
     448             :           }
     449           0 :           foundMatch = true;
     450           0 :           break;
     451             :         }
     452             :       }
     453             :     }
     454             : 
     455         312 :     if (!foundMatch) {
     456             :       // Check for nsSVGNumberPair attribute
     457         148 :       NumberPairAttributesInfo numberPairInfo = GetNumberPairInfo();
     458         148 :       for (i = 0; i < numberPairInfo.mNumberPairCount; i++) {
     459           0 :         if (aAttribute == *numberPairInfo.mNumberPairInfo[i].mName) {
     460           0 :           rv = numberPairInfo.mNumberPairs[i].SetBaseValueString(aValue, this);
     461           0 :           if (NS_FAILED(rv)) {
     462           0 :             numberPairInfo.Reset(i);
     463             :           } else {
     464           0 :             aResult.SetTo(numberPairInfo.mNumberPairs[i], &aValue);
     465           0 :             didSetResult = true;
     466             :           }
     467           0 :           foundMatch = true;
     468           0 :           break;
     469             :         }
     470             :       }
     471             :     }
     472             : 
     473         312 :     if (!foundMatch) {
     474             :       // Check for nsSVGInteger attribute
     475         148 :       IntegerAttributesInfo integerInfo = GetIntegerInfo();
     476         148 :       for (i = 0; i < integerInfo.mIntegerCount; i++) {
     477           0 :         if (aAttribute == *integerInfo.mIntegerInfo[i].mName) {
     478           0 :           rv = integerInfo.mIntegers[i].SetBaseValueString(aValue, this);
     479           0 :           if (NS_FAILED(rv)) {
     480           0 :             integerInfo.Reset(i);
     481             :           } else {
     482           0 :             aResult.SetTo(integerInfo.mIntegers[i].GetBaseValue(), &aValue);
     483           0 :             didSetResult = true;
     484             :           }
     485           0 :           foundMatch = true;
     486           0 :           break;
     487             :         }
     488             :       }
     489             :     }
     490             : 
     491         312 :     if (!foundMatch) {
     492             :       // Check for nsSVGIntegerPair attribute
     493         148 :       IntegerPairAttributesInfo integerPairInfo = GetIntegerPairInfo();
     494         148 :       for (i = 0; i < integerPairInfo.mIntegerPairCount; i++) {
     495           0 :         if (aAttribute == *integerPairInfo.mIntegerPairInfo[i].mName) {
     496             :           rv =
     497           0 :             integerPairInfo.mIntegerPairs[i].SetBaseValueString(aValue, this);
     498           0 :           if (NS_FAILED(rv)) {
     499           0 :             integerPairInfo.Reset(i);
     500             :           } else {
     501           0 :             aResult.SetTo(integerPairInfo.mIntegerPairs[i], &aValue);
     502           0 :             didSetResult = true;
     503             :           }
     504           0 :           foundMatch = true;
     505           0 :           break;
     506             :         }
     507             :       }
     508             :     }
     509             : 
     510         312 :     if (!foundMatch) {
     511             :       // Check for nsSVGAngle attribute
     512         148 :       AngleAttributesInfo angleInfo = GetAngleInfo();
     513         148 :       for (i = 0; i < angleInfo.mAngleCount; i++) {
     514           0 :         if (aAttribute == *angleInfo.mAngleInfo[i].mName) {
     515           0 :           rv = angleInfo.mAngles[i].SetBaseValueString(aValue, this, false);
     516           0 :           if (NS_FAILED(rv)) {
     517           0 :             angleInfo.Reset(i);
     518             :           } else {
     519           0 :             aResult.SetTo(angleInfo.mAngles[i], &aValue);
     520           0 :             didSetResult = true;
     521             :           }
     522           0 :           foundMatch = true;
     523           0 :           break;
     524             :         }
     525             :       }
     526             :     }
     527             : 
     528         312 :     if (!foundMatch) {
     529             :       // Check for nsSVGBoolean attribute
     530         148 :       BooleanAttributesInfo booleanInfo = GetBooleanInfo();
     531         148 :       for (i = 0; i < booleanInfo.mBooleanCount; i++) {
     532           0 :         if (aAttribute == *booleanInfo.mBooleanInfo[i].mName) {
     533           0 :           nsIAtom *valAtom = NS_GetStaticAtom(aValue);
     534           0 :           rv = valAtom ? booleanInfo.mBooleans[i].SetBaseValueAtom(valAtom, this) :
     535             :                  NS_ERROR_DOM_SYNTAX_ERR;
     536           0 :           if (NS_FAILED(rv)) {
     537           0 :             booleanInfo.Reset(i);
     538             :           } else {
     539           0 :             aResult.SetTo(valAtom);
     540           0 :             didSetResult = true;
     541             :           }
     542           0 :           foundMatch = true;
     543           0 :           break;
     544             :         }
     545             :       }
     546             :     }
     547             : 
     548         312 :     if (!foundMatch) {
     549             :       // Check for nsSVGEnum attribute
     550         148 :       EnumAttributesInfo enumInfo = GetEnumInfo();
     551         178 :       for (i = 0; i < enumInfo.mEnumCount; i++) {
     552          36 :         if (aAttribute == *enumInfo.mEnumInfo[i].mName) {
     553          12 :           nsCOMPtr<nsIAtom> valAtom = NS_Atomize(aValue);
     554           6 :           rv = enumInfo.mEnums[i].SetBaseValueAtom(valAtom, this);
     555           6 :           if (NS_FAILED(rv)) {
     556           0 :             enumInfo.Reset(i);
     557             :           } else {
     558           6 :             aResult.SetTo(valAtom);
     559           6 :             didSetResult = true;
     560             :           }
     561           6 :           foundMatch = true;
     562           6 :           break;
     563             :         }
     564             :       }
     565             :     }
     566             : 
     567         312 :     if (!foundMatch) {
     568             :       // Check for conditional processing attributes
     569         284 :       nsCOMPtr<SVGTests> tests = do_QueryObject(this);
     570         142 :       if (tests && tests->ParseConditionalProcessingAttribute(
     571         142 :                             aAttribute, aValue, aResult)) {
     572           0 :         foundMatch = true;
     573             :       }
     574             :     }
     575             : 
     576         312 :     if (!foundMatch) {
     577             :       // Check for StringList attribute
     578         142 :       StringListAttributesInfo stringListInfo = GetStringListInfo();
     579         142 :       for (i = 0; i < stringListInfo.mStringListCount; i++) {
     580           0 :         if (aAttribute == *stringListInfo.mStringListInfo[i].mName) {
     581           0 :           rv = stringListInfo.mStringLists[i].SetValue(aValue);
     582           0 :           if (NS_FAILED(rv)) {
     583           0 :             stringListInfo.Reset(i);
     584             :           } else {
     585           0 :             aResult.SetTo(stringListInfo.mStringLists[i], &aValue);
     586           0 :             didSetResult = true;
     587             :           }
     588           0 :           foundMatch = true;
     589           0 :           break;
     590             :         }
     591             :       }
     592             :     }
     593             : 
     594         312 :     if (!foundMatch) {
     595             :       // Check for nsSVGViewBox attribute
     596         142 :       if (aAttribute == nsGkAtoms::viewBox) {
     597          16 :         nsSVGViewBox* viewBox = GetViewBox();
     598          16 :         if (viewBox) {
     599          16 :           rv = viewBox->SetBaseValueString(aValue, this, false);
     600          16 :           if (NS_FAILED(rv)) {
     601           0 :             viewBox->Init();
     602             :           } else {
     603          16 :             aResult.SetTo(*viewBox, &aValue);
     604          16 :             didSetResult = true;
     605             :           }
     606          16 :           foundMatch = true;
     607             :         }
     608             :       // Check for SVGAnimatedPreserveAspectRatio attribute
     609         126 :       } else if (aAttribute == nsGkAtoms::preserveAspectRatio) {
     610             :         SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
     611           3 :           GetPreserveAspectRatio();
     612           3 :         if (preserveAspectRatio) {
     613           3 :           rv = preserveAspectRatio->SetBaseValueString(aValue, this, false);
     614           3 :           if (NS_FAILED(rv)) {
     615           0 :             preserveAspectRatio->Init();
     616             :           } else {
     617           3 :             aResult.SetTo(*preserveAspectRatio, &aValue);
     618           3 :             didSetResult = true;
     619             :           }
     620           3 :           foundMatch = true;
     621             :         }
     622             :       // Check for SVGAnimatedTransformList attribute
     623         123 :       } else if (GetTransformListAttrName() == aAttribute) {
     624             :         // The transform attribute is being set, so we must ensure that the
     625             :         // nsSVGAnimatedTransformList is/has been allocated:
     626             :         nsSVGAnimatedTransformList *transformList =
     627           7 :           GetAnimatedTransformList(DO_ALLOCATE);
     628           7 :         rv = transformList->SetBaseValueString(aValue);
     629           7 :         if (NS_FAILED(rv)) {
     630           0 :           transformList->ClearBaseValue();
     631             :         } else {
     632           7 :           aResult.SetTo(transformList->GetBaseValue(), &aValue);
     633           7 :           didSetResult = true;
     634             :         }
     635           7 :         foundMatch = true;
     636         116 :       } else if (aAttribute == nsGkAtoms::tabindex) {
     637           0 :         didSetResult = aResult.ParseIntValue(aValue);
     638           0 :         foundMatch = true;
     639             :       }
     640             :     }
     641             : 
     642         312 :     if (aAttribute == nsGkAtoms::_class) {
     643           0 :       mClassAttribute.SetBaseValue(aValue, this, false);
     644           0 :       aResult.ParseAtomArray(aValue);
     645           0 :       return true;
     646             :     }
     647             :   }
     648             : 
     649         360 :   if (!foundMatch) {
     650             :     // Check for nsSVGString attribute
     651         164 :     StringAttributesInfo stringInfo = GetStringInfo();
     652         225 :     for (uint32_t i = 0; i < stringInfo.mStringCount; i++) {
     653         138 :       if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
     654          48 :           aAttribute == *stringInfo.mStringInfo[i].mName) {
     655          29 :         stringInfo.mStrings[i].SetBaseValue(aValue, this, false);
     656          29 :         foundMatch = true;
     657          29 :         break;
     658             :       }
     659             :     }
     660             :   }
     661             : 
     662         360 :   if (foundMatch) {
     663         225 :     if (NS_FAILED(rv)) {
     664           0 :       ReportAttributeParseFailure(OwnerDoc(), aAttribute, aValue);
     665           0 :       return false;
     666             :     }
     667         225 :     if (!didSetResult) {
     668          29 :       aResult.SetTo(aValue);
     669             :     }
     670         225 :     return true;
     671             :   }
     672             : 
     673         135 :   return nsSVGElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
     674         135 :                                           aResult);
     675             : }
     676             : 
     677             : void
     678           0 : nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsIAtom* aName,
     679             :                                 bool aNotify)
     680             : {
     681             :   // XXXbz there's a bunch of redundancy here with AfterSetAttr.
     682             :   // Maybe consolidate?
     683             : 
     684           0 :   if (aNamespaceID == kNameSpaceID_None) {
     685             :     // If this is an svg presentation attribute, remove declaration block to
     686             :     // force an update
     687           0 :     if (IsAttributeMapped(aName)) {
     688           0 :       mContentDeclarationBlock = nullptr;
     689             :     }
     690             : 
     691           0 :     if (IsEventAttributeName(aName)) {
     692           0 :       EventListenerManager* manager = GetExistingListenerManager();
     693           0 :       if (manager) {
     694           0 :         nsIAtom* eventName = GetEventNameForAttr(aName);
     695           0 :         manager->RemoveEventHandler(eventName, EmptyString());
     696             :       }
     697           0 :       return;
     698             :     }
     699             : 
     700             :     // Check if this is a length attribute going away
     701           0 :     LengthAttributesInfo lenInfo = GetLengthInfo();
     702             : 
     703           0 :     for (uint32_t i = 0; i < lenInfo.mLengthCount; i++) {
     704           0 :       if (aName == *lenInfo.mLengthInfo[i].mName) {
     705           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     706           0 :         lenInfo.Reset(i);
     707           0 :         return;
     708             :       }
     709             :     }
     710             : 
     711             :     // Check if this is a length list attribute going away
     712           0 :     LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
     713             : 
     714           0 :     for (uint32_t i = 0; i < lengthListInfo.mLengthListCount; i++) {
     715           0 :       if (aName == *lengthListInfo.mLengthListInfo[i].mName) {
     716           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     717           0 :         lengthListInfo.Reset(i);
     718           0 :         return;
     719             :       }
     720             :     }
     721             : 
     722             :     // Check if this is a number list attribute going away
     723           0 :     NumberListAttributesInfo numberListInfo = GetNumberListInfo();
     724             : 
     725           0 :     for (uint32_t i = 0; i < numberListInfo.mNumberListCount; i++) {
     726           0 :       if (aName == *numberListInfo.mNumberListInfo[i].mName) {
     727           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     728           0 :         numberListInfo.Reset(i);
     729           0 :         return;
     730             :       }
     731             :     }
     732             : 
     733             :     // Check if this is a point list attribute going away
     734           0 :     if (GetPointListAttrName() == aName) {
     735           0 :       SVGAnimatedPointList *pointList = GetAnimatedPointList();
     736           0 :       if (pointList) {
     737           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     738           0 :         pointList->ClearBaseValue();
     739           0 :         return;
     740             :       }
     741             :     }
     742             : 
     743             :     // Check if this is a path segment list attribute going away
     744           0 :     if (GetPathDataAttrName() == aName) {
     745           0 :       SVGAnimatedPathSegList *segList = GetAnimPathSegList();
     746           0 :       if (segList) {
     747           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     748           0 :         segList->ClearBaseValue();
     749           0 :         return;
     750             :       }
     751             :     }
     752             : 
     753             :     // Check if this is a number attribute going away
     754           0 :     NumberAttributesInfo numInfo = GetNumberInfo();
     755             : 
     756           0 :     for (uint32_t i = 0; i < numInfo.mNumberCount; i++) {
     757           0 :       if (aName == *numInfo.mNumberInfo[i].mName) {
     758           0 :         numInfo.Reset(i);
     759           0 :         return;
     760             :       }
     761             :     }
     762             : 
     763             :     // Check if this is a number pair attribute going away
     764           0 :     NumberPairAttributesInfo numPairInfo = GetNumberPairInfo();
     765             : 
     766           0 :     for (uint32_t i = 0; i < numPairInfo.mNumberPairCount; i++) {
     767           0 :       if (aName == *numPairInfo.mNumberPairInfo[i].mName) {
     768           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     769           0 :         numPairInfo.Reset(i);
     770           0 :         return;
     771             :       }
     772             :     }
     773             : 
     774             :     // Check if this is an integer attribute going away
     775           0 :     IntegerAttributesInfo intInfo = GetIntegerInfo();
     776             : 
     777           0 :     for (uint32_t i = 0; i < intInfo.mIntegerCount; i++) {
     778           0 :       if (aName == *intInfo.mIntegerInfo[i].mName) {
     779           0 :         intInfo.Reset(i);
     780           0 :         return;
     781             :       }
     782             :     }
     783             : 
     784             :     // Check if this is an integer pair attribute going away
     785           0 :     IntegerPairAttributesInfo intPairInfo = GetIntegerPairInfo();
     786             : 
     787           0 :     for (uint32_t i = 0; i < intPairInfo.mIntegerPairCount; i++) {
     788           0 :       if (aName == *intPairInfo.mIntegerPairInfo[i].mName) {
     789           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     790           0 :         intPairInfo.Reset(i);
     791           0 :         return;
     792             :       }
     793             :     }
     794             : 
     795             :     // Check if this is an angle attribute going away
     796           0 :     AngleAttributesInfo angleInfo = GetAngleInfo();
     797             : 
     798           0 :     for (uint32_t i = 0; i < angleInfo.mAngleCount; i++) {
     799           0 :       if (aName == *angleInfo.mAngleInfo[i].mName) {
     800           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     801           0 :         angleInfo.Reset(i);
     802           0 :         return;
     803             :       }
     804             :     }
     805             : 
     806             :     // Check if this is a boolean attribute going away
     807           0 :     BooleanAttributesInfo boolInfo = GetBooleanInfo();
     808             : 
     809           0 :     for (uint32_t i = 0; i < boolInfo.mBooleanCount; i++) {
     810           0 :       if (aName == *boolInfo.mBooleanInfo[i].mName) {
     811           0 :         boolInfo.Reset(i);
     812           0 :         return;
     813             :       }
     814             :     }
     815             : 
     816             :     // Check if this is an enum attribute going away
     817           0 :     EnumAttributesInfo enumInfo = GetEnumInfo();
     818             : 
     819           0 :     for (uint32_t i = 0; i < enumInfo.mEnumCount; i++) {
     820           0 :       if (aName == *enumInfo.mEnumInfo[i].mName) {
     821           0 :         enumInfo.Reset(i);
     822           0 :         return;
     823             :       }
     824             :     }
     825             : 
     826             :     // Check if this is a nsViewBox attribute going away
     827           0 :     if (aName == nsGkAtoms::viewBox) {
     828           0 :       nsSVGViewBox* viewBox = GetViewBox();
     829           0 :       if (viewBox) {
     830           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     831           0 :         viewBox->Init();
     832           0 :         return;
     833             :       }
     834             :     }
     835             : 
     836             :     // Check if this is a preserveAspectRatio attribute going away
     837           0 :     if (aName == nsGkAtoms::preserveAspectRatio) {
     838             :       SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
     839           0 :         GetPreserveAspectRatio();
     840           0 :       if (preserveAspectRatio) {
     841           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     842           0 :         preserveAspectRatio->Init();
     843           0 :         return;
     844             :       }
     845             :     }
     846             : 
     847             :     // Check if this is a transform list attribute going away
     848           0 :     if (GetTransformListAttrName() == aName) {
     849           0 :       nsSVGAnimatedTransformList *transformList = GetAnimatedTransformList();
     850           0 :       if (transformList) {
     851           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     852           0 :         transformList->ClearBaseValue();
     853           0 :         return;
     854             :       }
     855             :     }
     856             : 
     857             :     // Check for conditional processing attributes
     858           0 :     nsCOMPtr<SVGTests> tests = do_QueryObject(this);
     859           0 :     if (tests && tests->IsConditionalProcessingAttribute(aName)) {
     860           0 :       MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     861           0 :       tests->UnsetAttr(aName);
     862           0 :       return;
     863             :     }
     864             : 
     865             :     // Check if this is a string list attribute going away
     866           0 :     StringListAttributesInfo stringListInfo = GetStringListInfo();
     867             : 
     868           0 :     for (uint32_t i = 0; i < stringListInfo.mStringListCount; i++) {
     869           0 :       if (aName == *stringListInfo.mStringListInfo[i].mName) {
     870           0 :         MaybeSerializeAttrBeforeRemoval(aName, aNotify);
     871           0 :         stringListInfo.Reset(i);
     872           0 :         return;
     873             :       }
     874             :     }
     875             : 
     876           0 :     if (aName == nsGkAtoms::_class) {
     877           0 :       mClassAttribute.Init();
     878           0 :       return;
     879             :     }
     880             :   }
     881             : 
     882             :   // Check if this is a string attribute going away
     883           0 :   StringAttributesInfo stringInfo = GetStringInfo();
     884             : 
     885           0 :   for (uint32_t i = 0; i < stringInfo.mStringCount; i++) {
     886           0 :     if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
     887           0 :         aName == *stringInfo.mStringInfo[i].mName) {
     888           0 :       stringInfo.Reset(i);
     889           0 :       return;
     890             :     }
     891             :   }
     892             : }
     893             : 
     894             : nsresult
     895           0 : nsSVGElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName,
     896             :                         bool aNotify)
     897             : {
     898           0 :   UnsetAttrInternal(aNamespaceID, aName, aNotify);
     899           0 :   return nsSVGElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
     900             : }
     901             : 
     902             : nsChangeHint
     903           0 : nsSVGElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
     904             :                                      int32_t aModType) const
     905             : {
     906             :   nsChangeHint retval =
     907           0 :     nsSVGElementBase::GetAttributeChangeHint(aAttribute, aModType);
     908             : 
     909           0 :   nsCOMPtr<SVGTests> tests = do_QueryObject(const_cast<nsSVGElement*>(this));
     910           0 :   if (tests && tests->IsConditionalProcessingAttribute(aAttribute)) {
     911             :     // It would be nice to only reconstruct the frame if the value returned by
     912             :     // SVGTests::PassesConditionalProcessingTests has changed, but we don't
     913             :     // know that
     914           0 :     retval |= nsChangeHint_ReconstructFrame;
     915             :   }
     916           0 :   return retval;
     917             : }
     918             : 
     919             : bool
     920        5510 : nsSVGElement::IsNodeOfType(uint32_t aFlags) const
     921             : {
     922        5510 :   return !(aFlags & ~eCONTENT);
     923             : }
     924             : 
     925             : void
     926           0 : nsSVGElement::NodeInfoChanged(nsIDocument* aOldDoc)
     927             : {
     928           0 :   nsSVGElementBase::NodeInfoChanged(aOldDoc);
     929           0 :   aOldDoc->UnscheduleSVGForPresAttrEvaluation(this);
     930           0 :   mContentDeclarationBlock = nullptr;
     931           0 :   OwnerDoc()->ScheduleSVGForPresAttrEvaluation(this);
     932           0 : }
     933             : 
     934             : NS_IMETHODIMP
     935         331 : nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
     936             : {
     937             : #ifdef DEBUG
     938             : //  printf("nsSVGElement(%p)::WalkContentStyleRules()\n", this);
     939             : #endif
     940         331 :   if (!mContentDeclarationBlock) {
     941         245 :     UpdateContentDeclarationBlock(StyleBackendType::Gecko);
     942             :   }
     943             : 
     944         331 :   if (mContentDeclarationBlock) {
     945         150 :     css::Declaration* declaration = mContentDeclarationBlock->AsGecko();
     946         150 :     declaration->SetImmutable();
     947         150 :     aRuleWalker->Forward(declaration);
     948             :   }
     949             : 
     950         331 :   return NS_OK;
     951             : }
     952             : 
     953             : NS_IMETHODIMP_(bool)
     954         832 : nsSVGElement::IsAttributeMapped(const nsIAtom* name) const
     955             : {
     956         832 :   if (name == nsGkAtoms::lang) {
     957           0 :     return true;
     958             :   }
     959         832 :   return nsSVGElementBase::IsAttributeMapped(name);
     960             : }
     961             : 
     962             : // PresentationAttributes-FillStroke
     963             : /* static */ const Element::MappedAttributeEntry
     964             : nsSVGElement::sFillStrokeMap[] = {
     965             :   { &nsGkAtoms::fill },
     966             :   { &nsGkAtoms::fill_opacity },
     967             :   { &nsGkAtoms::fill_rule },
     968             :   { &nsGkAtoms::paint_order },
     969             :   { &nsGkAtoms::stroke },
     970             :   { &nsGkAtoms::stroke_dasharray },
     971             :   { &nsGkAtoms::stroke_dashoffset },
     972             :   { &nsGkAtoms::stroke_linecap },
     973             :   { &nsGkAtoms::stroke_linejoin },
     974             :   { &nsGkAtoms::stroke_miterlimit },
     975             :   { &nsGkAtoms::stroke_opacity },
     976             :   { &nsGkAtoms::stroke_width },
     977             :   { &nsGkAtoms::vector_effect },
     978             :   { nullptr }
     979             : };
     980             : 
     981             : // PresentationAttributes-Graphics
     982             : /* static */ const Element::MappedAttributeEntry
     983             : nsSVGElement::sGraphicsMap[] = {
     984             :   { &nsGkAtoms::clip_path },
     985             :   { &nsGkAtoms::clip_rule },
     986             :   { &nsGkAtoms::colorInterpolation },
     987             :   { &nsGkAtoms::cursor },
     988             :   { &nsGkAtoms::display },
     989             :   { &nsGkAtoms::filter },
     990             :   { &nsGkAtoms::image_rendering },
     991             :   { &nsGkAtoms::mask },
     992             :   { &nsGkAtoms::opacity },
     993             :   { &nsGkAtoms::pointer_events },
     994             :   { &nsGkAtoms::shape_rendering },
     995             :   { &nsGkAtoms::text_rendering },
     996             :   { &nsGkAtoms::visibility },
     997             :   { nullptr }
     998             : };
     999             : 
    1000             : // PresentationAttributes-TextContentElements
    1001             : /* static */ const Element::MappedAttributeEntry
    1002             : nsSVGElement::sTextContentElementsMap[] = {
    1003             :   // Properties that we don't support are commented out.
    1004             :   // { &nsGkAtoms::alignment_baseline },
    1005             :   // { &nsGkAtoms::baseline_shift },
    1006             :   { &nsGkAtoms::direction },
    1007             :   { &nsGkAtoms::dominant_baseline },
    1008             :   { &nsGkAtoms::letter_spacing },
    1009             :   { &nsGkAtoms::text_anchor },
    1010             :   { &nsGkAtoms::text_decoration },
    1011             :   { &nsGkAtoms::unicode_bidi },
    1012             :   { &nsGkAtoms::word_spacing },
    1013             :   { &nsGkAtoms::writing_mode },
    1014             :   { nullptr }
    1015             : };
    1016             : 
    1017             : // PresentationAttributes-FontSpecification
    1018             : /* static */ const Element::MappedAttributeEntry
    1019             : nsSVGElement::sFontSpecificationMap[] = {
    1020             :   { &nsGkAtoms::font_family },
    1021             :   { &nsGkAtoms::font_size },
    1022             :   { &nsGkAtoms::font_size_adjust },
    1023             :   { &nsGkAtoms::font_stretch },
    1024             :   { &nsGkAtoms::font_style },
    1025             :   { &nsGkAtoms::font_variant },
    1026             :   { &nsGkAtoms::fontWeight },
    1027             :   { nullptr }
    1028             : };
    1029             : 
    1030             : // PresentationAttributes-GradientStop
    1031             : /* static */ const Element::MappedAttributeEntry
    1032             : nsSVGElement::sGradientStopMap[] = {
    1033             :   { &nsGkAtoms::stop_color },
    1034             :   { &nsGkAtoms::stop_opacity },
    1035             :   { nullptr }
    1036             : };
    1037             : 
    1038             : // PresentationAttributes-Viewports
    1039             : /* static */ const Element::MappedAttributeEntry
    1040             : nsSVGElement::sViewportsMap[] = {
    1041             :   { &nsGkAtoms::overflow },
    1042             :   { &nsGkAtoms::clip },
    1043             :   { nullptr }
    1044             : };
    1045             : 
    1046             : // PresentationAttributes-Makers
    1047             : /* static */ const Element::MappedAttributeEntry
    1048             : nsSVGElement::sMarkersMap[] = {
    1049             :   { &nsGkAtoms::marker_end },
    1050             :   { &nsGkAtoms::marker_mid },
    1051             :   { &nsGkAtoms::marker_start },
    1052             :   { nullptr }
    1053             : };
    1054             : 
    1055             : // PresentationAttributes-Color
    1056             : /* static */ const Element::MappedAttributeEntry
    1057             : nsSVGElement::sColorMap[] = {
    1058             :   { &nsGkAtoms::color },
    1059             :   { nullptr }
    1060             : };
    1061             : 
    1062             : // PresentationAttributes-Filters
    1063             : /* static */ const Element::MappedAttributeEntry
    1064             : nsSVGElement::sFiltersMap[] = {
    1065             :   { &nsGkAtoms::colorInterpolationFilters },
    1066             :   { nullptr }
    1067             : };
    1068             : 
    1069             : // PresentationAttributes-feFlood
    1070             : /* static */ const Element::MappedAttributeEntry
    1071             : nsSVGElement::sFEFloodMap[] = {
    1072             :   { &nsGkAtoms::flood_color },
    1073             :   { &nsGkAtoms::flood_opacity },
    1074             :   { nullptr }
    1075             : };
    1076             : 
    1077             : // PresentationAttributes-LightingEffects
    1078             : /* static */ const Element::MappedAttributeEntry
    1079             : nsSVGElement::sLightingEffectsMap[] = {
    1080             :   { &nsGkAtoms::lighting_color },
    1081             :   { nullptr }
    1082             : };
    1083             : 
    1084             : // PresentationAttributes-mask
    1085             : /* static */ const Element::MappedAttributeEntry
    1086             : nsSVGElement::sMaskMap[] = {
    1087             :   { &nsGkAtoms::mask_type },
    1088             :   { nullptr }
    1089             : };
    1090             : 
    1091             : //----------------------------------------------------------------------
    1092             : // nsIDOMElement methods
    1093             : 
    1094             : // forwarded to Element implementations
    1095             : 
    1096             : 
    1097             : //----------------------------------------------------------------------
    1098             : // nsIDOMSVGElement methods
    1099             : 
    1100             : NS_IMETHODIMP
    1101           0 : nsSVGElement::GetOwnerSVGElement(nsIDOMSVGElement * *aOwnerSVGElement)
    1102             : {
    1103           0 :   NS_IF_ADDREF(*aOwnerSVGElement = GetOwnerSVGElement());
    1104           0 :   return NS_OK;
    1105             : }
    1106             : 
    1107             : SVGSVGElement*
    1108           0 : nsSVGElement::GetOwnerSVGElement()
    1109             : {
    1110           0 :   return GetCtx(); // this may return nullptr
    1111             : }
    1112             : 
    1113             : NS_IMETHODIMP
    1114           0 : nsSVGElement::GetViewportElement(nsIDOMSVGElement * *aViewportElement)
    1115             : {
    1116           0 :   nsSVGElement* elem = GetViewportElement();
    1117           0 :   NS_ADDREF(*aViewportElement = elem);
    1118           0 :   return NS_OK;
    1119             : }
    1120             : 
    1121             : nsSVGElement*
    1122           0 : nsSVGElement::GetViewportElement()
    1123             : {
    1124           0 :   return SVGContentUtils::GetNearestViewportElement(this);
    1125             : }
    1126             : 
    1127             : already_AddRefed<SVGAnimatedString>
    1128           0 : nsSVGElement::ClassName()
    1129             : {
    1130           0 :   return mClassAttribute.ToDOMAnimatedString(this);
    1131             : }
    1132             : 
    1133             : bool
    1134           0 : nsSVGElement::IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex)
    1135             : {
    1136           0 :   nsIDocument* doc = GetComposedDoc();
    1137           0 :   if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
    1138             :     // In designMode documents we only allow focusing the document.
    1139           0 :     if (aTabIndex) {
    1140           0 :       *aTabIndex = -1;
    1141             :     }
    1142             : 
    1143           0 :     *aIsFocusable = false;
    1144             : 
    1145           0 :     return true;
    1146             :   }
    1147             : 
    1148           0 :   int32_t tabIndex = TabIndex();
    1149             : 
    1150           0 :   if (aTabIndex) {
    1151           0 :     *aTabIndex = tabIndex;
    1152             :   }
    1153             : 
    1154             :   // If a tabindex is specified at all, or the default tabindex is 0, we're focusable
    1155           0 :   *aIsFocusable =
    1156           0 :     tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex);
    1157             : 
    1158           0 :   return false;
    1159             : }
    1160             : 
    1161             : bool
    1162           0 : nsSVGElement::IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse)
    1163             : {
    1164           0 :   bool isFocusable = false;
    1165           0 :   IsSVGFocusable(&isFocusable, aTabIndex);
    1166           0 :   return isFocusable;
    1167             : }
    1168             : 
    1169             : //------------------------------------------------------------------------
    1170             : // Helper class: MappedAttrParser, for parsing values of mapped attributes
    1171             : 
    1172             : namespace {
    1173             : 
    1174             : class MOZ_STACK_CLASS MappedAttrParser {
    1175             : public:
    1176             :   MappedAttrParser(css::Loader* aLoader,
    1177             :                    nsIURI* aDocURI,
    1178             :                    already_AddRefed<nsIURI> aBaseURI,
    1179             :                    nsSVGElement* aElement,
    1180             :                    StyleBackendType aBackend);
    1181             :   ~MappedAttrParser();
    1182             : 
    1183             :   // Parses a mapped attribute value.
    1184             :   void ParseMappedAttrValue(nsIAtom* aMappedAttrName,
    1185             :                             const nsAString& aMappedAttrValue);
    1186             : 
    1187             :   // If we've parsed any values for mapped attributes, this method returns the
    1188             :   // already_AddRefed css::Declaration that incorporates the parsed
    1189             :   // values. Otherwise, this method returns null.
    1190             :   already_AddRefed<DeclarationBlock> GetDeclarationBlock();
    1191             : 
    1192             : private:
    1193             :   // MEMBER DATA
    1194             :   // -----------
    1195             :   nsCSSParser       mParser;
    1196             :   css::Loader*      mLoader;
    1197             : 
    1198             :   // Arguments for nsCSSParser::ParseProperty
    1199             :   nsIURI*           mDocURI;
    1200             :   nsCOMPtr<nsIURI>  mBaseURI;
    1201             : 
    1202             :   // Declaration for storing parsed values (lazily initialized)
    1203             :   RefPtr<DeclarationBlock> mDecl;
    1204             : 
    1205             :   // For reporting use counters
    1206             :   nsSVGElement*     mElement;
    1207             : 
    1208             :   StyleBackendType mBackend;
    1209             : };
    1210             : 
    1211         225 : MappedAttrParser::MappedAttrParser(css::Loader* aLoader,
    1212             :                                    nsIURI* aDocURI,
    1213             :                                    already_AddRefed<nsIURI> aBaseURI,
    1214             :                                    nsSVGElement* aElement,
    1215         225 :                                    StyleBackendType aBackend)
    1216             :   : mParser(aLoader), mLoader(aLoader), mDocURI(aDocURI), mBaseURI(aBaseURI),
    1217         225 :     mElement(aElement), mBackend(aBackend)
    1218             : {
    1219         225 : }
    1220             : 
    1221         450 : MappedAttrParser::~MappedAttrParser()
    1222             : {
    1223         225 :   MOZ_ASSERT(!mDecl,
    1224             :              "If mDecl was initialized, it should have been returned via "
    1225             :              "GetDeclarationBlock (and had its pointer cleared)");
    1226         225 : }
    1227             : 
    1228             : void
    1229          95 : MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
    1230             :                                        const nsAString& aMappedAttrValue)
    1231             : {
    1232          95 :   if (!mDecl) {
    1233          64 :     if (mBackend == StyleBackendType::Gecko) {
    1234          64 :       mDecl = new css::Declaration();
    1235          64 :       mDecl->AsGecko()->InitializeEmpty();
    1236             :     } else {
    1237           0 :       mDecl = new ServoDeclarationBlock();
    1238             :     }
    1239             :   }
    1240             : 
    1241             :   // Get the nsCSSPropertyID ID for our mapped attribute.
    1242             :   nsCSSPropertyID propertyID =
    1243         190 :     nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
    1244          95 :                                CSSEnabledState::eForAllContent);
    1245          95 :   if (propertyID != eCSSProperty_UNKNOWN) {
    1246          95 :     bool changed = false; // outparam for ParseProperty.
    1247          95 :     if (mBackend == StyleBackendType::Gecko) {
    1248         190 :       mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
    1249         190 :                             mElement->NodePrincipal(), mDecl->AsGecko(), &changed, false, true);
    1250             :     } else {
    1251           0 :       NS_ConvertUTF16toUTF8 value(aMappedAttrValue);
    1252             :       // FIXME (bug 1343964): Figure out a better solution for sending the base uri to servo
    1253             :       RefPtr<URLExtraData> data = new URLExtraData(mBaseURI, mDocURI,
    1254           0 :                                                    mElement->NodePrincipal());
    1255           0 :       changed = Servo_DeclarationBlock_SetPropertyById(
    1256           0 :         mDecl->AsServo()->Raw(), propertyID, &value, false, data,
    1257           0 :         ParsingMode::AllowUnitlessLength, mElement->OwnerDoc()->GetCompatibilityMode(), mLoader);
    1258             :     }
    1259             : 
    1260          95 :     if (changed) {
    1261             :       // The normal reporting of use counters by the nsCSSParser won't happen
    1262             :       // since it doesn't have a sheet.
    1263          95 :       if (nsCSSProps::IsShorthand(propertyID)) {
    1264          10 :         CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, propertyID,
    1265             :                                              CSSEnabledState::eForAllContent) {
    1266           9 :           UseCounter useCounter = nsCSSProps::UseCounterFor(*subprop);
    1267           9 :           if (useCounter != eUseCounter_UNKNOWN) {
    1268           0 :             mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
    1269             :           }
    1270             :         }
    1271             :       } else {
    1272          94 :         UseCounter useCounter = nsCSSProps::UseCounterFor(propertyID);
    1273          94 :         if (useCounter != eUseCounter_UNKNOWN) {
    1274          44 :           mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
    1275             :         }
    1276             :       }
    1277             :     }
    1278          95 :     return;
    1279             :   }
    1280           0 :   MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
    1281             :              "Only 'lang' should be unrecognized!");
    1282             :   // nsCSSParser doesn't know about 'lang', so we need to handle it specially.
    1283           0 :   if (aMappedAttrName == nsGkAtoms::lang) {
    1284           0 :     propertyID = eCSSProperty__x_lang;
    1285           0 :     if (mBackend == StyleBackendType::Gecko) {
    1286           0 :       nsCSSExpandedDataBlock block;
    1287           0 :       mDecl->AsGecko()->ExpandTo(&block);
    1288           0 :       nsCSSValue cssValue(PromiseFlatString(aMappedAttrValue), eCSSUnit_Ident);
    1289           0 :       block.AddLonghandProperty(propertyID, cssValue);
    1290           0 :       mDecl->AsGecko()->ValueAppended(propertyID);
    1291           0 :       mDecl->AsGecko()->CompressFrom(&block);
    1292             :     } else {
    1293           0 :       nsCOMPtr<nsIAtom> atom = NS_Atomize(aMappedAttrValue);
    1294           0 :       Servo_DeclarationBlock_SetIdentStringValue(mDecl->AsServo()->Raw(), propertyID, atom);
    1295             :     }
    1296             :   }
    1297             : }
    1298             : 
    1299             : already_AddRefed<DeclarationBlock>
    1300         225 : MappedAttrParser::GetDeclarationBlock()
    1301             : {
    1302         225 :   return mDecl.forget();
    1303             : }
    1304             : 
    1305             : } // namespace
    1306             : 
    1307             : //----------------------------------------------------------------------
    1308             : // Implementation Helpers:
    1309             : 
    1310             : void
    1311         245 : nsSVGElement::UpdateContentDeclarationBlock(mozilla::StyleBackendType aBackend)
    1312             : {
    1313         245 :   NS_ASSERTION(!mContentDeclarationBlock,
    1314             :                "we already have a content declaration block");
    1315             : 
    1316         245 :   uint32_t attrCount = mAttrsAndChildren.AttrCount();
    1317         245 :   if (!attrCount) {
    1318             :     // nothing to do
    1319          20 :     return;
    1320             :   }
    1321             : 
    1322         225 :   nsIDocument* doc = OwnerDoc();
    1323             :   MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
    1324         450 :                                     GetBaseURI(), this, aBackend);
    1325             : 
    1326         757 :   for (uint32_t i = 0; i < attrCount; ++i) {
    1327         532 :     const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
    1328         532 :     if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
    1329         874 :       continue;
    1330             : 
    1331          95 :     if (attrName->NamespaceID() != kNameSpaceID_None &&
    1332           0 :         !attrName->Equals(nsGkAtoms::lang, kNameSpaceID_XML)) {
    1333           0 :       continue;
    1334             :     }
    1335             : 
    1336          95 :     if (attrName->Equals(nsGkAtoms::lang, kNameSpaceID_None) &&
    1337           0 :         HasAttr(kNameSpaceID_XML, nsGkAtoms::lang)) {
    1338           0 :       continue; // xml:lang has precedence
    1339             :     }
    1340             : 
    1341          95 :     if (IsSVGElement(nsGkAtoms::svg)) {
    1342             :       // Special case: we don't want <svg> 'width'/'height' mapped into style
    1343             :       // if the attribute value isn't a valid <length> according to SVG (which
    1344             :       // only supports a subset of the CSS <length> values). We don't enforce
    1345             :       // this by checking the attribute value in SVGSVGElement::
    1346             :       // IsAttributeMapped since we don't want that method to depend on the
    1347             :       // value of the attribute that is being checked. Rather we just prevent
    1348             :       // the actual mapping here, as necessary.
    1349          62 :       if (attrName->Atom() == nsGkAtoms::width &&
    1350          20 :           !GetAnimatedLength(nsGkAtoms::width)->HasBaseVal()) {
    1351           0 :         continue;
    1352             :       }
    1353          63 :       if (attrName->Atom() == nsGkAtoms::height &&
    1354          21 :           !GetAnimatedLength(nsGkAtoms::height)->HasBaseVal()) {
    1355           0 :         continue;
    1356             :       }
    1357             :     }
    1358             : 
    1359         190 :     nsAutoString value;
    1360          95 :     mAttrsAndChildren.AttrAt(i)->ToString(value);
    1361          95 :     mappedAttrParser.ParseMappedAttrValue(attrName->Atom(), value);
    1362             :   }
    1363         225 :   mContentDeclarationBlock = mappedAttrParser.GetDeclarationBlock();
    1364             : }
    1365             : 
    1366             : const DeclarationBlock*
    1367           0 : nsSVGElement::GetContentDeclarationBlock() const
    1368             : {
    1369           0 :   return mContentDeclarationBlock;
    1370             : }
    1371             : 
    1372             : /**
    1373             :  * Helper methods for the type-specific WillChangeXXX methods.
    1374             :  *
    1375             :  * This method sends out appropriate pre-change notifications so that selector
    1376             :  * restyles (e.g. due to changes that cause |elem[attr="val"]| to start/stop
    1377             :  * matching) work, and it returns an nsAttrValue that _may_ contain the
    1378             :  * attribute's pre-change value.
    1379             :  *
    1380             :  * The nsAttrValue returned by this method depends on whether there are
    1381             :  * mutation event listeners listening for changes to this element's attributes.
    1382             :  * If not, then the object returned is empty. If there are, then the
    1383             :  * nsAttrValue returned contains a serialized copy of the attribute's value
    1384             :  * prior to the change, and this object should be passed to the corresponding
    1385             :  * DidChangeXXX method call (assuming a WillChangeXXX call is required for the
    1386             :  * SVG type - see comment below). This is necessary so that the 'prevValue'
    1387             :  * property of the mutation event that is dispatched will correctly contain the
    1388             :  * old value.
    1389             :  *
    1390             :  * The reason we need to serialize the old value if there are mutation
    1391             :  * event listeners is because the underlying nsAttrValue for the attribute
    1392             :  * points directly to a parsed representation of the attribute (e.g. an
    1393             :  * SVGAnimatedLengthList*) that is a member of the SVG element. That object
    1394             :  * will have changed by the time DidChangeXXX has been called, so without the
    1395             :  * serialization of the old attribute value that we provide, DidChangeXXX
    1396             :  * would have no way to get the old value to pass to SetAttrAndNotify.
    1397             :  *
    1398             :  * We only return the old value when there are mutation event listeners because
    1399             :  * it's not needed otherwise, and because it's expensive to serialize the old
    1400             :  * value. This is especially true for list type attributes, which may be built
    1401             :  * up via the SVG DOM resulting in a large number of Will/DidModifyXXX calls
    1402             :  * before the script finally finishes setting the attribute.
    1403             :  *
    1404             :  * Note that unlike using SetParsedAttr, using Will/DidChangeXXX does NOT check
    1405             :  * and filter out redundant changes. Before calling WillChangeXXX, the caller
    1406             :  * should check whether the new and old values are actually the same, and skip
    1407             :  * calling Will/DidChangeXXX if they are.
    1408             :  *
    1409             :  * Also note that not all SVG types use this scheme. For types that can be
    1410             :  * represented by an nsAttrValue without pointing back to an SVG object (e.g.
    1411             :  * enums, booleans, integers) we can simply use SetParsedAttr which will do all
    1412             :  * of the above for us. For such types there is no matching WillChangeXXX
    1413             :  * method, only DidChangeXXX which calls SetParsedAttr.
    1414             :  */
    1415             : nsAttrValue
    1416           0 : nsSVGElement::WillChangeValue(nsIAtom* aName)
    1417             : {
    1418             :   // We need an empty attr value:
    1419             :   //   a) to pass to BeforeSetAttr when GetParsedAttr returns nullptr
    1420             :   //   b) to store the old value in the case we have mutation listeners
    1421             :   //
    1422             :   // We can use the same value for both purposes, because if GetParsedAttr
    1423             :   // returns non-null its return value is what will get passed to BeforeSetAttr,
    1424             :   // not matter what our mutation listener situation is.
    1425             :   //
    1426             :   // Also, we should be careful to always return this value to benefit from
    1427             :   // return value optimization.
    1428           0 :   nsAttrValue emptyOrOldAttrValue;
    1429           0 :   const nsAttrValue* attrValue = GetParsedAttr(aName);
    1430             : 
    1431             :   // We only need to set the old value if we have listeners since otherwise it
    1432             :   // isn't used.
    1433           0 :   if (attrValue &&
    1434           0 :       nsContentUtils::HasMutationListeners(this,
    1435             :                                            NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    1436             :                                            this)) {
    1437           0 :     emptyOrOldAttrValue.SetToSerialized(*attrValue);
    1438             :   }
    1439             : 
    1440             :   uint8_t modType = attrValue
    1441           0 :                   ? static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION)
    1442           0 :                   : static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
    1443           0 :   nsNodeUtils::AttributeWillChange(this, kNameSpaceID_None, aName, modType,
    1444           0 :                                    nullptr);
    1445             : 
    1446             :   // This is not strictly correct--the attribute value parameter for
    1447             :   // BeforeSetAttr should reflect the value that *will* be set but that implies
    1448             :   // allocating, e.g. an extra nsSVGLength2, and isn't necessary at the moment
    1449             :   // since no SVG elements overload BeforeSetAttr. For now we just pass the
    1450             :   // current value.
    1451             :   nsAttrValueOrString attrStringOrValue(attrValue ? *attrValue
    1452           0 :                                                   : emptyOrOldAttrValue);
    1453             :   DebugOnly<nsresult> rv =
    1454           0 :     BeforeSetAttr(kNameSpaceID_None, aName, &attrStringOrValue,
    1455           0 :                   kNotifyDocumentObservers);
    1456             :   // SVG elements aren't expected to overload BeforeSetAttr in such a way that
    1457             :   // it may fail. So long as this is the case we don't need to check and pass on
    1458             :   // the return value which simplifies the calling code significantly.
    1459           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv), "Unexpected failure from BeforeSetAttr");
    1460             : 
    1461           0 :   return emptyOrOldAttrValue;
    1462             : }
    1463             : 
    1464             : /**
    1465             :  * Helper methods for the type-specific DidChangeXXX methods.
    1466             :  *
    1467             :  * aEmptyOrOldValue will normally be the object returned from the corresponding
    1468             :  * WillChangeXXX call. This is because:
    1469             :  * a) WillChangeXXX will ensure the object is set when we have mutation
    1470             :  *    listeners, and
    1471             :  * b) WillChangeXXX will ensure the object represents a serialized version of
    1472             :  *    the old attribute value so that the value doesn't change when the
    1473             :  *    underlying SVG type is updated.
    1474             :  *
    1475             :  * aNewValue is replaced with the old value.
    1476             :  */
    1477             : void
    1478           0 : nsSVGElement::DidChangeValue(nsIAtom* aName,
    1479             :                              const nsAttrValue& aEmptyOrOldValue,
    1480             :                              nsAttrValue& aNewValue)
    1481             : {
    1482             :   bool hasListeners =
    1483           0 :     nsContentUtils::HasMutationListeners(this,
    1484             :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    1485           0 :                                          this);
    1486           0 :   uint8_t modType = HasAttr(kNameSpaceID_None, aName)
    1487           0 :                   ? static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION)
    1488           0 :                   : static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
    1489             : 
    1490           0 :   nsIDocument* document = GetComposedDoc();
    1491             :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
    1492           0 :                                kNotifyDocumentObservers);
    1493             :   // XXX Really, the fourth argument to SetAttrAndNotify should be null if
    1494             :   // aEmptyOrOldValue does not represent the actual previous value of the
    1495             :   // attribute, but currently SVG elements do not even use the old attribute
    1496             :   // value in |AfterSetAttr|, so this should be ok.
    1497           0 :   SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, &aEmptyOrOldValue,
    1498             :                    aNewValue, modType, hasListeners, kNotifyDocumentObservers,
    1499           0 :                    kCallAfterSetAttr, document, updateBatch);
    1500           0 : }
    1501             : 
    1502             : void
    1503           0 : nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
    1504             : {
    1505           0 :   if (!aNotify ||
    1506           0 :       !nsContentUtils::HasMutationListeners(this,
    1507             :                                             NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    1508             :                                             this)) {
    1509           0 :     return;
    1510             :   }
    1511             : 
    1512           0 :   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(aName);
    1513           0 :   if (!attrValue)
    1514           0 :     return;
    1515             : 
    1516           0 :   nsAutoString serializedValue;
    1517           0 :   attrValue->ToString(serializedValue);
    1518           0 :   nsAttrValue oldAttrValue(serializedValue);
    1519             :   bool oldValueSet;
    1520           0 :   mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue, &oldValueSet);
    1521             : }
    1522             : 
    1523             : /* static */
    1524           0 : nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr)
    1525             : {
    1526           0 :   if (aAttr == nsGkAtoms::onload)
    1527           0 :     return nsGkAtoms::onSVGLoad;
    1528           0 :   if (aAttr == nsGkAtoms::onunload)
    1529           0 :     return nsGkAtoms::onSVGUnload;
    1530           0 :   if (aAttr == nsGkAtoms::onresize)
    1531           0 :     return nsGkAtoms::onSVGResize;
    1532           0 :   if (aAttr == nsGkAtoms::onscroll)
    1533           0 :     return nsGkAtoms::onSVGScroll;
    1534           0 :   if (aAttr == nsGkAtoms::onzoom)
    1535           0 :     return nsGkAtoms::onSVGZoom;
    1536           0 :   if (aAttr == nsGkAtoms::onbegin)
    1537           0 :     return nsGkAtoms::onbeginEvent;
    1538           0 :   if (aAttr == nsGkAtoms::onrepeat)
    1539           0 :     return nsGkAtoms::onrepeatEvent;
    1540           0 :   if (aAttr == nsGkAtoms::onend)
    1541           0 :     return nsGkAtoms::onendEvent;
    1542             : 
    1543           0 :   return aAttr;
    1544             : }
    1545             : 
    1546             : SVGSVGElement *
    1547         144 : nsSVGElement::GetCtx() const
    1548             : {
    1549         144 :   nsIContent* ancestor = GetFlattenedTreeParent();
    1550             : 
    1551         168 :   while (ancestor && ancestor->IsSVGElement()) {
    1552          54 :     if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
    1553           0 :       return nullptr;
    1554             :     }
    1555          54 :     if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
    1556          42 :       return static_cast<SVGSVGElement*>(ancestor);
    1557             :     }
    1558          12 :     ancestor = ancestor->GetFlattenedTreeParent();
    1559             :   }
    1560             : 
    1561             :   // we don't have an ancestor <svg> element...
    1562         102 :   return nullptr;
    1563             : }
    1564             : 
    1565             : /* virtual */ gfxMatrix
    1566           0 : nsSVGElement::PrependLocalTransformsTo(
    1567             :   const gfxMatrix &aMatrix, SVGTransformTypes aWhich) const
    1568             : {
    1569           0 :   return aMatrix;
    1570             : }
    1571             : 
    1572             : nsSVGElement::LengthAttributesInfo
    1573         235 : nsSVGElement::GetLengthInfo()
    1574             : {
    1575         235 :   return LengthAttributesInfo(nullptr, nullptr, 0);
    1576             : }
    1577             : 
    1578         300 : void nsSVGElement::LengthAttributesInfo::Reset(uint8_t aAttrEnum)
    1579             : {
    1580         600 :   mLengths[aAttrEnum].Init(mLengthInfo[aAttrEnum].mCtxType,
    1581             :                            aAttrEnum,
    1582         300 :                            mLengthInfo[aAttrEnum].mDefaultValue,
    1583         600 :                            mLengthInfo[aAttrEnum].mDefaultUnitType);
    1584         300 : }
    1585             : 
    1586             : void
    1587           0 : nsSVGElement::SetLength(nsIAtom* aName, const nsSVGLength2 &aLength)
    1588             : {
    1589           0 :   LengthAttributesInfo lengthInfo = GetLengthInfo();
    1590             : 
    1591           0 :   for (uint32_t i = 0; i < lengthInfo.mLengthCount; i++) {
    1592           0 :     if (aName == *lengthInfo.mLengthInfo[i].mName) {
    1593           0 :       lengthInfo.mLengths[i] = aLength;
    1594           0 :       DidAnimateLength(i);
    1595           0 :       return;
    1596             :     }
    1597             :   }
    1598           0 :   MOZ_ASSERT(false, "no length found to set");
    1599             : }
    1600             : 
    1601             : nsAttrValue
    1602           0 : nsSVGElement::WillChangeLength(uint8_t aAttrEnum)
    1603             : {
    1604           0 :   return WillChangeValue(*GetLengthInfo().mLengthInfo[aAttrEnum].mName);
    1605             : }
    1606             : 
    1607             : void
    1608           0 : nsSVGElement::DidChangeLength(uint8_t aAttrEnum,
    1609             :                               const nsAttrValue& aEmptyOrOldValue)
    1610             : {
    1611           0 :   LengthAttributesInfo info = GetLengthInfo();
    1612             : 
    1613           0 :   NS_ASSERTION(info.mLengthCount > 0,
    1614             :                "DidChangeLength on element with no length attribs");
    1615           0 :   NS_ASSERTION(aAttrEnum < info.mLengthCount, "aAttrEnum out of range");
    1616             : 
    1617           0 :   nsAttrValue newValue;
    1618           0 :   newValue.SetTo(info.mLengths[aAttrEnum], nullptr);
    1619             : 
    1620           0 :   DidChangeValue(*info.mLengthInfo[aAttrEnum].mName, aEmptyOrOldValue,
    1621           0 :                  newValue);
    1622           0 : }
    1623             : 
    1624             : void
    1625           0 : nsSVGElement::DidAnimateLength(uint8_t aAttrEnum)
    1626             : {
    1627           0 :   ClearAnyCachedPath();
    1628             : 
    1629           0 :   nsIFrame* frame = GetPrimaryFrame();
    1630             : 
    1631           0 :   if (frame) {
    1632           0 :     LengthAttributesInfo info = GetLengthInfo();
    1633           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1634           0 :                             *info.mLengthInfo[aAttrEnum].mName,
    1635           0 :                             nsIDOMMutationEvent::SMIL);
    1636             :   }
    1637           0 : }
    1638             : 
    1639             : nsSVGLength2*
    1640          41 : nsSVGElement::GetAnimatedLength(const nsIAtom *aAttrName)
    1641             : {
    1642          41 :   LengthAttributesInfo lengthInfo = GetLengthInfo();
    1643             : 
    1644         144 :   for (uint32_t i = 0; i < lengthInfo.mLengthCount; i++) {
    1645         144 :     if (aAttrName == *lengthInfo.mLengthInfo[i].mName) {
    1646          41 :       return &lengthInfo.mLengths[i];
    1647             :     }
    1648             :   }
    1649           0 :   MOZ_ASSERT(false, "no matching length found");
    1650             :   return nullptr;
    1651             : }
    1652             : 
    1653             : void
    1654          73 : nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...)
    1655             : {
    1656          73 :   LengthAttributesInfo info = GetLengthInfo();
    1657             : 
    1658          73 :   NS_ASSERTION(info.mLengthCount > 0,
    1659             :                "GetAnimatedLengthValues on element with no length attribs");
    1660             : 
    1661          73 :   SVGSVGElement *ctx = nullptr;
    1662             : 
    1663          73 :   float *f = aFirst;
    1664          73 :   uint32_t i = 0;
    1665             : 
    1666             :   va_list args;
    1667          73 :   va_start(args, aFirst);
    1668             : 
    1669         617 :   while (f && i < info.mLengthCount) {
    1670         272 :     uint8_t type = info.mLengths[i].GetSpecifiedUnitType();
    1671         272 :     if (!ctx) {
    1672         272 :       if (type != nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER &&
    1673             :           type != nsIDOMSVGLength::SVG_LENGTHTYPE_PX)
    1674           0 :         ctx = GetCtx();
    1675             :     }
    1676         272 :     if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS ||
    1677             :         type == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS)
    1678           0 :       *f = info.mLengths[i++].GetAnimValue(this);
    1679             :     else
    1680         272 :       *f = info.mLengths[i++].GetAnimValue(ctx);
    1681         272 :     f = va_arg(args, float*);
    1682             :   }
    1683             : 
    1684          73 :   va_end(args);
    1685          73 : }
    1686             : 
    1687             : nsSVGElement::LengthListAttributesInfo
    1688         357 : nsSVGElement::GetLengthListInfo()
    1689             : {
    1690         357 :   return LengthListAttributesInfo(nullptr, nullptr, 0);
    1691             : }
    1692             : 
    1693             : void
    1694           0 : nsSVGElement::LengthListAttributesInfo::Reset(uint8_t aAttrEnum)
    1695             : {
    1696           0 :   mLengthLists[aAttrEnum].ClearBaseValue(aAttrEnum);
    1697             :   // caller notifies
    1698           0 : }
    1699             : 
    1700             : nsAttrValue
    1701           0 : nsSVGElement::WillChangeLengthList(uint8_t aAttrEnum)
    1702             : {
    1703           0 :   return WillChangeValue(*GetLengthListInfo().mLengthListInfo[aAttrEnum].mName);
    1704             : }
    1705             : 
    1706             : void
    1707           0 : nsSVGElement::DidChangeLengthList(uint8_t aAttrEnum,
    1708             :                                   const nsAttrValue& aEmptyOrOldValue)
    1709             : {
    1710           0 :   LengthListAttributesInfo info = GetLengthListInfo();
    1711             : 
    1712           0 :   NS_ASSERTION(info.mLengthListCount > 0,
    1713             :                "DidChangeLengthList on element with no length list attribs");
    1714           0 :   NS_ASSERTION(aAttrEnum < info.mLengthListCount, "aAttrEnum out of range");
    1715             : 
    1716           0 :   nsAttrValue newValue;
    1717           0 :   newValue.SetTo(info.mLengthLists[aAttrEnum].GetBaseValue(), nullptr);
    1718             : 
    1719           0 :   DidChangeValue(*info.mLengthListInfo[aAttrEnum].mName, aEmptyOrOldValue,
    1720           0 :                  newValue);
    1721           0 : }
    1722             : 
    1723             : void
    1724           0 : nsSVGElement::DidAnimateLengthList(uint8_t aAttrEnum)
    1725             : {
    1726           0 :   nsIFrame* frame = GetPrimaryFrame();
    1727             : 
    1728           0 :   if (frame) {
    1729           0 :     LengthListAttributesInfo info = GetLengthListInfo();
    1730           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1731           0 :                             *info.mLengthListInfo[aAttrEnum].mName,
    1732           0 :                             nsIDOMMutationEvent::SMIL);
    1733             :   }
    1734           0 : }
    1735             : 
    1736             : void
    1737           0 : nsSVGElement::GetAnimatedLengthListValues(SVGUserUnitList *aFirst, ...)
    1738             : {
    1739           0 :   LengthListAttributesInfo info = GetLengthListInfo();
    1740             : 
    1741           0 :   NS_ASSERTION(info.mLengthListCount > 0,
    1742             :                "GetAnimatedLengthListValues on element with no length list attribs");
    1743             : 
    1744           0 :   SVGUserUnitList *list = aFirst;
    1745           0 :   uint32_t i = 0;
    1746             : 
    1747             :   va_list args;
    1748           0 :   va_start(args, aFirst);
    1749             : 
    1750           0 :   while (list && i < info.mLengthListCount) {
    1751           0 :     list->Init(&(info.mLengthLists[i].GetAnimValue()), this, info.mLengthListInfo[i].mAxis);
    1752           0 :     ++i;
    1753           0 :     list = va_arg(args, SVGUserUnitList*);
    1754             :   }
    1755             : 
    1756           0 :   va_end(args);
    1757           0 : }
    1758             : 
    1759             : SVGAnimatedLengthList*
    1760           0 : nsSVGElement::GetAnimatedLengthList(uint8_t aAttrEnum)
    1761             : {
    1762           0 :   LengthListAttributesInfo info = GetLengthListInfo();
    1763           0 :   if (aAttrEnum < info.mLengthListCount) {
    1764           0 :     return &(info.mLengthLists[aAttrEnum]);
    1765             :   }
    1766           0 :   NS_NOTREACHED("Bad attrEnum");
    1767           0 :   return nullptr;
    1768             : }
    1769             : 
    1770             : 
    1771             : nsSVGElement::NumberListAttributesInfo
    1772         357 : nsSVGElement::GetNumberListInfo()
    1773             : {
    1774         357 :   return NumberListAttributesInfo(nullptr, nullptr, 0);
    1775             : }
    1776             : 
    1777             : void
    1778           0 : nsSVGElement::NumberListAttributesInfo::Reset(uint8_t aAttrEnum)
    1779             : {
    1780           0 :   MOZ_ASSERT(aAttrEnum < mNumberListCount, "Bad attr enum");
    1781           0 :   mNumberLists[aAttrEnum].ClearBaseValue(aAttrEnum);
    1782             :   // caller notifies
    1783           0 : }
    1784             : 
    1785             : nsAttrValue
    1786           0 : nsSVGElement::WillChangeNumberList(uint8_t aAttrEnum)
    1787             : {
    1788           0 :   return WillChangeValue(*GetNumberListInfo().mNumberListInfo[aAttrEnum].mName);
    1789             : }
    1790             : 
    1791             : void
    1792           0 : nsSVGElement::DidChangeNumberList(uint8_t aAttrEnum,
    1793             :                                   const nsAttrValue& aEmptyOrOldValue)
    1794             : {
    1795           0 :   NumberListAttributesInfo info = GetNumberListInfo();
    1796             : 
    1797           0 :   MOZ_ASSERT(info.mNumberListCount > 0,
    1798             :              "DidChangeNumberList on element with no number list attribs");
    1799           0 :   MOZ_ASSERT(aAttrEnum < info.mNumberListCount,
    1800             :              "aAttrEnum out of range");
    1801             : 
    1802           0 :   nsAttrValue newValue;
    1803           0 :   newValue.SetTo(info.mNumberLists[aAttrEnum].GetBaseValue(), nullptr);
    1804             : 
    1805           0 :   DidChangeValue(*info.mNumberListInfo[aAttrEnum].mName, aEmptyOrOldValue,
    1806           0 :                  newValue);
    1807           0 : }
    1808             : 
    1809             : void
    1810           0 : nsSVGElement::DidAnimateNumberList(uint8_t aAttrEnum)
    1811             : {
    1812           0 :   nsIFrame* frame = GetPrimaryFrame();
    1813             : 
    1814           0 :   if (frame) {
    1815           0 :     NumberListAttributesInfo info = GetNumberListInfo();
    1816           0 :     MOZ_ASSERT(aAttrEnum < info.mNumberListCount, "aAttrEnum out of range");
    1817             : 
    1818           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1819           0 :                             *info.mNumberListInfo[aAttrEnum].mName,
    1820           0 :                             nsIDOMMutationEvent::SMIL);
    1821             :   }
    1822           0 : }
    1823             : 
    1824             : SVGAnimatedNumberList*
    1825           0 : nsSVGElement::GetAnimatedNumberList(uint8_t aAttrEnum)
    1826             : {
    1827           0 :   NumberListAttributesInfo info = GetNumberListInfo();
    1828           0 :   if (aAttrEnum < info.mNumberListCount) {
    1829           0 :     return &(info.mNumberLists[aAttrEnum]);
    1830             :   }
    1831           0 :   MOZ_ASSERT(false, "Bad attrEnum");
    1832             :   return nullptr;
    1833             : }
    1834             : 
    1835             : SVGAnimatedNumberList*
    1836           0 : nsSVGElement::GetAnimatedNumberList(nsIAtom *aAttrName)
    1837             : {
    1838           0 :   NumberListAttributesInfo info = GetNumberListInfo();
    1839           0 :   for (uint32_t i = 0; i < info.mNumberListCount; i++) {
    1840           0 :     if (aAttrName == *info.mNumberListInfo[i].mName) {
    1841           0 :       return &info.mNumberLists[i];
    1842             :     }
    1843             :   }
    1844           0 :   MOZ_ASSERT(false, "Bad caller");
    1845             :   return nullptr;
    1846             : }
    1847             : 
    1848             : nsAttrValue
    1849           0 : nsSVGElement::WillChangePointList()
    1850             : {
    1851           0 :   MOZ_ASSERT(GetPointListAttrName(),
    1852             :              "Changing non-existent point list?");
    1853           0 :   return WillChangeValue(GetPointListAttrName());
    1854             : }
    1855             : 
    1856             : void
    1857           0 : nsSVGElement::DidChangePointList(const nsAttrValue& aEmptyOrOldValue)
    1858             : {
    1859           0 :   MOZ_ASSERT(GetPointListAttrName(),
    1860             :              "Changing non-existent point list?");
    1861             : 
    1862           0 :   nsAttrValue newValue;
    1863           0 :   newValue.SetTo(GetAnimatedPointList()->GetBaseValue(), nullptr);
    1864             : 
    1865           0 :   DidChangeValue(GetPointListAttrName(), aEmptyOrOldValue, newValue);
    1866           0 : }
    1867             : 
    1868             : void
    1869           0 : nsSVGElement::DidAnimatePointList()
    1870             : {
    1871           0 :   MOZ_ASSERT(GetPointListAttrName(),
    1872             :              "Animating non-existent path data?");
    1873             : 
    1874           0 :   ClearAnyCachedPath();
    1875             : 
    1876           0 :   nsIFrame* frame = GetPrimaryFrame();
    1877             : 
    1878           0 :   if (frame) {
    1879           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1880           0 :                             GetPointListAttrName(),
    1881           0 :                             nsIDOMMutationEvent::SMIL);
    1882             :   }
    1883           0 : }
    1884             : 
    1885             : nsAttrValue
    1886           0 : nsSVGElement::WillChangePathSegList()
    1887             : {
    1888           0 :   MOZ_ASSERT(GetPathDataAttrName(),
    1889             :              "Changing non-existent path seg list?");
    1890           0 :   return WillChangeValue(GetPathDataAttrName());
    1891             : }
    1892             : 
    1893             : void
    1894           0 : nsSVGElement::DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue)
    1895             : {
    1896           0 :   MOZ_ASSERT(GetPathDataAttrName(),
    1897             :              "Changing non-existent path seg list?");
    1898             : 
    1899           0 :   nsAttrValue newValue;
    1900           0 :   newValue.SetTo(GetAnimPathSegList()->GetBaseValue(), nullptr);
    1901             : 
    1902           0 :   DidChangeValue(GetPathDataAttrName(), aEmptyOrOldValue, newValue);
    1903           0 : }
    1904             : 
    1905             : void
    1906           0 : nsSVGElement::DidAnimatePathSegList()
    1907             : {
    1908           0 :   MOZ_ASSERT(GetPathDataAttrName(),
    1909             :              "Animating non-existent path data?");
    1910             : 
    1911           0 :   ClearAnyCachedPath();
    1912             : 
    1913           0 :   nsIFrame* frame = GetPrimaryFrame();
    1914             : 
    1915           0 :   if (frame) {
    1916           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1917           0 :                             GetPathDataAttrName(),
    1918           0 :                             nsIDOMMutationEvent::SMIL);
    1919             :   }
    1920           0 : }
    1921             : 
    1922             : nsSVGElement::NumberAttributesInfo
    1923         161 : nsSVGElement::GetNumberInfo()
    1924             : {
    1925         161 :   return NumberAttributesInfo(nullptr, nullptr, 0);
    1926             : }
    1927             : 
    1928          73 : void nsSVGElement::NumberAttributesInfo::Reset(uint8_t aAttrEnum)
    1929             : {
    1930          73 :   mNumbers[aAttrEnum].Init(aAttrEnum,
    1931         146 :                            mNumberInfo[aAttrEnum].mDefaultValue);
    1932          73 : }
    1933             : 
    1934             : void
    1935           0 : nsSVGElement::DidChangeNumber(uint8_t aAttrEnum)
    1936             : {
    1937           0 :   NumberAttributesInfo info = GetNumberInfo();
    1938             : 
    1939           0 :   NS_ASSERTION(info.mNumberCount > 0,
    1940             :                "DidChangeNumber on element with no number attribs");
    1941           0 :   NS_ASSERTION(aAttrEnum < info.mNumberCount, "aAttrEnum out of range");
    1942             : 
    1943           0 :   nsAttrValue attrValue;
    1944           0 :   attrValue.SetTo(info.mNumbers[aAttrEnum].GetBaseValue(), nullptr);
    1945             : 
    1946           0 :   SetParsedAttr(kNameSpaceID_None, *info.mNumberInfo[aAttrEnum].mName, nullptr,
    1947           0 :                 attrValue, true);
    1948           0 : }
    1949             : 
    1950             : void
    1951           0 : nsSVGElement::DidAnimateNumber(uint8_t aAttrEnum)
    1952             : {
    1953           0 :   nsIFrame* frame = GetPrimaryFrame();
    1954             : 
    1955           0 :   if (frame) {
    1956           0 :     NumberAttributesInfo info = GetNumberInfo();
    1957           0 :     frame->AttributeChanged(kNameSpaceID_None,
    1958           0 :                             *info.mNumberInfo[aAttrEnum].mName,
    1959           0 :                             nsIDOMMutationEvent::SMIL);
    1960             :   }
    1961           0 : }
    1962             : 
    1963             : void
    1964           0 : nsSVGElement::GetAnimatedNumberValues(float *aFirst, ...)
    1965             : {
    1966           0 :   NumberAttributesInfo info = GetNumberInfo();
    1967             : 
    1968           0 :   NS_ASSERTION(info.mNumberCount > 0,
    1969             :                "GetAnimatedNumberValues on element with no number attribs");
    1970             : 
    1971           0 :   float *f = aFirst;
    1972           0 :   uint32_t i = 0;
    1973             : 
    1974             :   va_list args;
    1975           0 :   va_start(args, aFirst);
    1976             : 
    1977           0 :   while (f && i < info.mNumberCount) {
    1978           0 :     *f = info.mNumbers[i++].GetAnimValue();
    1979           0 :     f = va_arg(args, float*);
    1980             :   }
    1981           0 :   va_end(args);
    1982           0 : }
    1983             : 
    1984             : nsSVGElement::NumberPairAttributesInfo
    1985         299 : nsSVGElement::GetNumberPairInfo()
    1986             : {
    1987         299 :   return NumberPairAttributesInfo(nullptr, nullptr, 0);
    1988             : }
    1989             : 
    1990           0 : void nsSVGElement::NumberPairAttributesInfo::Reset(uint8_t aAttrEnum)
    1991             : {
    1992           0 :   mNumberPairs[aAttrEnum].Init(aAttrEnum,
    1993           0 :                                mNumberPairInfo[aAttrEnum].mDefaultValue1,
    1994           0 :                                mNumberPairInfo[aAttrEnum].mDefaultValue2);
    1995           0 : }
    1996             : 
    1997             : nsAttrValue
    1998           0 : nsSVGElement::WillChangeNumberPair(uint8_t aAttrEnum)
    1999             : {
    2000           0 :   return WillChangeValue(*GetNumberPairInfo().mNumberPairInfo[aAttrEnum].mName);
    2001             : }
    2002             : 
    2003             : void
    2004           0 : nsSVGElement::DidChangeNumberPair(uint8_t aAttrEnum,
    2005             :                                   const nsAttrValue& aEmptyOrOldValue)
    2006             : {
    2007           0 :   NumberPairAttributesInfo info = GetNumberPairInfo();
    2008             : 
    2009           0 :   NS_ASSERTION(info.mNumberPairCount > 0,
    2010             :                "DidChangePairNumber on element with no number pair attribs");
    2011           0 :   NS_ASSERTION(aAttrEnum < info.mNumberPairCount, "aAttrEnum out of range");
    2012             : 
    2013           0 :   nsAttrValue newValue;
    2014           0 :   newValue.SetTo(info.mNumberPairs[aAttrEnum], nullptr);
    2015             : 
    2016           0 :   DidChangeValue(*info.mNumberPairInfo[aAttrEnum].mName, aEmptyOrOldValue,
    2017           0 :                  newValue);
    2018           0 : }
    2019             : 
    2020             : void
    2021           0 : nsSVGElement::DidAnimateNumberPair(uint8_t aAttrEnum)
    2022             : {
    2023           0 :   nsIFrame* frame = GetPrimaryFrame();
    2024             : 
    2025           0 :   if (frame) {
    2026           0 :     NumberPairAttributesInfo info = GetNumberPairInfo();
    2027           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2028           0 :                             *info.mNumberPairInfo[aAttrEnum].mName,
    2029           0 :                             nsIDOMMutationEvent::SMIL);
    2030             :   }
    2031           0 : }
    2032             : 
    2033             : nsSVGElement::IntegerAttributesInfo
    2034         299 : nsSVGElement::GetIntegerInfo()
    2035             : {
    2036         299 :   return IntegerAttributesInfo(nullptr, nullptr, 0);
    2037             : }
    2038             : 
    2039           0 : void nsSVGElement::IntegerAttributesInfo::Reset(uint8_t aAttrEnum)
    2040             : {
    2041           0 :   mIntegers[aAttrEnum].Init(aAttrEnum,
    2042           0 :                             mIntegerInfo[aAttrEnum].mDefaultValue);
    2043           0 : }
    2044             : 
    2045             : void
    2046           0 : nsSVGElement::DidChangeInteger(uint8_t aAttrEnum)
    2047             : {
    2048           0 :   IntegerAttributesInfo info = GetIntegerInfo();
    2049             : 
    2050           0 :   NS_ASSERTION(info.mIntegerCount > 0,
    2051             :                "DidChangeInteger on element with no integer attribs");
    2052           0 :   NS_ASSERTION(aAttrEnum < info.mIntegerCount, "aAttrEnum out of range");
    2053             : 
    2054           0 :   nsAttrValue attrValue;
    2055           0 :   attrValue.SetTo(info.mIntegers[aAttrEnum].GetBaseValue(), nullptr);
    2056             : 
    2057           0 :   SetParsedAttr(kNameSpaceID_None, *info.mIntegerInfo[aAttrEnum].mName, nullptr,
    2058           0 :                 attrValue, true);
    2059           0 : }
    2060             : 
    2061             : void
    2062           0 : nsSVGElement::DidAnimateInteger(uint8_t aAttrEnum)
    2063             : {
    2064           0 :   nsIFrame* frame = GetPrimaryFrame();
    2065             : 
    2066           0 :   if (frame) {
    2067           0 :     IntegerAttributesInfo info = GetIntegerInfo();
    2068           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2069           0 :                             *info.mIntegerInfo[aAttrEnum].mName,
    2070           0 :                             nsIDOMMutationEvent::SMIL);
    2071             :   }
    2072           0 : }
    2073             : 
    2074             : void
    2075           0 : nsSVGElement::GetAnimatedIntegerValues(int32_t *aFirst, ...)
    2076             : {
    2077           0 :   IntegerAttributesInfo info = GetIntegerInfo();
    2078             : 
    2079           0 :   NS_ASSERTION(info.mIntegerCount > 0,
    2080             :                "GetAnimatedIntegerValues on element with no integer attribs");
    2081             : 
    2082           0 :   int32_t *n = aFirst;
    2083           0 :   uint32_t i = 0;
    2084             : 
    2085             :   va_list args;
    2086           0 :   va_start(args, aFirst);
    2087             : 
    2088           0 :   while (n && i < info.mIntegerCount) {
    2089           0 :     *n = info.mIntegers[i++].GetAnimValue();
    2090           0 :     n = va_arg(args, int32_t*);
    2091             :   }
    2092           0 :   va_end(args);
    2093           0 : }
    2094             : 
    2095             : nsSVGElement::IntegerPairAttributesInfo
    2096         299 : nsSVGElement::GetIntegerPairInfo()
    2097             : {
    2098         299 :   return IntegerPairAttributesInfo(nullptr, nullptr, 0);
    2099             : }
    2100             : 
    2101           0 : void nsSVGElement::IntegerPairAttributesInfo::Reset(uint8_t aAttrEnum)
    2102             : {
    2103           0 :   mIntegerPairs[aAttrEnum].Init(aAttrEnum,
    2104           0 :                                 mIntegerPairInfo[aAttrEnum].mDefaultValue1,
    2105           0 :                                 mIntegerPairInfo[aAttrEnum].mDefaultValue2);
    2106           0 : }
    2107             : 
    2108             : nsAttrValue
    2109           0 : nsSVGElement::WillChangeIntegerPair(uint8_t aAttrEnum)
    2110             : {
    2111             :   return WillChangeValue(
    2112           0 :     *GetIntegerPairInfo().mIntegerPairInfo[aAttrEnum].mName);
    2113             : }
    2114             : 
    2115             : void
    2116           0 : nsSVGElement::DidChangeIntegerPair(uint8_t aAttrEnum,
    2117             :                                    const nsAttrValue& aEmptyOrOldValue)
    2118             : {
    2119           0 :   IntegerPairAttributesInfo info = GetIntegerPairInfo();
    2120             : 
    2121           0 :   NS_ASSERTION(info.mIntegerPairCount > 0,
    2122             :                "DidChangeIntegerPair on element with no integer pair attribs");
    2123           0 :   NS_ASSERTION(aAttrEnum < info.mIntegerPairCount, "aAttrEnum out of range");
    2124             : 
    2125           0 :   nsAttrValue newValue;
    2126           0 :   newValue.SetTo(info.mIntegerPairs[aAttrEnum], nullptr);
    2127             : 
    2128           0 :   DidChangeValue(*info.mIntegerPairInfo[aAttrEnum].mName, aEmptyOrOldValue,
    2129           0 :                  newValue);
    2130           0 : }
    2131             : 
    2132             : void
    2133           0 : nsSVGElement::DidAnimateIntegerPair(uint8_t aAttrEnum)
    2134             : {
    2135           0 :   nsIFrame* frame = GetPrimaryFrame();
    2136             : 
    2137           0 :   if (frame) {
    2138           0 :     IntegerPairAttributesInfo info = GetIntegerPairInfo();
    2139           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2140           0 :                             *info.mIntegerPairInfo[aAttrEnum].mName,
    2141           0 :                             nsIDOMMutationEvent::SMIL);
    2142             :   }
    2143           0 : }
    2144             : 
    2145             : nsSVGElement::AngleAttributesInfo
    2146         299 : nsSVGElement::GetAngleInfo()
    2147             : {
    2148         299 :   return AngleAttributesInfo(nullptr, nullptr, 0);
    2149             : }
    2150             : 
    2151           0 : void nsSVGElement::AngleAttributesInfo::Reset(uint8_t aAttrEnum)
    2152             : {
    2153           0 :   mAngles[aAttrEnum].Init(aAttrEnum,
    2154           0 :                           mAngleInfo[aAttrEnum].mDefaultValue,
    2155           0 :                           mAngleInfo[aAttrEnum].mDefaultUnitType);
    2156           0 : }
    2157             : 
    2158             : nsAttrValue
    2159           0 : nsSVGElement::WillChangeAngle(uint8_t aAttrEnum)
    2160             : {
    2161           0 :   return WillChangeValue(*GetAngleInfo().mAngleInfo[aAttrEnum].mName);
    2162             : }
    2163             : 
    2164             : void
    2165           0 : nsSVGElement::DidChangeAngle(uint8_t aAttrEnum,
    2166             :                              const nsAttrValue& aEmptyOrOldValue)
    2167             : {
    2168           0 :   AngleAttributesInfo info = GetAngleInfo();
    2169             : 
    2170           0 :   NS_ASSERTION(info.mAngleCount > 0,
    2171             :                "DidChangeAngle on element with no angle attribs");
    2172           0 :   NS_ASSERTION(aAttrEnum < info.mAngleCount, "aAttrEnum out of range");
    2173             : 
    2174           0 :   nsAttrValue newValue;
    2175           0 :   newValue.SetTo(info.mAngles[aAttrEnum], nullptr);
    2176             : 
    2177           0 :   DidChangeValue(*info.mAngleInfo[aAttrEnum].mName, aEmptyOrOldValue, newValue);
    2178           0 : }
    2179             : 
    2180             : void
    2181           0 : nsSVGElement::DidAnimateAngle(uint8_t aAttrEnum)
    2182             : {
    2183           0 :   nsIFrame* frame = GetPrimaryFrame();
    2184             : 
    2185           0 :   if (frame) {
    2186           0 :     AngleAttributesInfo info = GetAngleInfo();
    2187           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2188           0 :                             *info.mAngleInfo[aAttrEnum].mName,
    2189           0 :                             nsIDOMMutationEvent::SMIL);
    2190             :   }
    2191           0 : }
    2192             : 
    2193             : nsSVGElement::BooleanAttributesInfo
    2194         299 : nsSVGElement::GetBooleanInfo()
    2195             : {
    2196         299 :   return BooleanAttributesInfo(nullptr, nullptr, 0);
    2197             : }
    2198             : 
    2199           0 : void nsSVGElement::BooleanAttributesInfo::Reset(uint8_t aAttrEnum)
    2200             : {
    2201           0 :   mBooleans[aAttrEnum].Init(aAttrEnum,
    2202           0 :                             mBooleanInfo[aAttrEnum].mDefaultValue);
    2203           0 : }
    2204             : 
    2205             : void
    2206           0 : nsSVGElement::DidChangeBoolean(uint8_t aAttrEnum)
    2207             : {
    2208           0 :   BooleanAttributesInfo info = GetBooleanInfo();
    2209             : 
    2210           0 :   NS_ASSERTION(info.mBooleanCount > 0,
    2211             :                "DidChangeBoolean on element with no boolean attribs");
    2212           0 :   NS_ASSERTION(aAttrEnum < info.mBooleanCount, "aAttrEnum out of range");
    2213             : 
    2214           0 :   nsAttrValue attrValue(info.mBooleans[aAttrEnum].GetBaseValueAtom());
    2215           0 :   SetParsedAttr(kNameSpaceID_None, *info.mBooleanInfo[aAttrEnum].mName, nullptr,
    2216           0 :                 attrValue, true);
    2217           0 : }
    2218             : 
    2219             : void
    2220           0 : nsSVGElement::DidAnimateBoolean(uint8_t aAttrEnum)
    2221             : {
    2222           0 :   nsIFrame* frame = GetPrimaryFrame();
    2223             : 
    2224           0 :   if (frame) {
    2225           0 :     BooleanAttributesInfo info = GetBooleanInfo();
    2226           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2227           0 :                             *info.mBooleanInfo[aAttrEnum].mName,
    2228           0 :                             nsIDOMMutationEvent::SMIL);
    2229             :   }
    2230           0 : }
    2231             : 
    2232             : nsSVGElement::EnumAttributesInfo
    2233         235 : nsSVGElement::GetEnumInfo()
    2234             : {
    2235         235 :   return EnumAttributesInfo(nullptr, nullptr, 0);
    2236             : }
    2237             : 
    2238          32 : void nsSVGElement::EnumAttributesInfo::Reset(uint8_t aAttrEnum)
    2239             : {
    2240          32 :   mEnums[aAttrEnum].Init(aAttrEnum,
    2241          64 :                          mEnumInfo[aAttrEnum].mDefaultValue);
    2242          32 : }
    2243             : 
    2244             : void
    2245           0 : nsSVGElement::DidChangeEnum(uint8_t aAttrEnum)
    2246             : {
    2247           0 :   EnumAttributesInfo info = GetEnumInfo();
    2248             : 
    2249           0 :   NS_ASSERTION(info.mEnumCount > 0,
    2250             :                "DidChangeEnum on element with no enum attribs");
    2251           0 :   NS_ASSERTION(aAttrEnum < info.mEnumCount, "aAttrEnum out of range");
    2252             : 
    2253           0 :   nsAttrValue attrValue(info.mEnums[aAttrEnum].GetBaseValueAtom(this));
    2254           0 :   SetParsedAttr(kNameSpaceID_None, *info.mEnumInfo[aAttrEnum].mName, nullptr,
    2255           0 :                 attrValue, true);
    2256           0 : }
    2257             : 
    2258             : void
    2259           0 : nsSVGElement::DidAnimateEnum(uint8_t aAttrEnum)
    2260             : {
    2261           0 :   nsIFrame* frame = GetPrimaryFrame();
    2262             : 
    2263           0 :   if (frame) {
    2264           0 :     EnumAttributesInfo info = GetEnumInfo();
    2265           0 :     frame->AttributeChanged(kNameSpaceID_None,
    2266           0 :                             *info.mEnumInfo[aAttrEnum].mName,
    2267           0 :                             nsIDOMMutationEvent::SMIL);
    2268             :   }
    2269           0 : }
    2270             : 
    2271             : nsSVGViewBox *
    2272         129 : nsSVGElement::GetViewBox()
    2273             : {
    2274         129 :   return nullptr;
    2275             : }
    2276             : 
    2277             : nsAttrValue
    2278           0 : nsSVGElement::WillChangeViewBox()
    2279             : {
    2280           0 :   return WillChangeValue(nsGkAtoms::viewBox);
    2281             : }
    2282             : 
    2283             : void
    2284           0 : nsSVGElement::DidChangeViewBox(const nsAttrValue& aEmptyOrOldValue)
    2285             : {
    2286           0 :   nsSVGViewBox *viewBox = GetViewBox();
    2287             : 
    2288           0 :   NS_ASSERTION(viewBox, "DidChangeViewBox on element with no viewBox attrib");
    2289             : 
    2290           0 :   nsAttrValue newValue;
    2291           0 :   newValue.SetTo(*viewBox, nullptr);
    2292             : 
    2293           0 :   DidChangeValue(nsGkAtoms::viewBox, aEmptyOrOldValue, newValue);
    2294           0 : }
    2295             : 
    2296             : void
    2297           0 : nsSVGElement::DidAnimateViewBox()
    2298             : {
    2299           0 :   nsIFrame* frame = GetPrimaryFrame();
    2300             : 
    2301           0 :   if (frame) {
    2302             :     frame->AttributeChanged(kNameSpaceID_None,
    2303             :                             nsGkAtoms::viewBox,
    2304           0 :                             nsIDOMMutationEvent::SMIL);
    2305             :   }
    2306           0 : }
    2307             : 
    2308             : SVGAnimatedPreserveAspectRatio *
    2309         129 : nsSVGElement::GetPreserveAspectRatio()
    2310             : {
    2311         129 :   return nullptr;
    2312             : }
    2313             : 
    2314             : nsAttrValue
    2315           0 : nsSVGElement::WillChangePreserveAspectRatio()
    2316             : {
    2317           0 :   return WillChangeValue(nsGkAtoms::preserveAspectRatio);
    2318             : }
    2319             : 
    2320             : void
    2321           0 : nsSVGElement::DidChangePreserveAspectRatio(const nsAttrValue& aEmptyOrOldValue)
    2322             : {
    2323             :   SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
    2324           0 :     GetPreserveAspectRatio();
    2325             : 
    2326           0 :   NS_ASSERTION(preserveAspectRatio,
    2327             :                "DidChangePreserveAspectRatio on element with no "
    2328             :                "preserveAspectRatio attrib");
    2329             : 
    2330           0 :   nsAttrValue newValue;
    2331           0 :   newValue.SetTo(*preserveAspectRatio, nullptr);
    2332             : 
    2333           0 :   DidChangeValue(nsGkAtoms::preserveAspectRatio, aEmptyOrOldValue, newValue);
    2334           0 : }
    2335             : 
    2336             : void
    2337           0 : nsSVGElement::DidAnimatePreserveAspectRatio()
    2338             : {
    2339           0 :   nsIFrame* frame = GetPrimaryFrame();
    2340             : 
    2341           0 :   if (frame) {
    2342             :     frame->AttributeChanged(kNameSpaceID_None,
    2343             :                             nsGkAtoms::preserveAspectRatio,
    2344           0 :                             nsIDOMMutationEvent::SMIL);
    2345             :   }
    2346           0 : }
    2347             : 
    2348             : nsAttrValue
    2349           0 : nsSVGElement::WillChangeTransformList()
    2350             : {
    2351           0 :   return WillChangeValue(GetTransformListAttrName());
    2352             : }
    2353             : 
    2354             : void
    2355           0 : nsSVGElement::DidChangeTransformList(const nsAttrValue& aEmptyOrOldValue)
    2356             : {
    2357           0 :   MOZ_ASSERT(GetTransformListAttrName(),
    2358             :              "Changing non-existent transform list?");
    2359             : 
    2360             :   // The transform attribute is being set, so we must ensure that the
    2361             :   // SVGAnimatedTransformList is/has been allocated:
    2362           0 :   nsAttrValue newValue;
    2363           0 :   newValue.SetTo(GetAnimatedTransformList(DO_ALLOCATE)->GetBaseValue(), nullptr);
    2364             : 
    2365           0 :   DidChangeValue(GetTransformListAttrName(), aEmptyOrOldValue, newValue);
    2366           0 : }
    2367             : 
    2368             : void
    2369           0 : nsSVGElement::DidAnimateTransformList(int32_t aModType)
    2370             : {
    2371           0 :   MOZ_ASSERT(GetTransformListAttrName(),
    2372             :              "Animating non-existent transform data?");
    2373             : 
    2374           0 :   nsIFrame* frame = GetPrimaryFrame();
    2375             : 
    2376           0 :   if (frame) {
    2377           0 :     nsIAtom *transformAttr = GetTransformListAttrName();
    2378             :     frame->AttributeChanged(kNameSpaceID_None,
    2379             :                             transformAttr,
    2380           0 :                             aModType);
    2381             :     // When script changes the 'transform' attribute, Element::SetAttrAndNotify
    2382             :     // will call nsNodeUtills::AttributeChanged, under which
    2383             :     // SVGTransformableElement::GetAttributeChangeHint will be called and an
    2384             :     // appropriate change event posted to update our frame's overflow rects.
    2385             :     // The SetAttrAndNotify doesn't happen for transform changes caused by
    2386             :     // 'animateTransform' though (and sending out the mutation events that
    2387             :     // nsNodeUtills::AttributeChanged dispatches would be inappropriate
    2388             :     // anyway), so we need to post the change event ourself.
    2389           0 :     nsChangeHint changeHint = GetAttributeChangeHint(transformAttr, aModType);
    2390           0 :     if (changeHint) {
    2391           0 :       nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), changeHint);
    2392             :     }
    2393             :   }
    2394           0 : }
    2395             : 
    2396             : nsSVGElement::StringAttributesInfo
    2397         238 : nsSVGElement::GetStringInfo()
    2398             : {
    2399         238 :   return StringAttributesInfo(nullptr, nullptr, 0);
    2400             : }
    2401             : 
    2402          58 : void nsSVGElement::StringAttributesInfo::Reset(uint8_t aAttrEnum)
    2403             : {
    2404          58 :   mStrings[aAttrEnum].Init(aAttrEnum);
    2405          58 : }
    2406             : 
    2407          23 : void nsSVGElement::GetStringBaseValue(uint8_t aAttrEnum, nsAString& aResult) const
    2408             : {
    2409          23 :   nsSVGElement::StringAttributesInfo info = const_cast<nsSVGElement*>(this)->GetStringInfo();
    2410             : 
    2411          23 :   NS_ASSERTION(info.mStringCount > 0,
    2412             :                "GetBaseValue on element with no string attribs");
    2413             : 
    2414          23 :   NS_ASSERTION(aAttrEnum < info.mStringCount, "aAttrEnum out of range");
    2415             : 
    2416          23 :   GetAttr(info.mStringInfo[aAttrEnum].mNamespaceID,
    2417          46 :           *info.mStringInfo[aAttrEnum].mName, aResult);
    2418          23 : }
    2419             : 
    2420           0 : void nsSVGElement::SetStringBaseValue(uint8_t aAttrEnum, const nsAString& aValue)
    2421             : {
    2422           0 :   nsSVGElement::StringAttributesInfo info = GetStringInfo();
    2423             : 
    2424           0 :   NS_ASSERTION(info.mStringCount > 0,
    2425             :                "SetBaseValue on element with no string attribs");
    2426             : 
    2427           0 :   NS_ASSERTION(aAttrEnum < info.mStringCount, "aAttrEnum out of range");
    2428             : 
    2429           0 :   SetAttr(info.mStringInfo[aAttrEnum].mNamespaceID,
    2430           0 :           *info.mStringInfo[aAttrEnum].mName, aValue, true);
    2431           0 : }
    2432             : 
    2433             : void
    2434           0 : nsSVGElement::DidAnimateString(uint8_t aAttrEnum)
    2435             : {
    2436           0 :   nsIFrame* frame = GetPrimaryFrame();
    2437             : 
    2438           0 :   if (frame) {
    2439           0 :     StringAttributesInfo info = GetStringInfo();
    2440           0 :     frame->AttributeChanged(info.mStringInfo[aAttrEnum].mNamespaceID,
    2441           0 :                             *info.mStringInfo[aAttrEnum].mName,
    2442           0 :                             nsIDOMMutationEvent::SMIL);
    2443             :   }
    2444           0 : }
    2445             : 
    2446             : nsSVGElement::StringListAttributesInfo
    2447         142 : nsSVGElement::GetStringListInfo()
    2448             : {
    2449         142 :   return StringListAttributesInfo(nullptr, nullptr, 0);
    2450             : }
    2451             : 
    2452             : nsAttrValue
    2453           0 : nsSVGElement::WillChangeStringList(bool aIsConditionalProcessingAttribute,
    2454             :                                    uint8_t aAttrEnum)
    2455             : {
    2456             :   nsIAtom* name;
    2457           0 :   if (aIsConditionalProcessingAttribute) {
    2458           0 :     nsCOMPtr<SVGTests> tests(do_QueryInterface(static_cast<nsIDOMSVGElement*>(this)));
    2459           0 :     name = tests->GetAttrName(aAttrEnum);
    2460             :   } else {
    2461           0 :     name = *GetStringListInfo().mStringListInfo[aAttrEnum].mName;
    2462             :   }
    2463           0 :   return WillChangeValue(name);
    2464             : }
    2465             : 
    2466             : void
    2467           0 : nsSVGElement::DidChangeStringList(bool aIsConditionalProcessingAttribute,
    2468             :                                   uint8_t aAttrEnum,
    2469             :                                   const nsAttrValue& aEmptyOrOldValue)
    2470             : {
    2471             :   nsIAtom* name;
    2472           0 :   nsAttrValue newValue;
    2473           0 :   nsCOMPtr<SVGTests> tests;
    2474             : 
    2475           0 :   if (aIsConditionalProcessingAttribute) {
    2476           0 :     tests = do_QueryObject(this);
    2477           0 :     name = tests->GetAttrName(aAttrEnum);
    2478           0 :     tests->GetAttrValue(aAttrEnum, newValue);
    2479             :   } else {
    2480           0 :     StringListAttributesInfo info = GetStringListInfo();
    2481             : 
    2482           0 :     NS_ASSERTION(info.mStringListCount > 0,
    2483             :                  "DidChangeStringList on element with no string list attribs");
    2484           0 :     NS_ASSERTION(aAttrEnum < info.mStringListCount, "aAttrEnum out of range");
    2485             : 
    2486           0 :     name = *info.mStringListInfo[aAttrEnum].mName;
    2487           0 :     newValue.SetTo(info.mStringLists[aAttrEnum], nullptr);
    2488             :   }
    2489             : 
    2490           0 :   DidChangeValue(name, aEmptyOrOldValue, newValue);
    2491             : 
    2492           0 :   if (aIsConditionalProcessingAttribute) {
    2493           0 :     tests->MaybeInvalidate();
    2494             :   }
    2495           0 : }
    2496             : 
    2497             : void
    2498           0 : nsSVGElement::StringListAttributesInfo::Reset(uint8_t aAttrEnum)
    2499             : {
    2500           0 :   mStringLists[aAttrEnum].Clear();
    2501             :   // caller notifies
    2502           0 : }
    2503             : 
    2504             : nsresult
    2505           0 : nsSVGElement::ReportAttributeParseFailure(nsIDocument* aDocument,
    2506             :                                           nsIAtom* aAttribute,
    2507             :                                           const nsAString& aValue)
    2508             : {
    2509           0 :   const nsString& attributeValue = PromiseFlatString(aValue);
    2510           0 :   const char16_t *strings[] = { aAttribute->GetUTF16String(),
    2511           0 :                                  attributeValue.get() };
    2512           0 :   return SVGContentUtils::ReportToConsole(aDocument,
    2513             :                                           "AttributeParseWarning",
    2514           0 :                                           strings, ArrayLength(strings));
    2515             : }
    2516             : 
    2517             : void
    2518           0 : nsSVGElement::RecompileScriptEventListeners()
    2519             : {
    2520           0 :   int32_t i, count = mAttrsAndChildren.AttrCount();
    2521           0 :   for (i = 0; i < count; ++i) {
    2522           0 :     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
    2523             : 
    2524             :     // Eventlistenener-attributes are always in the null namespace
    2525           0 :     if (!name->IsAtom()) {
    2526           0 :         continue;
    2527             :     }
    2528             : 
    2529           0 :     nsIAtom *attr = name->Atom();
    2530           0 :     if (!IsEventAttributeName(attr)) {
    2531           0 :       continue;
    2532             :     }
    2533             : 
    2534           0 :     nsAutoString value;
    2535           0 :     GetAttr(kNameSpaceID_None, attr, value);
    2536           0 :     SetEventHandler(GetEventNameForAttr(attr), value, true);
    2537             :   }
    2538           0 : }
    2539             : 
    2540             : UniquePtr<nsISMILAttr>
    2541           0 : nsSVGElement::GetAnimatedAttr(int32_t aNamespaceID, nsIAtom* aName)
    2542             : {
    2543           0 :   if (aNamespaceID == kNameSpaceID_None) {
    2544             :     // Transforms:
    2545           0 :     if (GetTransformListAttrName() == aName) {
    2546             :       // The transform attribute is being animated, so we must ensure that the
    2547             :       // SVGAnimatedTransformList is/has been allocated:
    2548           0 :       return GetAnimatedTransformList(DO_ALLOCATE)->ToSMILAttr(this);
    2549             :     }
    2550             : 
    2551             :     // Motion (fake 'attribute' for animateMotion)
    2552           0 :     if (aName == nsGkAtoms::mozAnimateMotionDummyAttr) {
    2553           0 :       return MakeUnique<SVGMotionSMILAttr>(this);
    2554             :     }
    2555             : 
    2556             :     // Lengths:
    2557           0 :     LengthAttributesInfo info = GetLengthInfo();
    2558           0 :     for (uint32_t i = 0; i < info.mLengthCount; i++) {
    2559           0 :       if (aName == *info.mLengthInfo[i].mName) {
    2560           0 :         return info.mLengths[i].ToSMILAttr(this);
    2561             :       }
    2562             :     }
    2563             : 
    2564             :     // Numbers:
    2565             :     {
    2566           0 :       NumberAttributesInfo info = GetNumberInfo();
    2567           0 :       for (uint32_t i = 0; i < info.mNumberCount; i++) {
    2568           0 :         if (aName == *info.mNumberInfo[i].mName) {
    2569           0 :           return info.mNumbers[i].ToSMILAttr(this);
    2570             :         }
    2571             :       }
    2572             :     }
    2573             : 
    2574             :     // Number Pairs:
    2575             :     {
    2576           0 :       NumberPairAttributesInfo info = GetNumberPairInfo();
    2577           0 :       for (uint32_t i = 0; i < info.mNumberPairCount; i++) {
    2578           0 :         if (aName == *info.mNumberPairInfo[i].mName) {
    2579           0 :           return info.mNumberPairs[i].ToSMILAttr(this);
    2580             :         }
    2581             :       }
    2582             :     }
    2583             : 
    2584             :     // Integers:
    2585             :     {
    2586           0 :       IntegerAttributesInfo info = GetIntegerInfo();
    2587           0 :       for (uint32_t i = 0; i < info.mIntegerCount; i++) {
    2588           0 :         if (aName == *info.mIntegerInfo[i].mName) {
    2589           0 :           return info.mIntegers[i].ToSMILAttr(this);
    2590             :         }
    2591             :       }
    2592             :     }
    2593             : 
    2594             :     // Integer Pairs:
    2595             :     {
    2596           0 :       IntegerPairAttributesInfo info = GetIntegerPairInfo();
    2597           0 :       for (uint32_t i = 0; i < info.mIntegerPairCount; i++) {
    2598           0 :         if (aName == *info.mIntegerPairInfo[i].mName) {
    2599           0 :           return info.mIntegerPairs[i].ToSMILAttr(this);
    2600             :         }
    2601             :       }
    2602             :     }
    2603             : 
    2604             :     // Enumerations:
    2605             :     {
    2606           0 :       EnumAttributesInfo info = GetEnumInfo();
    2607           0 :       for (uint32_t i = 0; i < info.mEnumCount; i++) {
    2608           0 :         if (aName == *info.mEnumInfo[i].mName) {
    2609           0 :           return info.mEnums[i].ToSMILAttr(this);
    2610             :         }
    2611             :       }
    2612             :     }
    2613             : 
    2614             :     // Booleans:
    2615             :     {
    2616           0 :       BooleanAttributesInfo info = GetBooleanInfo();
    2617           0 :       for (uint32_t i = 0; i < info.mBooleanCount; i++) {
    2618           0 :         if (aName == *info.mBooleanInfo[i].mName) {
    2619           0 :           return info.mBooleans[i].ToSMILAttr(this);
    2620             :         }
    2621             :       }
    2622             :     }
    2623             : 
    2624             :     // Angles:
    2625             :     {
    2626           0 :       AngleAttributesInfo info = GetAngleInfo();
    2627           0 :       for (uint32_t i = 0; i < info.mAngleCount; i++) {
    2628           0 :         if (aName == *info.mAngleInfo[i].mName) {
    2629           0 :           return info.mAngles[i].ToSMILAttr(this);
    2630             :         }
    2631             :       }
    2632             :     }
    2633             : 
    2634             :     // viewBox:
    2635           0 :     if (aName == nsGkAtoms::viewBox) {
    2636           0 :       nsSVGViewBox *viewBox = GetViewBox();
    2637           0 :       return viewBox ? viewBox->ToSMILAttr(this) : nullptr;
    2638             :     }
    2639             : 
    2640             :     // preserveAspectRatio:
    2641           0 :     if (aName == nsGkAtoms::preserveAspectRatio) {
    2642             :       SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
    2643           0 :         GetPreserveAspectRatio();
    2644             :       return preserveAspectRatio ?
    2645           0 :         preserveAspectRatio->ToSMILAttr(this) : nullptr;
    2646             :     }
    2647             : 
    2648             :     // NumberLists:
    2649             :     {
    2650           0 :       NumberListAttributesInfo info = GetNumberListInfo();
    2651           0 :       for (uint32_t i = 0; i < info.mNumberListCount; i++) {
    2652           0 :         if (aName == *info.mNumberListInfo[i].mName) {
    2653           0 :           MOZ_ASSERT(i <= UCHAR_MAX, "Too many attributes");
    2654           0 :           return info.mNumberLists[i].ToSMILAttr(this, uint8_t(i));
    2655             :         }
    2656             :       }
    2657             :     }
    2658             : 
    2659             :     // LengthLists:
    2660             :     {
    2661           0 :       LengthListAttributesInfo info = GetLengthListInfo();
    2662           0 :       for (uint32_t i = 0; i < info.mLengthListCount; i++) {
    2663           0 :         if (aName == *info.mLengthListInfo[i].mName) {
    2664           0 :           MOZ_ASSERT(i <= UCHAR_MAX, "Too many attributes");
    2665           0 :           return info.mLengthLists[i].ToSMILAttr(this,
    2666             :                                                  uint8_t(i),
    2667           0 :                                                  info.mLengthListInfo[i].mAxis,
    2668           0 :                                                  info.mLengthListInfo[i].mCouldZeroPadList);
    2669             :         }
    2670             :       }
    2671             :     }
    2672             : 
    2673             :     // PointLists:
    2674             :     {
    2675           0 :       if (GetPointListAttrName() == aName) {
    2676           0 :         SVGAnimatedPointList *pointList = GetAnimatedPointList();
    2677           0 :         if (pointList) {
    2678           0 :           return pointList->ToSMILAttr(this);
    2679             :         }
    2680             :       }
    2681             :     }
    2682             : 
    2683             :     // PathSegLists:
    2684             :     {
    2685           0 :       if (GetPathDataAttrName() == aName) {
    2686           0 :         SVGAnimatedPathSegList *segList = GetAnimPathSegList();
    2687           0 :         if (segList) {
    2688           0 :           return segList->ToSMILAttr(this);
    2689             :         }
    2690             :       }
    2691             :     }
    2692             : 
    2693           0 :     if (aName == nsGkAtoms::_class) {
    2694           0 :       return mClassAttribute.ToSMILAttr(this);
    2695             :     }
    2696             :   }
    2697             : 
    2698             :   // Strings
    2699             :   {
    2700           0 :     StringAttributesInfo info = GetStringInfo();
    2701           0 :     for (uint32_t i = 0; i < info.mStringCount; i++) {
    2702           0 :       if (aNamespaceID == info.mStringInfo[i].mNamespaceID &&
    2703           0 :           aName == *info.mStringInfo[i].mName) {
    2704           0 :         return info.mStrings[i].ToSMILAttr(this);
    2705             :       }
    2706             :     }
    2707             :   }
    2708             : 
    2709           0 :   return nullptr;
    2710             : }
    2711             : 
    2712             : void
    2713          57 : nsSVGElement::AnimationNeedsResample()
    2714             : {
    2715          57 :   nsIDocument* doc = GetComposedDoc();
    2716          57 :   if (doc && doc->HasAnimationController()) {
    2717          57 :     doc->GetAnimationController()->SetResampleNeeded();
    2718             :   }
    2719          57 : }
    2720             : 
    2721             : void
    2722          72 : nsSVGElement::FlushAnimations()
    2723             : {
    2724          72 :   nsIDocument* doc = GetComposedDoc();
    2725          72 :   if (doc && doc->HasAnimationController()) {
    2726          72 :     doc->GetAnimationController()->FlushResampleRequests();
    2727             :   }
    2728          72 : }

Generated by: LCOV version 1.13