Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / svg / DOMSVGPoint.cpp
blob1c9dbf45b8de7fbbd3a61665a8604ccaa336d23c
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 MOZ_CONSTINIT static SVGAttrTearoffTable<SVGPoint, DOMSVGPoint>
41 sSVGTranslateTearOffTable;
43 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
44 // clear our list's weak ref to us to be safe. (The other option would be to
45 // not unlink and rely on the breaking of the other edges in the cycle, as
46 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
47 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
49 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
50 tmp->CleanupWeakRefs();
51 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
52 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
53 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPoint)
56 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
59 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPoint)
60 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
61 NS_IMPL_CYCLE_COLLECTION_TRACE_END
63 JSObject* DOMSVGPoint::WrapObject(JSContext* aCx,
64 JS::Handle<JSObject*> aGivenProto) {
65 return SVGPoint_Binding::Wrap(aCx, this, aGivenProto);
68 float DOMSVGPoint::X() {
69 if (mIsAnimValItem && IsInList()) {
70 Element()->FlushAnimations(); // May make IsInList() == false
72 return InternalItem().mX;
75 void DOMSVGPoint::SetX(float aX, ErrorResult& rv) {
76 if (mIsAnimValItem) {
77 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
78 return;
81 auto& val = InternalItem();
83 if (val.mX == aX) {
84 return;
87 AutoChangePointListNotifier listNotifier(this);
88 AutoChangePointNotifier translateNotifier(this);
90 val.mX = aX;
93 float DOMSVGPoint::Y() {
94 if (mIsAnimValItem && IsInList()) {
95 Element()->FlushAnimations(); // May make IsInList() == false
97 return InternalItem().mY;
100 void DOMSVGPoint::SetY(float aY, ErrorResult& rv) {
101 if (mIsAnimValItem) {
102 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
103 return;
105 auto& val = InternalItem();
107 if (val.mY == aY) {
108 return;
111 AutoChangePointListNotifier listNotifier(this);
112 AutoChangePointNotifier translateNotifier(this);
114 val.mY = aY;
117 already_AddRefed<DOMSVGPoint> DOMSVGPoint::MatrixTransform(
118 const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) {
119 RefPtr<DOMMatrixReadOnly> matrix =
120 DOMMatrixReadOnly::FromMatrix(GetParentObject(), aMatrix, aRv);
121 if (aRv.Failed()) {
122 return nullptr;
124 const auto* matrix2D = matrix->GetInternal2D();
125 if (!matrix2D->IsFinite()) {
126 aRv.ThrowTypeError<MSG_NOT_FINITE>("MatrixTransform matrix");
127 return nullptr;
129 auto pt = matrix2D->TransformPoint(InternalItem());
130 return do_AddRef(new DOMSVGPoint(ToPoint(pt)));
133 void DOMSVGPoint::InsertingIntoList(DOMSVGPointList* aList, uint32_t aListIndex,
134 bool aIsAnimValItem) {
135 MOZ_RELEASE_ASSERT(!IsInList(), "Inserting item that is already in a list");
136 MOZ_RELEASE_ASSERT(!mIsTranslatePoint,
137 "Inserting item that is a currentTranslate");
139 delete mVal;
140 mVal = nullptr;
142 mOwner = aList;
143 mListIndex = aListIndex;
144 mIsAnimValItem = aIsAnimValItem;
146 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPoint!");
149 void DOMSVGPoint::RemovingFromList() {
150 MOZ_ASSERT(
151 IsInList(),
152 "We should start in a list if we're going to be removed from one.");
153 mVal = new SVGPoint(InternalItem());
154 mOwner = nullptr;
155 mIsAnimValItem = false;
158 SVGPoint& DOMSVGPoint::InternalItem() {
159 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
160 return pointList->InternalList().mItems[mListIndex];
162 return *mVal;
165 already_AddRefed<DOMSVGPoint> DOMSVGPoint::GetTranslateTearOff(
166 SVGPoint* aVal, SVGSVGElement* aSVGSVGElement) {
167 RefPtr<DOMSVGPoint> domPoint = sSVGTranslateTearOffTable.GetTearoff(aVal);
168 if (!domPoint) {
169 domPoint = new DOMSVGPoint(aVal, aSVGSVGElement);
170 sSVGTranslateTearOffTable.AddTearoff(aVal, domPoint);
173 return domPoint.forget();
176 bool DOMSVGPoint::AttrIsAnimating() const {
177 nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
178 return pointList && pointList->AttrIsAnimating();
181 void DOMSVGPoint::DidChangeTranslate() {
182 nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
183 MOZ_ASSERT(svg);
184 nsContentUtils::AddScriptRunner(
185 NewRunnableMethod("dom::SVGSVGElement::DidChangeTranslate", svg,
186 &SVGSVGElement::DidChangeTranslate));
189 SVGElement* DOMSVGPoint::Element() {
190 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
191 return pointList->Element();
193 nsCOMPtr<SVGSVGElement> svg = do_QueryInterface(mOwner);
194 return svg;
197 void DOMSVGPoint::CleanupWeakRefs() {
198 // Our mList's weak ref to us must be nulled out when we die (or when we're
199 // cycle collected), so we that don't leave behind a pointer to
200 // free / soon-to-be-free memory.
201 if (nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner)) {
202 MOZ_ASSERT(pointList->mItems[mListIndex] == this,
203 "Clearing out the wrong list index...?");
204 pointList->mItems[mListIndex] = nullptr;
207 if (mVal) {
208 if (mIsTranslatePoint) {
209 // Similarly, we must update the tearoff table to remove its (non-owning)
210 // pointer to mVal.
211 sSVGTranslateTearOffTable.RemoveTearoff(mVal);
212 } else {
213 // In this case we own mVal
214 delete mVal;
216 mVal = nullptr;
220 #ifdef DEBUG
221 bool DOMSVGPoint::IndexIsValid() {
222 nsCOMPtr<DOMSVGPointList> pointList = do_QueryInterface(mOwner);
223 return mListIndex < pointList->InternalList().Length();
225 #endif
227 } // namespace mozilla::dom