DOMSVGNumber.cpp (4583B)
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 "DOMSVGNumber.h" 8 9 #include "DOMSVGAnimatedNumberList.h" 10 #include "DOMSVGNumberList.h" 11 #include "SVGAnimatedNumberList.h" 12 #include "SVGElement.h" 13 #include "mozilla/dom/SVGNumberBinding.h" 14 #include "mozilla/dom/SVGSVGElement.h" 15 #include "nsContentUtils.h" // for NS_ENSURE_FINITE 16 #include "nsError.h" 17 18 // See the architecture comment in DOMSVGAnimatedNumberList.h. 19 20 namespace mozilla::dom { 21 22 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to 23 // clear our list's weak ref to us to be safe. (The other option would be to 24 // not unlink and rely on the breaking of the other edges in the cycle, as 25 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.) 26 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumber) 27 28 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumber) 29 // We may not belong to a list, so we must null check tmp->mList. 30 if (tmp->mList) { 31 tmp->mList->mItems[tmp->mListIndex] = nullptr; 32 } 33 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER 34 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList) 35 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent) 36 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber) 38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) 39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) 40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 41 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumber) 42 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER 43 NS_IMPL_CYCLE_COLLECTION_TRACE_END 44 45 DOMSVGNumber::DOMSVGNumber(DOMSVGNumberList* aList, uint8_t aAttrEnum, 46 uint32_t aListIndex, bool aIsAnimValItem) 47 : mList(aList), 48 mParent(aList), 49 mListIndex(aListIndex), 50 mAttrEnum(aAttrEnum), 51 mIsAnimValItem(aIsAnimValItem), 52 mValue(0.0f) { 53 // These shifts are in sync with the members in the header. 54 MOZ_ASSERT(aList && aAttrEnum < (1 << 4) && aListIndex <= MaxListIndex(), 55 "bad arg"); 56 57 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!"); 58 } 59 60 DOMSVGNumber::DOMSVGNumber(nsISupports* aParent) 61 : mList(nullptr), 62 mParent(aParent), 63 mListIndex(0), 64 mAttrEnum(0), 65 mIsAnimValItem(false), 66 mValue(0.0f) {} 67 68 DOMSVGNumber::DOMSVGNumber(SVGSVGElement* aParent) 69 : mList(nullptr), 70 mParent(ToSupports(aParent)), 71 mListIndex(0), 72 mAttrEnum(0), 73 mIsAnimValItem(false), 74 mValue(0.0f) {} 75 76 float DOMSVGNumber::Value() { 77 if (mIsAnimValItem && HasOwner()) { 78 Element()->FlushAnimations(); // May make HasOwner() == false 79 } 80 return HasOwner() ? InternalItem() : mValue; 81 } 82 83 void DOMSVGNumber::SetValue(float aValue, ErrorResult& aRv) { 84 if (mIsAnimValItem) { 85 aRv.ThrowNoModificationAllowedError("Animated values cannot be set"); 86 return; 87 } 88 89 if (HasOwner()) { 90 if (InternalItem() == aValue) { 91 return; 92 } 93 AutoChangeNumberListNotifier notifier(this); 94 InternalItem() = aValue; 95 return; 96 } 97 98 mValue = aValue; 99 } 100 101 void DOMSVGNumber::InsertingIntoList(DOMSVGNumberList* aList, uint8_t aAttrEnum, 102 uint32_t aListIndex, bool aIsAnimValItem) { 103 NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list"); 104 105 mList = aList; 106 mAttrEnum = aAttrEnum; 107 mListIndex = aListIndex; 108 mIsAnimValItem = aIsAnimValItem; 109 110 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!"); 111 } 112 113 void DOMSVGNumber::RemovingFromList() { 114 mValue = InternalItem(); 115 mList = nullptr; 116 mIsAnimValItem = false; 117 } 118 119 float DOMSVGNumber::ToSVGNumber() { 120 return HasOwner() ? InternalItem() : mValue; 121 } 122 123 float& DOMSVGNumber::InternalItem() { 124 SVGAnimatedNumberList* alist = Element()->GetAnimatedNumberList(mAttrEnum); 125 return mIsAnimValItem && alist->mAnimVal ? (*alist->mAnimVal)[mListIndex] 126 : alist->mBaseVal[mListIndex]; 127 } 128 129 #ifdef DEBUG 130 bool DOMSVGNumber::IndexIsValid() { 131 SVGAnimatedNumberList* alist = Element()->GetAnimatedNumberList(mAttrEnum); 132 return (mIsAnimValItem && mListIndex < alist->GetAnimValue().Length()) || 133 (!mIsAnimValItem && mListIndex < alist->GetBaseValue().Length()); 134 } 135 #endif 136 137 JSObject* DOMSVGNumber::WrapObject(JSContext* aCx, 138 JS::Handle<JSObject*> aGivenProto) { 139 return SVGNumber_Binding::Wrap(aCx, this, aGivenProto); 140 } 141 142 } // namespace mozilla::dom