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

Generated by: LCOV version 1.13-14-ga5dd952