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"
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.
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
,
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
,
57 bool aIsAnimValItem
) {
58 MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
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));
72 mIsAnimValItem
= false;
75 void DOMSVGPathSeg::ToSVGPathSegEncodedData(float* aRaw
) {
76 MOZ_ASSERT(aRaw
, "null pointer");
77 uint32_t argCount
= SVGPathSegUtils::ArgCountForType(Type());
79 // 1 + argCount, because we're copying the encoded seg type and args
80 memcpy(aRaw
, InternalItem(), (1 + argCount
) * sizeof(float));
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
]);
94 bool DOMSVGPathSeg::IndexIsValid() {
95 SVGAnimatedPathSegList
* alist
= Element()->GetAnimPathSegList();
96 return (mIsAnimValItem
&& mListIndex
< alist
->GetAnimValue().CountItems()) ||
97 (!mIsAnimValItem
&& mListIndex
< alist
->GetBaseValue().CountItems());
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, \
113 if (mIsAnimValItem) { \
114 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); \
118 if (InternalItem()[1 + index] == float(a##propName)) { \
121 AutoChangePathSegListNotifier notifier(this); \
122 InternalItem()[1 + index] = float(a##propName); \
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.
250 DOMSVGPathSeg
* DOMSVGPathSeg::CreateFor(DOMSVGPathSegList
* aList
,
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]);
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
,
271 case PATHSEG_CURVETO_CUBIC_REL
:
272 return new DOMSVGPathSegCurvetoCubicRel(aList
, aListIndex
,
274 case PATHSEG_CURVETO_QUADRATIC_ABS
:
275 return new DOMSVGPathSegCurvetoQuadraticAbs(aList
, aListIndex
,
277 case PATHSEG_CURVETO_QUADRATIC_REL
:
278 return new DOMSVGPathSegCurvetoQuadraticRel(aList
, aListIndex
,
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
,
287 case PATHSEG_LINETO_HORIZONTAL_REL
:
288 return new DOMSVGPathSegLinetoHorizontalRel(aList
, aListIndex
,
290 case PATHSEG_LINETO_VERTICAL_ABS
:
291 return new DOMSVGPathSegLinetoVerticalAbs(aList
, aListIndex
,
293 case PATHSEG_LINETO_VERTICAL_REL
:
294 return new DOMSVGPathSegLinetoVerticalRel(aList
, aListIndex
,
296 case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
:
297 return new DOMSVGPathSegCurvetoCubicSmoothAbs(aList
, aListIndex
,
299 case PATHSEG_CURVETO_CUBIC_SMOOTH_REL
:
300 return new DOMSVGPathSegCurvetoCubicSmoothRel(aList
, aListIndex
,
302 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
:
303 return new DOMSVGPathSegCurvetoQuadraticSmoothAbs(aList
, aListIndex
,
305 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
:
306 return new DOMSVGPathSegCurvetoQuadraticSmoothRel(aList
, aListIndex
,
309 MOZ_ASSERT_UNREACHABLE("Invalid path segment type");
314 } // namespace mozilla::dom