Bug 1889091 - Part 6: Remove "scratch" register parameter from emitPushArguments...
[gecko.git] / dom / svg / DOMSVGPoint.cpp
blob465f4e28a55ba07dce0964c1cc93fa7885cc5a5e
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/. */
7 #include "DOMSVGPoint.h"
9 #include "DOMSVGPointList.h"
10 #include "gfx2DGlue.h"
11 #include "nsError.h"
12 #include "mozilla/dom/DOMMatrix.h"
13 #include "mozilla/dom/SVGPointBinding.h"
15 // See the architecture comment in DOMSVGPointList.h.
17 using namespace mozilla::gfx;
19 namespace mozilla::dom {
21 //----------------------------------------------------------------------
22 // Helper class: AutoChangePointNotifier
24 class MOZ_RAII AutoChangePointNotifier {
25 public:
26 explicit AutoChangePointNotifier(DOMSVGPoint* aValue) : mValue(aValue) {
27 MOZ_ASSERT(mValue, "Expecting non-null value");
30 ~AutoChangePointNotifier() {
31 if (mValue->IsTranslatePoint()) {
32 mValue->DidChangeTranslate();
36 private:
37 DOMSVGPoint* const mValue;
40 static SVGAttrTearoffTable<SVGPoint, DOMSVGPoint> sSVGTranslateTearOffTable;
42 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
43 // clear our list's weak ref to us to be safe. (The other option would be to
44 // not unlink and rely on the breaking of the other edges in the cycle, as
45 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
46 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
49 tmp->CleanupWeakRefs();
50 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
51 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
52 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
54 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPoint)
55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
56 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
58 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPoint)
59 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
60 NS_IMPL_CYCLE_COLLECTION_TRACE_END
62 JSObject* DOMSVGPoint::WrapObject(JSContext* aCx,
63 JS::Handle<JSObject*> aGivenProto) {
64 return SVGPoint_Binding::Wrap(aCx, this, aGivenProto);
67 float DOMSVGPoint::X() {
68 if (mIsAnimValItem && IsInList()) {
69 Element()->FlushAnimations(); // May make IsInList() == false
71 return InternalItem().mX;
74 void DOMSVGPoint::SetX(float aX, ErrorResult& rv) {
75 if (mIsAnimValItem) {
76 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
77 return;
80 auto& val = InternalItem();
82 if (val.mX == aX) {
83 return;
86 AutoChangePointListNotifier listNotifier(this);
87 AutoChangePointNotifier translateNotifier(this);
89 val.mX = aX;
92 float DOMSVGPoint::Y() {
93 if (mIsAnimValItem && IsInList()) {
94 Element()->FlushAnimations(); // May make IsInList() == false
96 return InternalItem().mY;
99 void DOMSVGPoint::SetY(float aY, ErrorResult& rv) {
100 if (mIsAnimValItem) {
101 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
102 return;
104 auto& val = InternalItem();
106 if (val.mY == aY) {
107 return;
110 AutoChangePointListNotifier listNotifier(this);
111 AutoChangePointNotifier translateNotifier(this);
113 val.mY = aY;
116 already_AddRefed<DOMSVGPoint> DOMSVGPoint::MatrixTransform(
117 const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) {
118 RefPtr<DOMMatrixReadOnly> matrix =
119 DOMMatrixReadOnly::FromMatrix(GetParentObject(), aMatrix, aRv);
120 if (aRv.Failed()) {
121 return nullptr;
123 const auto* matrix2D = matrix->GetInternal2D();
124 if (!matrix2D->IsFinite()) {
125 aRv.ThrowTypeError<MSG_NOT_FINITE>("MatrixTransform matrix");
126 return nullptr;
128 auto pt = matrix2D->TransformPoint(InternalItem());
129 return do_AddRef(new DOMSVGPoint(ToPoint(pt)));
132 void DOMSVGPoint::InsertingIntoList(DOMSVGPointList* aList, uint32_t aListIndex,
133 bool aIsAnimValItem) {
134 MOZ_RELEASE_ASSERT(!IsInList(), "Inserting item that is already in a list");
135 MOZ_RELEASE_ASSERT(!mIsTranslatePoint,
136 "Inserting item that is a currentTranslate");
138 delete mVal;
139 mVal = nullptr;
141 mOwner = aList;
142 mListIndex = aListIndex;
143 mIsAnimValItem = aIsAnimValItem;
145 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPoint!");
148 void DOMSVGPoint::RemovingFromList() {
149 MOZ_ASSERT(
150 IsInList(),
151 "We should start in a list if we're going to be removed from one.");
152 mVal = new SVGPoint(InternalItem());
153 mOwner = nullptr;
154 mIsAnimValItem = false;
157 SVGPoint& DOMSVGPoint::InternalItem() {
158 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
159 return pointList->InternalList().mItems[mListIndex];
161 return *mVal;
164 already_AddRefed<DOMSVGPoint> DOMSVGPoint::GetTranslateTearOff(
165 SVGPoint* aVal, SVGSVGElement* aSVGSVGElement) {
166 RefPtr<DOMSVGPoint> domPoint = sSVGTranslateTearOffTable.GetTearoff(aVal);
167 if (!domPoint) {
168 domPoint = new DOMSVGPoint(aVal, aSVGSVGElement);
169 sSVGTranslateTearOffTable.AddTearoff(aVal, domPoint);
172 return domPoint.forget();
175 bool DOMSVGPoint::AttrIsAnimating() const {
176 nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
177 return pointList && pointList->AttrIsAnimating();
180 void DOMSVGPoint::DidChangeTranslate() {
181 nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
182 MOZ_ASSERT(svg);
183 nsContentUtils::AddScriptRunner(
184 NewRunnableMethod("dom::SVGSVGElement::DidChangeTranslate", svg,
185 &SVGSVGElement::DidChangeTranslate));
188 SVGElement* DOMSVGPoint::Element() {
189 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
190 return pointList->Element();
192 nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
193 return svg;
196 void DOMSVGPoint::CleanupWeakRefs() {
197 // Our mList's weak ref to us must be nulled out when we die (or when we're
198 // cycle collected), so we that don't leave behind a pointer to
199 // free / soon-to-be-free memory.
200 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
201 MOZ_ASSERT(pointList->mItems[mListIndex] == this,
202 "Clearing out the wrong list index...?");
203 pointList->mItems[mListIndex] = nullptr;
206 if (mVal) {
207 if (mIsTranslatePoint) {
208 // Similarly, we must update the tearoff table to remove its (non-owning)
209 // pointer to mVal.
210 sSVGTranslateTearOffTable.RemoveTearoff(mVal);
211 } else {
212 // In this case we own mVal
213 delete mVal;
215 mVal = nullptr;
219 #ifdef DEBUG
220 bool DOMSVGPoint::IndexIsValid() {
221 nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
222 return mListIndex < pointList->InternalList().Length();
224 #endif
226 } // namespace mozilla::dom