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.
19 using namespace dom::SVGPathSeg_Binding
;
21 // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
22 // clear our list's weak ref to us to be safe. (The other option would be to
23 // not unlink and rely on the breaking of the other edges in the cycle, as
24 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
25 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSeg
)
27 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSeg
)
28 // We may not belong to a list, so we must null check tmp->mList.
30 tmp
->mList
->ItemAt(tmp
->mListIndex
) = nullptr;
32 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList
)
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
34 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSeg
)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList
)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
40 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSeg
)
41 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
42 NS_IMPL_CYCLE_COLLECTION_TRACE_END
44 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMSVGPathSeg
, AddRef
)
45 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGPathSeg
, Release
)
47 DOMSVGPathSeg::DOMSVGPathSeg(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
49 : mList(aList
), mListIndex(aListIndex
), mIsAnimValItem(aIsAnimValItem
) {
50 // These shifts are in sync with the members in the header.
51 MOZ_ASSERT(aList
&& aListIndex
<= MaxListIndex(), "bad arg");
53 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
56 DOMSVGPathSeg::DOMSVGPathSeg()
57 : mList(nullptr), mListIndex(0), mIsAnimValItem(false) {}
59 void DOMSVGPathSeg::InsertingIntoList(DOMSVGPathSegList
* aList
,
61 bool aIsAnimValItem
) {
62 MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
65 mListIndex
= aListIndex
;
66 mIsAnimValItem
= aIsAnimValItem
;
68 MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
71 void DOMSVGPathSeg::RemovingFromList() {
72 uint32_t argCount
= SVGPathSegUtils::ArgCountForType(Type());
73 // InternalItem() + 1, because the args come after the encoded seg type
74 memcpy(PtrToMemberArgs(), InternalItem() + 1, argCount
* sizeof(float));
76 mIsAnimValItem
= false;
79 void DOMSVGPathSeg::ToSVGPathSegEncodedData(float* aRaw
) {
80 MOZ_ASSERT(aRaw
, "null pointer");
81 uint32_t argCount
= SVGPathSegUtils::ArgCountForType(Type());
83 // 1 + argCount, because we're copying the encoded seg type and args
84 memcpy(aRaw
, InternalItem(), (1 + argCount
) * sizeof(float));
86 aRaw
[0] = SVGPathSegUtils::EncodeType(Type());
87 // aRaw + 1, because the args go after the encoded seg type
88 memcpy(aRaw
+ 1, PtrToMemberArgs(), argCount
* sizeof(float));
92 float* DOMSVGPathSeg::InternalItem() {
93 uint32_t dataIndex
= mList
->mItems
[mListIndex
].mInternalDataIndex
;
94 return &(mList
->InternalList().mData
[dataIndex
]);
98 bool DOMSVGPathSeg::IndexIsValid() {
99 SVGAnimatedPathSegList
* alist
= Element()->GetAnimPathSegList();
100 return (mIsAnimValItem
&& mListIndex
< alist
->GetAnimValue().CountItems()) ||
101 (!mIsAnimValItem
&& mListIndex
< alist
->GetBaseValue().CountItems());
105 ////////////////////////////////////////////////////////////////////////
106 // Implementation of DOMSVGPathSeg sub-classes below this point
108 #define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \
109 type DOMSVGPathSeg##segName::propName() { \
110 if (mIsAnimValItem && HasOwner()) { \
111 Element()->FlushAnimations(); /* May make HasOwner() == false */ \
113 return type(HasOwner() ? InternalItem()[1 + index] : mArgs[index]); \
115 void DOMSVGPathSeg##segName::Set##propName(type a##propName, \
117 if (mIsAnimValItem) { \
118 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); \
122 if (InternalItem()[1 + index] == float(a##propName)) { \
125 AutoChangePathSegListNotifier notifier(this); \
126 InternalItem()[1 + index] = float(a##propName); \
128 mArgs[index] = float(a##propName); \
132 // For float, the normal type of arguments
133 #define IMPL_FLOAT_PROP(segName, propName, index) \
134 IMPL_PROP_WITH_TYPE(segName, propName, index, float)
136 // For the boolean flags in arc commands
137 #define IMPL_BOOL_PROP(segName, propName, index) \
138 IMPL_PROP_WITH_TYPE(segName, propName, index, bool)
140 ///////////////////////////////////////////////////////////////////////
142 IMPL_FLOAT_PROP(MovetoAbs
, X
, 0)
143 IMPL_FLOAT_PROP(MovetoAbs
, Y
, 1)
145 ////////////////////////////////////////////////////////////////////////
147 IMPL_FLOAT_PROP(MovetoRel
, X
, 0)
148 IMPL_FLOAT_PROP(MovetoRel
, Y
, 1)
150 ////////////////////////////////////////////////////////////////////////
152 IMPL_FLOAT_PROP(LinetoAbs
, X
, 0)
153 IMPL_FLOAT_PROP(LinetoAbs
, Y
, 1)
155 ////////////////////////////////////////////////////////////////////////
157 IMPL_FLOAT_PROP(LinetoRel
, X
, 0)
158 IMPL_FLOAT_PROP(LinetoRel
, Y
, 1)
160 ////////////////////////////////////////////////////////////////////////
162 IMPL_FLOAT_PROP(CurvetoCubicAbs
, X1
, 0)
163 IMPL_FLOAT_PROP(CurvetoCubicAbs
, Y1
, 1)
164 IMPL_FLOAT_PROP(CurvetoCubicAbs
, X2
, 2)
165 IMPL_FLOAT_PROP(CurvetoCubicAbs
, Y2
, 3)
166 IMPL_FLOAT_PROP(CurvetoCubicAbs
, X
, 4)
167 IMPL_FLOAT_PROP(CurvetoCubicAbs
, Y
, 5)
169 ////////////////////////////////////////////////////////////////////////
171 IMPL_FLOAT_PROP(CurvetoCubicRel
, X1
, 0)
172 IMPL_FLOAT_PROP(CurvetoCubicRel
, Y1
, 1)
173 IMPL_FLOAT_PROP(CurvetoCubicRel
, X2
, 2)
174 IMPL_FLOAT_PROP(CurvetoCubicRel
, Y2
, 3)
175 IMPL_FLOAT_PROP(CurvetoCubicRel
, X
, 4)
176 IMPL_FLOAT_PROP(CurvetoCubicRel
, Y
, 5)
178 ////////////////////////////////////////////////////////////////////////
180 IMPL_FLOAT_PROP(CurvetoQuadraticAbs
, X1
, 0)
181 IMPL_FLOAT_PROP(CurvetoQuadraticAbs
, Y1
, 1)
182 IMPL_FLOAT_PROP(CurvetoQuadraticAbs
, X
, 2)
183 IMPL_FLOAT_PROP(CurvetoQuadraticAbs
, Y
, 3)
185 ////////////////////////////////////////////////////////////////////////
187 IMPL_FLOAT_PROP(CurvetoQuadraticRel
, X1
, 0)
188 IMPL_FLOAT_PROP(CurvetoQuadraticRel
, Y1
, 1)
189 IMPL_FLOAT_PROP(CurvetoQuadraticRel
, X
, 2)
190 IMPL_FLOAT_PROP(CurvetoQuadraticRel
, Y
, 3)
192 ////////////////////////////////////////////////////////////////////////
194 IMPL_FLOAT_PROP(ArcAbs
, R1
, 0)
195 IMPL_FLOAT_PROP(ArcAbs
, R2
, 1)
196 IMPL_FLOAT_PROP(ArcAbs
, Angle
, 2)
197 IMPL_BOOL_PROP(ArcAbs
, LargeArcFlag
, 3)
198 IMPL_BOOL_PROP(ArcAbs
, SweepFlag
, 4)
199 IMPL_FLOAT_PROP(ArcAbs
, X
, 5)
200 IMPL_FLOAT_PROP(ArcAbs
, Y
, 6)
202 ////////////////////////////////////////////////////////////////////////
204 IMPL_FLOAT_PROP(ArcRel
, R1
, 0)
205 IMPL_FLOAT_PROP(ArcRel
, R2
, 1)
206 IMPL_FLOAT_PROP(ArcRel
, Angle
, 2)
207 IMPL_BOOL_PROP(ArcRel
, LargeArcFlag
, 3)
208 IMPL_BOOL_PROP(ArcRel
, SweepFlag
, 4)
209 IMPL_FLOAT_PROP(ArcRel
, X
, 5)
210 IMPL_FLOAT_PROP(ArcRel
, Y
, 6)
212 ////////////////////////////////////////////////////////////////////////
214 IMPL_FLOAT_PROP(LinetoHorizontalAbs
, X
, 0)
216 ////////////////////////////////////////////////////////////////////////
218 IMPL_FLOAT_PROP(LinetoHorizontalRel
, X
, 0)
220 ////////////////////////////////////////////////////////////////////////
222 IMPL_FLOAT_PROP(LinetoVerticalAbs
, Y
, 0)
224 ////////////////////////////////////////////////////////////////////////
226 IMPL_FLOAT_PROP(LinetoVerticalRel
, Y
, 0)
228 ////////////////////////////////////////////////////////////////////////
230 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs
, X2
, 0)
231 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs
, Y2
, 1)
232 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs
, X
, 2)
233 IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs
, Y
, 3)
235 ////////////////////////////////////////////////////////////////////////
237 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel
, X2
, 0)
238 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel
, Y2
, 1)
239 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel
, X
, 2)
240 IMPL_FLOAT_PROP(CurvetoCubicSmoothRel
, Y
, 3)
242 ////////////////////////////////////////////////////////////////////////
244 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs
, X
, 0)
245 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs
, Y
, 1)
247 ////////////////////////////////////////////////////////////////////////
249 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel
, X
, 0)
250 IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel
, Y
, 1)
252 // This must come after DOMSVGPathSegClosePath et. al. have been declared.
254 DOMSVGPathSeg
* DOMSVGPathSeg::CreateFor(DOMSVGPathSegList
* aList
,
256 bool aIsAnimValItem
) {
257 uint32_t dataIndex
= aList
->mItems
[aListIndex
].mInternalDataIndex
;
258 float* data
= &aList
->InternalList().mData
[dataIndex
];
259 uint32_t type
= SVGPathSegUtils::DecodeType(data
[0]);
262 case PATHSEG_CLOSEPATH
:
263 return new DOMSVGPathSegClosePath(aList
, aListIndex
, aIsAnimValItem
);
264 case PATHSEG_MOVETO_ABS
:
265 return new DOMSVGPathSegMovetoAbs(aList
, aListIndex
, aIsAnimValItem
);
266 case PATHSEG_MOVETO_REL
:
267 return new DOMSVGPathSegMovetoRel(aList
, aListIndex
, aIsAnimValItem
);
268 case PATHSEG_LINETO_ABS
:
269 return new DOMSVGPathSegLinetoAbs(aList
, aListIndex
, aIsAnimValItem
);
270 case PATHSEG_LINETO_REL
:
271 return new DOMSVGPathSegLinetoRel(aList
, aListIndex
, aIsAnimValItem
);
272 case PATHSEG_CURVETO_CUBIC_ABS
:
273 return new DOMSVGPathSegCurvetoCubicAbs(aList
, aListIndex
,
275 case PATHSEG_CURVETO_CUBIC_REL
:
276 return new DOMSVGPathSegCurvetoCubicRel(aList
, aListIndex
,
278 case PATHSEG_CURVETO_QUADRATIC_ABS
:
279 return new DOMSVGPathSegCurvetoQuadraticAbs(aList
, aListIndex
,
281 case PATHSEG_CURVETO_QUADRATIC_REL
:
282 return new DOMSVGPathSegCurvetoQuadraticRel(aList
, aListIndex
,
284 case PATHSEG_ARC_ABS
:
285 return new DOMSVGPathSegArcAbs(aList
, aListIndex
, aIsAnimValItem
);
286 case PATHSEG_ARC_REL
:
287 return new DOMSVGPathSegArcRel(aList
, aListIndex
, aIsAnimValItem
);
288 case PATHSEG_LINETO_HORIZONTAL_ABS
:
289 return new DOMSVGPathSegLinetoHorizontalAbs(aList
, aListIndex
,
291 case PATHSEG_LINETO_HORIZONTAL_REL
:
292 return new DOMSVGPathSegLinetoHorizontalRel(aList
, aListIndex
,
294 case PATHSEG_LINETO_VERTICAL_ABS
:
295 return new DOMSVGPathSegLinetoVerticalAbs(aList
, aListIndex
,
297 case PATHSEG_LINETO_VERTICAL_REL
:
298 return new DOMSVGPathSegLinetoVerticalRel(aList
, aListIndex
,
300 case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
:
301 return new DOMSVGPathSegCurvetoCubicSmoothAbs(aList
, aListIndex
,
303 case PATHSEG_CURVETO_CUBIC_SMOOTH_REL
:
304 return new DOMSVGPathSegCurvetoCubicSmoothRel(aList
, aListIndex
,
306 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
:
307 return new DOMSVGPathSegCurvetoQuadraticSmoothAbs(aList
, aListIndex
,
309 case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
:
310 return new DOMSVGPathSegCurvetoQuadraticSmoothRel(aList
, aListIndex
,
313 MOZ_ASSERT_UNREACHABLE("Invalid path segment type");
319 } // namespace mozilla