Bug 1867190 - Initialise the PHC allocate delay later r=glandium
[gecko.git] / dom / svg / DOMSVGPathSeg.cpp
blobc39f624c93b9f12a664fe83401003fff2d73f664
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 "DOMSVGPathSeg.h"
8 #include "DOMSVGPathSegList.h"
9 #include "SVGAnimatedPathSegList.h"
10 #include "SVGElement.h"
11 #include "mozAutoDocUpdate.h"
12 #include "nsError.h"
14 // See the architecture comment in DOMSVGPathSegList.h.
16 namespace mozilla::dom {
18 using namespace dom::SVGPathSeg_Binding;
20 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
21 // clear our list's weak ref to us to be safe. (The other option would be to
22 // not unlink and rely on the breaking of the other edges in the cycle, as
23 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
24 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSeg)
26 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSeg)
27 // We may not belong to a list, so we must null check tmp->mList.
28 if (tmp->mList) {
29 tmp->mList->ItemAt(tmp->mListIndex) = nullptr;
31 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSeg)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
39 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSeg)
40 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
41 NS_IMPL_CYCLE_COLLECTION_TRACE_END
43 DOMSVGPathSeg::DOMSVGPathSeg(DOMSVGPathSegList* aList, uint32_t aListIndex,
44 bool aIsAnimValItem)
45 : mList(aList), mListIndex(aListIndex), mIsAnimValItem(aIsAnimValItem) {
46 // These shifts are in sync with the members in the header.
47 MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
49 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
52 DOMSVGPathSeg::DOMSVGPathSeg()
53 : mList(nullptr), mListIndex(0), mIsAnimValItem(false) {}
55 void DOMSVGPathSeg::InsertingIntoList(DOMSVGPathSegList* aList,
56 uint32_t aListIndex,
57 bool aIsAnimValItem) {
58 MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
60 mList = aList;
61 mListIndex = aListIndex;
62 mIsAnimValItem = aIsAnimValItem;
64 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
67 void DOMSVGPathSeg::RemovingFromList() {
68 uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
69 // InternalItem() + 1, because the args come after the encoded seg type
70 memcpy(PtrToMemberArgs(), InternalItem() + 1, argCount * sizeof(float));
71 mList = nullptr;
72 mIsAnimValItem = false;
75 void DOMSVGPathSeg::ToSVGPathSegEncodedData(float* aRaw) {
76 MOZ_ASSERT(aRaw, "null pointer");
77 uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
78 if (IsInList()) {
79 // 1 + argCount, because we're copying the encoded seg type and args
80 memcpy(aRaw, InternalItem(), (1 + argCount) * sizeof(float));
81 } else {
82 aRaw[0] = SVGPathSegUtils::EncodeType(Type());
83 // aRaw + 1, because the args go after the encoded seg type
84 memcpy(aRaw + 1, PtrToMemberArgs(), argCount * sizeof(float));
88 float* DOMSVGPathSeg::InternalItem() {
89 uint32_t dataIndex = mList->mItems[mListIndex].mInternalDataIndex;
90 return &(mList->InternalList().mData[dataIndex]);
93 #ifdef DEBUG
94 bool DOMSVGPathSeg::IndexIsValid() {
95 SVGAnimatedPathSegList* alist = Element()->GetAnimPathSegList();
96 return (mIsAnimValItem && mListIndex < alist->GetAnimValue().CountItems()) ||
97 (!mIsAnimValItem && mListIndex < alist->GetBaseValue().CountItems());
99 #endif
101 ////////////////////////////////////////////////////////////////////////
102 // Implementation of DOMSVGPathSeg sub-classes below this point
104 #define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \
105 type DOMSVGPathSeg##segName::propName() { \
106 if (mIsAnimValItem && HasOwner()) { \
107 Element()->FlushAnimations(); /* May make HasOwner() == false */ \
109 return type(HasOwner() ? InternalItem()[1 + index] : mArgs[index]); \
111 void DOMSVGPathSeg##segName::Set##propName(type a##propName, \
112 ErrorResult& rv) { \
113 if (mIsAnimValItem) { \
114 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); \
115 return; \
117 if (HasOwner()) { \
118 if (InternalItem()[1 + index] == float(a##propName)) { \
119 return; \
121 AutoChangePathSegListNotifier notifier(this); \
122 InternalItem()[1 + index] = float(a##propName); \
123 } else { \
124 mArgs[index] = float(a##propName); \
128 // For float, the normal type of arguments
129 #define IMPL_FLOAT_PROP(segName, propName, index) \
130 IMPL_PROP_WITH_TYPE(segName, propName, index, float)
132 // For the boolean flags in arc commands
133 #define IMPL_BOOL_PROP(segName, propName, index) \
134 IMPL_PROP_WITH_TYPE(segName, propName, index, bool)
136 ///////////////////////////////////////////////////////////////////////
138 IMPL_FLOAT_PROP(MovetoAbs, X, 0)
139 IMPL_FLOAT_PROP(MovetoAbs, Y, 1)
141 ////////////////////////////////////////////////////////////////////////
143 IMPL_FLOAT_PROP(MovetoRel, X, 0)
144 IMPL_FLOAT_PROP(MovetoRel, Y, 1)
146 ////////////////////////////////////////////////////////////////////////
148 IMPL_FLOAT_PROP(LinetoAbs, X, 0)
149 IMPL_FLOAT_PROP(LinetoAbs, Y, 1)
151 ////////////////////////////////////////////////////////////////////////
153 IMPL_FLOAT_PROP(LinetoRel, X, 0)
154 IMPL_FLOAT_PROP(LinetoRel, Y, 1)
156 ////////////////////////////////////////////////////////////////////////
158 IMPL_FLOAT_PROP(CurvetoCubicAbs, X1, 0)
159 IMPL_FLOAT_PROP(CurvetoCubicAbs, Y1, 1)
160 IMPL_FLOAT_PROP(CurvetoCubicAbs, X2, 2)
161 IMPL_FLOAT_PROP(CurvetoCubicAbs, Y2, 3)
162 IMPL_FLOAT_PROP(CurvetoCubicAbs, X, 4)
163 IMPL_FLOAT_PROP(CurvetoCubicAbs, Y, 5)
165 ////////////////////////////////////////////////////////////////////////
167 IMPL_FLOAT_PROP(CurvetoCubicRel, X1, 0)
168 IMPL_FLOAT_PROP(CurvetoCubicRel, Y1, 1)
169 IMPL_FLOAT_PROP(CurvetoCubicRel, X2, 2)
170 IMPL_FLOAT_PROP(CurvetoCubicRel, Y2, 3)
171 IMPL_FLOAT_PROP(CurvetoCubicRel, X, 4)
172 IMPL_FLOAT_PROP(CurvetoCubicRel, Y, 5)
174 ////////////////////////////////////////////////////////////////////////
176 IMPL_FLOAT_PROP(CurvetoQuadraticAbs, X1, 0)
177 IMPL_FLOAT_PROP(CurvetoQuadraticAbs, Y1, 1)
178 IMPL_FLOAT_PROP(CurvetoQuadraticAbs, X, 2)
179 IMPL_FLOAT_PROP(CurvetoQuadraticAbs, Y, 3)
181 ////////////////////////////////////////////////////////////////////////
183 IMPL_FLOAT_PROP(CurvetoQuadraticRel, X1, 0)
184 IMPL_FLOAT_PROP(CurvetoQuadraticRel, Y1, 1)
185 IMPL_FLOAT_PROP(CurvetoQuadraticRel, X, 2)
186 IMPL_FLOAT_PROP(CurvetoQuadraticRel, Y, 3)
188 ////////////////////////////////////////////////////////////////////////
190 IMPL_FLOAT_PROP(ArcAbs, R1, 0)
191 IMPL_FLOAT_PROP(ArcAbs, R2, 1)
192 IMPL_FLOAT_PROP(ArcAbs, Angle, 2)
193 IMPL_BOOL_PROP(ArcAbs, LargeArcFlag, 3)
194 IMPL_BOOL_PROP(ArcAbs, SweepFlag, 4)
195 IMPL_FLOAT_PROP(ArcAbs, X, 5)
196 IMPL_FLOAT_PROP(ArcAbs, Y, 6)
198 ////////////////////////////////////////////////////////////////////////
200 IMPL_FLOAT_PROP(ArcRel, R1, 0)
201 IMPL_FLOAT_PROP(ArcRel, R2, 1)
202 IMPL_FLOAT_PROP(ArcRel, Angle, 2)
203 IMPL_BOOL_PROP(ArcRel, LargeArcFlag, 3)
204 IMPL_BOOL_PROP(ArcRel, SweepFlag, 4)
205 IMPL_FLOAT_PROP(ArcRel, X, 5)
206 IMPL_FLOAT_PROP(ArcRel, Y, 6)
208 ////////////////////////////////////////////////////////////////////////
210 IMPL_FLOAT_PROP(LinetoHorizontalAbs, X, 0)
212 ////////////////////////////////////////////////////////////////////////
214 IMPL_FLOAT_PROP(LinetoHorizontalRel, X, 0)
216 ////////////////////////////////////////////////////////////////////////
218 IMPL_FLOAT_PROP(LinetoVerticalAbs, Y, 0)
220 ////////////////////////////////////////////////////////////////////////
222 IMPL_FLOAT_PROP(LinetoVerticalRel, Y, 0)
224 ////////////////////////////////////////////////////////////////////////
226 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, X2, 0)
227 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, Y2, 1)
228 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, X, 2)
229 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, Y, 3)
231 ////////////////////////////////////////////////////////////////////////
233 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, X2, 0)
234 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, Y2, 1)
235 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, X, 2)
236 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, Y, 3)
238 ////////////////////////////////////////////////////////////////////////
240 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs, X, 0)
241 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs, Y, 1)
243 ////////////////////////////////////////////////////////////////////////
245 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel, X, 0)
246 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel, Y, 1)
248 // This must come after DOMSVGPathSegClosePath et. al. have been declared.
249 /* static */
250 DOMSVGPathSeg* DOMSVGPathSeg::CreateFor(DOMSVGPathSegList* aList,
251 uint32_t aListIndex,
252 bool aIsAnimValItem) {
253 uint32_t dataIndex = aList->mItems[aListIndex].mInternalDataIndex;
254 float* data = &aList->InternalList().mData[dataIndex];
255 uint32_t type = SVGPathSegUtils::DecodeType(data[0]);
257 switch (type) {
258 case PATHSEG_CLOSEPATH:
259 return new DOMSVGPathSegClosePath(aList, aListIndex, aIsAnimValItem);
260 case PATHSEG_MOVETO_ABS:
261 return new DOMSVGPathSegMovetoAbs(aList, aListIndex, aIsAnimValItem);
262 case PATHSEG_MOVETO_REL:
263 return new DOMSVGPathSegMovetoRel(aList, aListIndex, aIsAnimValItem);
264 case PATHSEG_LINETO_ABS:
265 return new DOMSVGPathSegLinetoAbs(aList, aListIndex, aIsAnimValItem);
266 case PATHSEG_LINETO_REL:
267 return new DOMSVGPathSegLinetoRel(aList, aListIndex, aIsAnimValItem);
268 case PATHSEG_CURVETO_CUBIC_ABS:
269 return new DOMSVGPathSegCurvetoCubicAbs(aList, aListIndex,
270 aIsAnimValItem);
271 case PATHSEG_CURVETO_CUBIC_REL:
272 return new DOMSVGPathSegCurvetoCubicRel(aList, aListIndex,
273 aIsAnimValItem);
274 case PATHSEG_CURVETO_QUADRATIC_ABS:
275 return new DOMSVGPathSegCurvetoQuadraticAbs(aList, aListIndex,
276 aIsAnimValItem);
277 case PATHSEG_CURVETO_QUADRATIC_REL:
278 return new DOMSVGPathSegCurvetoQuadraticRel(aList, aListIndex,
279 aIsAnimValItem);
280 case PATHSEG_ARC_ABS:
281 return new DOMSVGPathSegArcAbs(aList, aListIndex, aIsAnimValItem);
282 case PATHSEG_ARC_REL:
283 return new DOMSVGPathSegArcRel(aList, aListIndex, aIsAnimValItem);
284 case PATHSEG_LINETO_HORIZONTAL_ABS:
285 return new DOMSVGPathSegLinetoHorizontalAbs(aList, aListIndex,
286 aIsAnimValItem);
287 case PATHSEG_LINETO_HORIZONTAL_REL:
288 return new DOMSVGPathSegLinetoHorizontalRel(aList, aListIndex,
289 aIsAnimValItem);
290 case PATHSEG_LINETO_VERTICAL_ABS:
291 return new DOMSVGPathSegLinetoVerticalAbs(aList, aListIndex,
292 aIsAnimValItem);
293 case PATHSEG_LINETO_VERTICAL_REL:
294 return new DOMSVGPathSegLinetoVerticalRel(aList, aListIndex,
295 aIsAnimValItem);
296 case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
297 return new DOMSVGPathSegCurvetoCubicSmoothAbs(aList, aListIndex,
298 aIsAnimValItem);
299 case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
300 return new DOMSVGPathSegCurvetoCubicSmoothRel(aList, aListIndex,
301 aIsAnimValItem);
302 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
303 return new DOMSVGPathSegCurvetoQuadraticSmoothAbs(aList, aListIndex,
304 aIsAnimValItem);
305 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
306 return new DOMSVGPathSegCurvetoQuadraticSmoothRel(aList, aListIndex,
307 aIsAnimValItem);
308 default:
309 MOZ_ASSERT_UNREACHABLE("Invalid path segment type");
310 return nullptr;
314 } // namespace mozilla::dom