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 #ifndef DOM_SVG_SVGELEMENT_H_
8 #define DOM_SVG_SVGELEMENT_H_
9 
10 /*
11   SVGElement is the base class for all SVG content elements.
12   It implements all the common DOM interfaces and handles attributes.
13 */
14 
15 #include "mozilla/Attributes.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/SVGAnimatedClass.h"
18 #include "mozilla/SVGContentUtils.h"
19 #include "mozilla/dom/DOMRect.h"
20 #include "mozilla/dom/Element.h"
21 #include "mozilla/gfx/MatrixFwd.h"
22 #include "mozilla/UniquePtr.h"
23 #include "nsCSSPropertyID.h"
24 #include "nsChangeHint.h"
25 #include "nsCycleCollectionParticipant.h"
26 #include "nsError.h"
27 #include "nsISupportsImpl.h"
28 #include "nsStyledElement.h"
29 #include "gfxMatrix.h"
30 
31 // {70db954d-e452-4be3-83aa-f54a51cf7890}
32 #define MOZILLA_SVGELEMENT_IID                       \
33   {                                                  \
34     0x70db954d, 0xe452, 0x4be3, {                    \
35       0x82, 0xaa, 0xf5, 0x4a, 0x51, 0xcf, 0x78, 0x90 \
36     }                                                \
37   }
38 
39 nsresult NS_NewSVGElement(mozilla::dom::Element** aResult,
40                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
41 
42 class mozAutoDocUpdate;
43 
44 namespace mozilla {
45 class DeclarationBlock;
46 
47 class SVGAnimatedBoolean;
48 class SVGAnimatedEnumeration;
49 class SVGAnimatedInteger;
50 class SVGAnimatedIntegerPair;
51 class SVGAnimatedLength;
52 class SVGAnimatedLengthList;
53 class SVGAnimatedNumber;
54 class SVGAnimatedNumberList;
55 class SVGAnimatedNumberPair;
56 class SVGAnimatedOrient;
57 class SVGAnimatedPathSegList;
58 class SVGAnimatedPointList;
59 class SVGAnimatedString;
60 class SVGAnimatedPreserveAspectRatio;
61 class SVGAnimatedTransformList;
62 class SVGAnimatedViewBox;
63 class SVGNumberList;
64 class SVGStringList;
65 class SVGUserUnitList;
66 
67 struct SVGEnumMapping;
68 
69 namespace dom {
70 class DOMSVGStringList;
71 class SVGSVGElement;
72 class SVGViewportElement;
73 
74 using SVGElementBase = nsStyledElement;
75 
76 class SVGElement : public SVGElementBase  // nsIContent
77 {
78  protected:
79   explicit SVGElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
80   friend nsresult(
81       ::NS_NewSVGElement(mozilla::dom::Element** aResult,
82                          already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
83   nsresult Init();
84   virtual ~SVGElement();
85 
86  public:
87   virtual nsresult Clone(mozilla::dom::NodeInfo*,
88                          nsINode** aResult) const MOZ_MUST_OVERRIDE override;
89 
90   // From Element
91   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
92 
93   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_SVGELEMENT_IID)
94   // nsISupports
95   NS_INLINE_DECL_REFCOUNTING_INHERITED(SVGElement, SVGElementBase)
96 
97   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
98 
99   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
100 
101   void DidAnimateClass();
102 
SetNonce(const nsAString & aNonce)103   void SetNonce(const nsAString& aNonce) {
104     SetProperty(nsGkAtoms::nonce, new nsString(aNonce),
105                 nsINode::DeleteProperty<nsString>);
106   }
RemoveNonce()107   void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); }
GetNonce(nsAString & aNonce)108   void GetNonce(nsAString& aNonce) const {
109     nsString* cspNonce = static_cast<nsString*>(GetProperty(nsGkAtoms::nonce));
110     if (cspNonce) {
111       aNonce = *cspNonce;
112     }
113   }
114 
115   // nsIContent interface methods
116 
117   virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
118 
119   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
120                                               int32_t aModType) const override;
121 
122   virtual bool IsNodeOfType(uint32_t aFlags) const override;
IsSVGGraphicsElement()123   virtual bool IsSVGGraphicsElement() const { return false; }
124 
125   /**
126    * We override the default to unschedule computation of Servo declaration
127    * blocks when adopted across documents.
128    */
129   virtual void NodeInfoChanged(Document* aOldDoc) override;
130 
131   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
132 
133   static const MappedAttributeEntry sFillStrokeMap[];
134   static const MappedAttributeEntry sGraphicsMap[];
135   static const MappedAttributeEntry sTextContentElementsMap[];
136   static const MappedAttributeEntry sFontSpecificationMap[];
137   static const MappedAttributeEntry sGradientStopMap[];
138   static const MappedAttributeEntry sViewportsMap[];
139   static const MappedAttributeEntry sMarkersMap[];
140   static const MappedAttributeEntry sColorMap[];
141   static const MappedAttributeEntry sFiltersMap[];
142   static const MappedAttributeEntry sFEFloodMap[];
143   static const MappedAttributeEntry sLightingEffectsMap[];
144   static const MappedAttributeEntry sMaskMap[];
145 
146   NS_IMPL_FROMNODE(SVGElement, kNameSpaceID_SVG)
147 
148   // Gets the element that establishes the rectangular viewport against which
149   // we should resolve percentage lengths (our "coordinate context"). Returns
150   // nullptr for outer <svg> or SVG without an <svg> parent (invalid SVG).
151   mozilla::dom::SVGViewportElement* GetCtx() const;
152 
153   /**
154    * Returns aMatrix pre-multiplied by (explicit or implicit) transforms that
155    * are introduced by attributes on this element.
156    *
157    * If aWhich is eAllTransforms, then all the transforms from the coordinate
158    * space established by this element for its children to the coordinate
159    * space established by this element's parent element for this element, are
160    * included.
161    *
162    * If aWhich is eUserSpaceToParent, then only the transforms from this
163    * element's userspace to the coordinate space established by its parent is
164    * included. This includes any transforms introduced by the 'transform'
165    * attribute, transform animations and animateMotion, but not any offsets
166    * due to e.g. 'x'/'y' attributes, or any transform due to a 'viewBox'
167    * attribute. (SVG userspace is defined to be the coordinate space in which
168    * coordinates on an element apply.)
169    *
170    * If aWhich is eChildToUserSpace, then only the transforms from the
171    * coordinate space established by this element for its childre to this
172    * elements userspace are included. This includes any offsets due to e.g.
173    * 'x'/'y' attributes, and any transform due to a 'viewBox' attribute, but
174    * does not include any transforms due to the 'transform' attribute.
175    */
176   virtual gfxMatrix PrependLocalTransformsTo(
177       const gfxMatrix& aMatrix,
178       SVGTransformTypes aWhich = eAllTransforms) const;
179 
180   // Setter for to set the current <animateMotion> transformation
181   // Only visible for SVGGraphicElement, so it's a no-op here, and that
182   // subclass has the useful implementation.
SetAnimateMotionTransform(const mozilla::gfx::Matrix * aMatrix)183   virtual void SetAnimateMotionTransform(
184       const mozilla::gfx::Matrix* aMatrix) { /*no-op*/
185   }
GetAnimateMotionTransform()186   virtual const mozilla::gfx::Matrix* GetAnimateMotionTransform() const {
187     return nullptr;
188   }
189 
IsStringAnimatable(uint8_t aAttrEnum)190   bool IsStringAnimatable(uint8_t aAttrEnum) {
191     return GetStringInfo().mInfos[aAttrEnum].mIsAnimatable;
192   }
NumberAttrAllowsPercentage(uint8_t aAttrEnum)193   bool NumberAttrAllowsPercentage(uint8_t aAttrEnum) {
194     return GetNumberInfo().mInfos[aAttrEnum].mPercentagesAllowed;
195   }
HasValidDimensions()196   virtual bool HasValidDimensions() const { return true; }
197   void SetLength(nsAtom* aName, const SVGAnimatedLength& aLength);
198 
199   enum class ValToUse { Base, Anim };
200   static bool UpdateDeclarationBlockFromLength(DeclarationBlock& aBlock,
201                                                nsCSSPropertyID aPropId,
202                                                const SVGAnimatedLength& aLength,
203                                                ValToUse aValToUse);
204   static bool UpdateDeclarationBlockFromPath(
205       DeclarationBlock& aBlock, const SVGAnimatedPathSegList& aPath,
206       ValToUse aValToUse);
207 
208   nsAttrValue WillChangeLength(uint8_t aAttrEnum,
209                                const mozAutoDocUpdate& aProofOfUpdate);
210   nsAttrValue WillChangeNumberPair(uint8_t aAttrEnum);
211   nsAttrValue WillChangeIntegerPair(uint8_t aAttrEnum,
212                                     const mozAutoDocUpdate& aProofOfUpdate);
213   nsAttrValue WillChangeOrient(const mozAutoDocUpdate& aProofOfUpdate);
214   nsAttrValue WillChangeViewBox(const mozAutoDocUpdate& aProofOfUpdate);
215   nsAttrValue WillChangePreserveAspectRatio(
216       const mozAutoDocUpdate& aProofOfUpdate);
217   nsAttrValue WillChangeNumberList(uint8_t aAttrEnum,
218                                    const mozAutoDocUpdate& aProofOfUpdate);
219   nsAttrValue WillChangeLengthList(uint8_t aAttrEnum,
220                                    const mozAutoDocUpdate& aProofOfUpdate);
221   nsAttrValue WillChangePointList(const mozAutoDocUpdate& aProofOfUpdate);
222   nsAttrValue WillChangePathSegList(const mozAutoDocUpdate& aProofOfUpdate);
223   nsAttrValue WillChangeTransformList(const mozAutoDocUpdate& aProofOfUpdate);
224   nsAttrValue WillChangeStringList(bool aIsConditionalProcessingAttribute,
225                                    uint8_t aAttrEnum,
226                                    const mozAutoDocUpdate& aProofOfUpdate);
227 
228   void DidChangeLength(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue,
229                        const mozAutoDocUpdate& aProofOfUpdate);
230   void DidChangeNumber(uint8_t aAttrEnum);
231   void DidChangeNumberPair(uint8_t aAttrEnum,
232                            const nsAttrValue& aEmptyOrOldValue);
233   void DidChangeInteger(uint8_t aAttrEnum);
234   void DidChangeIntegerPair(uint8_t aAttrEnum,
235                             const nsAttrValue& aEmptyOrOldValue,
236                             const mozAutoDocUpdate& aProofOfUpdate);
237   void DidChangeBoolean(uint8_t aAttrEnum);
238   void DidChangeEnum(uint8_t aAttrEnum);
239   void DidChangeOrient(const nsAttrValue& aEmptyOrOldValue,
240                        const mozAutoDocUpdate& aProofOfUpdate);
241   void DidChangeViewBox(const nsAttrValue& aEmptyOrOldValue,
242                         const mozAutoDocUpdate& aProofOfUpdate);
243   void DidChangePreserveAspectRatio(const nsAttrValue& aEmptyOrOldValue,
244                                     const mozAutoDocUpdate& aProofOfUpdate);
245   void DidChangeNumberList(uint8_t aAttrEnum,
246                            const nsAttrValue& aEmptyOrOldValue,
247                            const mozAutoDocUpdate& aProofOfUpdate);
248   void DidChangeLengthList(uint8_t aAttrEnum,
249                            const nsAttrValue& aEmptyOrOldValue,
250                            const mozAutoDocUpdate& aProofOfUpdate);
251   void DidChangePointList(const nsAttrValue& aEmptyOrOldValue,
252                           const mozAutoDocUpdate& aProofOfUpdate);
253   void DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue,
254                             const mozAutoDocUpdate& aProofOfUpdate);
255   void DidChangeTransformList(const nsAttrValue& aEmptyOrOldValue,
256                               const mozAutoDocUpdate& aProofOfUpdate);
DidChangeString(uint8_t aAttrEnum)257   void DidChangeString(uint8_t aAttrEnum) {}
258   void DidChangeStringList(bool aIsConditionalProcessingAttribute,
259                            uint8_t aAttrEnum,
260                            const nsAttrValue& aEmptyOrOldValue,
261                            const mozAutoDocUpdate& aProofOfUpdate);
262 
263   void DidAnimateLength(uint8_t aAttrEnum);
264   void DidAnimateNumber(uint8_t aAttrEnum);
265   void DidAnimateNumberPair(uint8_t aAttrEnum);
266   void DidAnimateInteger(uint8_t aAttrEnum);
267   void DidAnimateIntegerPair(uint8_t aAttrEnum);
268   void DidAnimateBoolean(uint8_t aAttrEnum);
269   void DidAnimateEnum(uint8_t aAttrEnum);
270   void DidAnimateOrient();
271   void DidAnimateViewBox();
272   void DidAnimatePreserveAspectRatio();
273   void DidAnimateNumberList(uint8_t aAttrEnum);
274   void DidAnimateLengthList(uint8_t aAttrEnum);
275   void DidAnimatePointList();
276   void DidAnimatePathSegList();
277   void DidAnimateTransformList(int32_t aModType);
278   void DidAnimateString(uint8_t aAttrEnum);
279 
280   enum {
281     /**
282      * Flag to indicate to GetAnimatedXxx() methods that the object being
283      * requested should be allocated if it hasn't already been allocated, and
284      * that the method should not return null. Only applicable to methods that
285      * need to allocate the object that they return.
286      */
287     DO_ALLOCATE = 0x1
288   };
289 
290   SVGAnimatedLength* GetAnimatedLength(uint8_t aAttrEnum);
291   SVGAnimatedLength* GetAnimatedLength(const nsAtom* aAttrName);
292   void GetAnimatedLengthValues(float* aFirst, ...);
293   void GetAnimatedNumberValues(float* aFirst, ...);
294   void GetAnimatedIntegerValues(int32_t* aFirst, ...);
295   SVGAnimatedNumberList* GetAnimatedNumberList(uint8_t aAttrEnum);
296   SVGAnimatedNumberList* GetAnimatedNumberList(nsAtom* aAttrName);
297   void GetAnimatedLengthListValues(SVGUserUnitList* aFirst, ...);
298   SVGAnimatedLengthList* GetAnimatedLengthList(uint8_t aAttrEnum);
GetAnimatedPointList()299   virtual SVGAnimatedPointList* GetAnimatedPointList() { return nullptr; }
GetAnimPathSegList()300   virtual SVGAnimatedPathSegList* GetAnimPathSegList() {
301     // DOM interface 'SVGAnimatedPathData' (*inherited* by SVGPathElement)
302     // has a member called 'animatedPathSegList' member, so we have a shorter
303     // name so we don't get hidden by the GetAnimatedPathSegList declared by
304     // NS_DECL_NSIDOMSVGANIMATEDPATHDATA.
305     return nullptr;
306   }
307   /**
308    * Get the SVGAnimatedTransformList for this element.
309    *
310    * Despite the fact that animated transform lists are used for a variety of
311    * attributes, no SVG element uses more than one.
312    *
313    * It's relatively uncommon for elements to have their transform attribute
314    * set, so to save memory the SVGAnimatedTransformList is not allocated
315    * until the attribute is set/animated or its DOM wrapper is created. Callers
316    * that require the SVGAnimatedTransformList to be allocated and for this
317    * method to return non-null must pass the DO_ALLOCATE flag.
318    */
319   virtual SVGAnimatedTransformList* GetAnimatedTransformList(
320       uint32_t aFlags = 0) {
321     return nullptr;
322   }
323 
324   mozilla::UniquePtr<SMILAttr> GetAnimatedAttr(int32_t aNamespaceID,
325                                                nsAtom* aName) override;
326   void AnimationNeedsResample();
327   void FlushAnimations();
328 
329   void GetStringBaseValue(uint8_t aAttrEnum, nsAString& aResult) const;
330   void SetStringBaseValue(uint8_t aAttrEnum, const nsAString& aValue);
331 
GetPointListAttrName()332   virtual nsStaticAtom* GetPointListAttrName() const { return nullptr; }
GetPathDataAttrName()333   virtual nsStaticAtom* GetPathDataAttrName() const { return nullptr; }
GetTransformListAttrName()334   virtual nsStaticAtom* GetTransformListAttrName() const { return nullptr; }
GetAnimatedClassName()335   const nsAttrValue* GetAnimatedClassName() const {
336     if (!mClassAttribute.IsAnimated()) {
337       return nullptr;
338     }
339     return mClassAnimAttr.get();
340   }
341 
ClearAnyCachedPath()342   virtual void ClearAnyCachedPath() {}
IsTransformable()343   virtual bool IsTransformable() { return false; }
344 
345   // WebIDL
346   mozilla::dom::SVGSVGElement* GetOwnerSVGElement();
347   SVGElement* GetViewportElement();
348   already_AddRefed<mozilla::dom::DOMSVGAnimatedString> ClassName();
349 
350   void UpdateContentDeclarationBlock();
351   const mozilla::DeclarationBlock* GetContentDeclarationBlock() const;
352 
353  protected:
354   virtual JSObject* WrapNode(JSContext* cx,
355                              JS::Handle<JSObject*> aGivenProto) override;
356 
357   // We define BeforeSetAttr here and mark it final to ensure it is NOT used
358   // by SVG elements.
359   // This is because we're not currently passing the correct value for aValue to
360   // BeforeSetAttr since it would involve allocating extra SVG value types.
361   // See the comment in SVGElement::WillChangeValue.
362   nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
363                          const nsAttrValueOrString* aValue, bool aNotify) final;
364   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
365                                 const nsAttrValue* aValue,
366                                 const nsAttrValue* aOldValue,
367                                 nsIPrincipal* aSubjectPrincipal,
368                                 bool aNotify) override;
369   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
370                               const nsAString& aValue,
371                               nsIPrincipal* aMaybeScriptedPrincipal,
372                               nsAttrValue& aResult) override;
373   static nsresult ReportAttributeParseFailure(Document* aDocument,
374                                               nsAtom* aAttribute,
375                                               const nsAString& aValue);
376 
377   nsAttrValue WillChangeValue(nsAtom* aName,
378                               const mozAutoDocUpdate& aProofOfUpdate);
379   // aNewValue is set to the old value. This value may be invalid if
380   // !StoresOwnData.
381   void DidChangeValue(nsAtom* aName, const nsAttrValue& aEmptyOrOldValue,
382                       nsAttrValue& aNewValue,
383                       const mozAutoDocUpdate& aProofOfUpdate);
384   void MaybeSerializeAttrBeforeRemoval(nsAtom* aName, bool aNotify);
385 
386   nsAtom* GetEventNameForAttr(nsAtom* aAttr) override;
387 
388   struct LengthInfo {
389     nsStaticAtom* const mName;
390     const float mDefaultValue;
391     const uint8_t mDefaultUnitType;
392     const uint8_t mCtxType;
393   };
394 
395   template <typename Value, typename InfoValue>
396   struct AttributesInfo {
397     Value* const mValues;
398     const InfoValue* const mInfos;
399     const uint32_t mCount;
400 
AttributesInfoAttributesInfo401     AttributesInfo(Value* aValues, const InfoValue* aInfos, uint32_t aCount)
402         : mValues(aValues), mInfos(aInfos), mCount(aCount) {}
403 
404     void CopyAllFrom(const AttributesInfo&);
405     void ResetAll();
406     void Reset(uint8_t aEnum);
407   };
408 
409   using LengthAttributesInfo = AttributesInfo<SVGAnimatedLength, LengthInfo>;
410 
411   struct NumberInfo {
412     nsStaticAtom* const mName;
413     const float mDefaultValue;
414     const bool mPercentagesAllowed;
415   };
416 
417   using NumberAttributesInfo = AttributesInfo<SVGAnimatedNumber, NumberInfo>;
418 
419   struct NumberPairInfo {
420     nsStaticAtom* const mName;
421     const float mDefaultValue1;
422     const float mDefaultValue2;
423   };
424 
425   using NumberPairAttributesInfo =
426       AttributesInfo<SVGAnimatedNumberPair, NumberPairInfo>;
427 
428   struct IntegerInfo {
429     nsStaticAtom* const mName;
430     const int32_t mDefaultValue;
431   };
432 
433   using IntegerAttributesInfo = AttributesInfo<SVGAnimatedInteger, IntegerInfo>;
434 
435   struct IntegerPairInfo {
436     nsStaticAtom* const mName;
437     const int32_t mDefaultValue1;
438     const int32_t mDefaultValue2;
439   };
440 
441   using IntegerPairAttributesInfo =
442       AttributesInfo<SVGAnimatedIntegerPair, IntegerPairInfo>;
443 
444   struct BooleanInfo {
445     nsStaticAtom* const mName;
446     const bool mDefaultValue;
447   };
448 
449   using BooleanAttributesInfo = AttributesInfo<SVGAnimatedBoolean, BooleanInfo>;
450 
451   friend class mozilla::SVGAnimatedEnumeration;
452 
453   struct EnumInfo {
454     nsStaticAtom* const mName;
455     const SVGEnumMapping* const mMapping;
456     const uint16_t mDefaultValue;
457   };
458 
459   using EnumAttributesInfo = AttributesInfo<SVGAnimatedEnumeration, EnumInfo>;
460 
461   struct NumberListInfo {
462     nsStaticAtom* const mName;
463   };
464 
465   using NumberListAttributesInfo =
466       AttributesInfo<SVGAnimatedNumberList, NumberListInfo>;
467 
468   struct LengthListInfo {
469     nsStaticAtom* const mName;
470     const uint8_t mAxis;
471     /**
472      * Flag to indicate whether appending zeros to the end of the list would
473      * change the rendering of the SVG for the attribute in question. For x and
474      * y on the <text> element this is true, but for dx and dy on <text> this
475      * is false. This flag is fed down to SVGLengthListSMILType so it can
476      * determine if it can sensibly animate from-to lists of different lengths,
477      * which is desirable in the case of dx and dy.
478      */
479     const bool mCouldZeroPadList;
480   };
481 
482   using LengthListAttributesInfo =
483       AttributesInfo<SVGAnimatedLengthList, LengthListInfo>;
484 
485   struct StringInfo {
486     nsStaticAtom* const mName;
487     const int32_t mNamespaceID;
488     const bool mIsAnimatable;
489   };
490 
491   using StringAttributesInfo = AttributesInfo<SVGAnimatedString, StringInfo>;
492 
493   friend class DOMSVGStringList;
494 
495   struct StringListInfo {
496     nsStaticAtom* const mName;
497   };
498 
499   using StringListAttributesInfo =
500       AttributesInfo<SVGStringList, StringListInfo>;
501 
502   virtual LengthAttributesInfo GetLengthInfo();
503   virtual NumberAttributesInfo GetNumberInfo();
504   virtual NumberPairAttributesInfo GetNumberPairInfo();
505   virtual IntegerAttributesInfo GetIntegerInfo();
506   virtual IntegerPairAttributesInfo GetIntegerPairInfo();
507   virtual BooleanAttributesInfo GetBooleanInfo();
508   virtual EnumAttributesInfo GetEnumInfo();
509   // We assume all orients, viewboxes and preserveAspectRatios are alike
510   // so we don't need to wrap the class
511   virtual SVGAnimatedOrient* GetAnimatedOrient();
512   virtual SVGAnimatedPreserveAspectRatio* GetAnimatedPreserveAspectRatio();
513   virtual SVGAnimatedViewBox* GetAnimatedViewBox();
514   virtual NumberListAttributesInfo GetNumberListInfo();
515   virtual LengthListAttributesInfo GetLengthListInfo();
516   virtual StringAttributesInfo GetStringInfo();
517   virtual StringListAttributesInfo GetStringListInfo();
518 
519   static SVGEnumMapping sSVGUnitTypesMap[];
520 
521  private:
522   void UnsetAttrInternal(int32_t aNameSpaceID, nsAtom* aName, bool aNotify);
523 
524   SVGAnimatedClass mClassAttribute;
525   UniquePtr<nsAttrValue> mClassAnimAttr;
526   RefPtr<mozilla::DeclarationBlock> mContentDeclarationBlock;
527 };
528 
529 NS_DEFINE_STATIC_IID_ACCESSOR(SVGElement, MOZILLA_SVGELEMENT_IID)
530 
531 /**
532  * A macro to implement the NS_NewSVGXXXElement() functions.
533  */
534 #define NS_IMPL_NS_NEW_SVG_ELEMENT(_elementName)                               \
535   nsresult NS_NewSVG##_elementName##Element(                                   \
536       nsIContent** aResult,                                                    \
537       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) {                  \
538     RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);                        \
539     auto* nim = nodeInfo->NodeInfoManager();                                   \
540     RefPtr<mozilla::dom::SVG##_elementName##Element> it =                      \
541         new (nim) mozilla::dom::SVG##_elementName##Element(nodeInfo.forget()); \
542                                                                                \
543     nsresult rv = it->Init();                                                  \
544                                                                                \
545     if (NS_FAILED(rv)) {                                                       \
546       return rv;                                                               \
547     }                                                                          \
548                                                                                \
549     it.forget(aResult);                                                        \
550                                                                                \
551     return rv;                                                                 \
552   }
553 
554 #define NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(_elementName)                 \
555   nsresult NS_NewSVG##_elementName##Element(                                  \
556       nsIContent** aResult,                                                   \
557       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,                   \
558       mozilla::dom::FromParser aFromParser) {                                 \
559     RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);                       \
560     auto* nim = nodeInfo->NodeInfoManager();                                  \
561     RefPtr<mozilla::dom::SVG##_elementName##Element> it =                     \
562         new (nim) mozilla::dom::SVG##_elementName##Element(nodeInfo.forget(), \
563                                                            aFromParser);      \
564                                                                               \
565     nsresult rv = it->Init();                                                 \
566                                                                               \
567     if (NS_FAILED(rv)) {                                                      \
568       return rv;                                                              \
569     }                                                                         \
570                                                                               \
571     it.forget(aResult);                                                       \
572                                                                               \
573     return rv;                                                                \
574   }
575 
576 // No unlinking, we'd need to null out the value pointer (the object it
577 // points to is held by the element) and null-check it everywhere.
578 #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION(_val, _element) \
579   NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                   \
580   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)          \
581     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element)          \
582   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                  \
583   NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_val)
584 
585 #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(_val, _element) \
586   NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                                 \
587   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_val)                          \
588     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER                  \
589   NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                  \
590   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)                        \
591     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element)                        \
592   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                \
593   NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_val)                           \
594     NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER                   \
595   NS_IMPL_CYCLE_COLLECTION_TRACE_END
596 
597 }  // namespace dom
598 }  // namespace mozilla
599 
600 #endif  // DOM_SVG_SVGELEMENT_H_
601