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