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 #ifndef DOM_SVG_DOMSVGPATHSEG_H_
8 #define DOM_SVG_DOMSVGPATHSEG_H_
10 #include "DOMSVGPathSegList.h"
11 #include "nsCycleCollectionParticipant.h"
12 #include "nsWrapperCache.h"
13 #include "SVGPathSegUtils.h"
14 #include "mozilla/dom/SVGPathSegBinding.h"
16 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 31
18 namespace mozilla::dom
{
22 #define CHECK_ARG_COUNT_IN_SYNC(segType) \
24 ArrayLength(mArgs) == \
25 SVGPathSegUtils::ArgCountForType(uint32_t(segType)) || \
26 uint32_t(segType) == dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH, \
27 "Arg count/array size out of sync")
29 #define IMPL_SVGPATHSEG_SUBCLASS_COMMON(segName, segType) \
30 explicit DOMSVGPathSeg##segName(const float* aArgs) : DOMSVGPathSeg() { \
31 CHECK_ARG_COUNT_IN_SYNC(segType); \
34 SVGPathSegUtils::ArgCountForType(uint32_t(segType)) * sizeof(float)); \
36 DOMSVGPathSeg##segName(DOMSVGPathSegList* aList, uint32_t aListIndex, \
37 bool aIsAnimValItem) \
38 : DOMSVGPathSeg(aList, aListIndex, aIsAnimValItem) { \
39 CHECK_ARG_COUNT_IN_SYNC(segType); \
41 /* From DOMSVGPathSeg: */ \
42 uint32_t Type() const override { return segType; } \
43 DOMSVGPathSeg* Clone() override { \
44 /* InternalItem() + 1, because we're skipping the encoded seg type */ \
45 float* args = IsInList() ? InternalItem() + 1 : mArgs; \
46 return new DOMSVGPathSeg##segName(args); \
48 float* PtrToMemberArgs() override { return mArgs; } \
50 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) \
52 return dom::SVGPathSeg##segName##_Binding::Wrap(aCx, this, aGivenProto); \
58 * This class is the base class of the classes that create the DOM objects that
59 * wrap the internal path segments that are encoded in an SVGPathData. Its
60 * sub-classes are also used to create the objects returned by
61 * SVGPathElement.createSVGPathSegXxx().
63 * See the architecture comment in DOMSVGPathSegList.h for an overview of the
64 * important points regarding these DOM wrapper structures.
66 * See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
67 * of the important points regarding how this specific class works.
69 * The main differences between this class and DOMSVGLength is that we have
70 * sub-classes (it does not), and the "internal counterpart" that we provide a
71 * DOM wrapper for is a list of floats, not an instance of an internal class.
73 class DOMSVGPathSeg
: public nsWrapperCache
{
75 friend class AutoChangePathSegListNotifier
;
78 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGPathSeg
)
79 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGPathSeg
)
82 * Unlike the other list classes, we hide our ctor (because no one should be
83 * creating instances of this class directly). This factory method in exposed
84 * instead to take care of creating instances of the correct sub-class.
86 static DOMSVGPathSeg
* CreateFor(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
90 * Create an unowned copy of this object. The caller is responsible for the
93 virtual DOMSVGPathSeg
* Clone() = 0;
95 bool IsInList() const { return !!mList
; }
98 * Returns true if our attribute is animating (in which case our animVal is
99 * not simply a mirror of our baseVal).
101 bool AttrIsAnimating() const { return mList
&& mList
->AttrIsAnimating(); }
104 * In future, if this class is used for non-list segments, this will be
105 * different to IsInList().
107 bool HasOwner() const { return !!mList
; }
110 * This method is called to notify this DOM object that it is being inserted
111 * into a list, and give it the information it needs as a result.
113 * This object MUST NOT already belong to a list when this method is called.
114 * That's not to say that script can't move these DOM objects between
115 * lists - it can - it's just that the logic to handle that (and send out
116 * the necessary notifications) is located elsewhere (in DOMSVGPathSegList).)
118 void InsertingIntoList(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
119 bool aIsAnimValItem
);
121 static uint32_t MaxListIndex() {
122 return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT
) - 1;
125 /// This method is called to notify this object that its list index changed.
126 void UpdateListIndex(uint32_t aListIndex
) { mListIndex
= aListIndex
; }
129 * This method is called to notify this DOM object that it is about to be
130 * removed from its current DOM list so that it can first make a copy of its
131 * internal counterpart's values. (If it didn't do this, then it would
132 * "lose" its value on being removed.)
134 void RemovingFromList();
137 * This method converts the segment to a string of floats as found in
138 * SVGPathData (i.e. the first float contains the type of the segment,
139 * encoded into a float, followed by its arguments in the same order as they
140 * are given in the <path> element's 'd' attribute).
142 void ToSVGPathSegEncodedData(float* aRaw
);
145 * The type of this path segment.
147 virtual uint32_t Type() const = 0;
150 DOMSVGPathSegList
* GetParentObject() { return mList
; }
151 uint16_t PathSegType() const { return Type(); }
152 void GetPathSegTypeAsLetter(nsAString
& aPathSegTypeAsLetter
) {
153 aPathSegTypeAsLetter
= SVGPathSegUtils::GetPathSegTypeAsLetter(Type());
155 virtual JSObject
* WrapObject(JSContext
* aCx
,
156 JS::Handle
<JSObject
*> aGivenProto
) override
= 0;
160 * Generic ctor for DOMSVGPathSeg objects that are created for an attribute.
162 DOMSVGPathSeg(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
163 bool aIsAnimValItem
);
166 * Ctor for creating the objects returned by
167 * SVGPathElement.createSVGPathSegXxx(), which do not initially belong to an
172 virtual ~DOMSVGPathSeg() {
173 // Our mList's weak ref to us must be nulled out when we die. If GC has
174 // unlinked us using the cycle collector code, then that has already
175 // happened, and mList is null.
177 mList
->ItemAt(mListIndex
) = nullptr;
181 dom::SVGElement
* Element() { return mList
->Element(); }
184 * Get a reference to the internal SVGPathSeg list item that this DOM wrapper
185 * object currently wraps.
187 * To simplify the code we just have this one method for obtaining both
188 * baseVal and animVal internal items. This means that animVal items don't
189 * get const protection, but then our setter methods guard against changing
192 float* InternalItem();
194 virtual float* PtrToMemberArgs() = 0;
200 RefPtr
<DOMSVGPathSegList
> mList
;
202 // Bounds for the following are checked in the ctor, so be sure to update
203 // that if you change the capacity of any of the following.
205 uint32_t mListIndex
: MOZ_SVG_LIST_INDEX_BIT_COUNT
;
206 uint32_t mIsAnimValItem
: 1; // uint32_t because MSVC won't pack otherwise
209 class DOMSVGPathSegClosePath
: public DOMSVGPathSeg
{
211 DOMSVGPathSegClosePath() : DOMSVGPathSeg() {}
213 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ClosePath
,
214 dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH
)
217 // To allow IMPL_SVGPATHSEG_SUBCLASS_COMMON above to compile we need an
218 // mArgs, but since C++ doesn't allow zero-sized arrays we need to give it
219 // one (unused) element.
223 class DOMSVGPathSegMovetoAbs
: public DOMSVGPathSeg
{
225 DOMSVGPathSegMovetoAbs(float x
, float y
) : DOMSVGPathSeg() {
230 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoAbs
,
231 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS
)
234 void SetX(float aX
, ErrorResult
& rv
);
236 void SetY(float aY
, ErrorResult
& rv
);
242 class DOMSVGPathSegMovetoRel
: public DOMSVGPathSeg
{
244 DOMSVGPathSegMovetoRel(float x
, float y
) : DOMSVGPathSeg() {
249 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoRel
,
250 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_REL
)
253 void SetX(float aX
, ErrorResult
& rv
);
255 void SetY(float aY
, ErrorResult
& rv
);
261 class DOMSVGPathSegLinetoAbs
: public DOMSVGPathSeg
{
263 DOMSVGPathSegLinetoAbs(float x
, float y
) : DOMSVGPathSeg() {
268 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoAbs
,
269 dom::SVGPathSeg_Binding::PATHSEG_LINETO_ABS
)
272 void SetX(float aX
, ErrorResult
& rv
);
274 void SetY(float aY
, ErrorResult
& rv
);
280 class DOMSVGPathSegLinetoRel
: public DOMSVGPathSeg
{
282 DOMSVGPathSegLinetoRel(float x
, float y
) : DOMSVGPathSeg() {
287 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoRel
,
288 dom::SVGPathSeg_Binding::PATHSEG_LINETO_REL
)
291 void SetX(float aX
, ErrorResult
& rv
);
293 void SetY(float aY
, ErrorResult
& rv
);
299 class DOMSVGPathSegCurvetoCubicAbs
: public DOMSVGPathSeg
{
301 DOMSVGPathSegCurvetoCubicAbs(float x1
, float y1
, float x2
, float y2
, float x
,
313 void SetX(float aX
, ErrorResult
& rv
);
315 void SetY(float aY
, ErrorResult
& rv
);
317 void SetX1(float aX1
, ErrorResult
& rv
);
319 void SetY1(float aY1
, ErrorResult
& rv
);
321 void SetX2(float aX2
, ErrorResult
& rv
);
323 void SetY2(float aY2
, ErrorResult
& rv
);
325 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
326 CurvetoCubicAbs
, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS
)
332 class DOMSVGPathSegCurvetoCubicRel
: public DOMSVGPathSeg
{
334 DOMSVGPathSegCurvetoCubicRel(float x1
, float y1
, float x2
, float y2
, float x
,
345 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
346 CurvetoCubicRel
, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL
)
349 void SetX(float aX
, ErrorResult
& rv
);
351 void SetY(float aY
, ErrorResult
& rv
);
353 void SetX1(float aX1
, ErrorResult
& rv
);
355 void SetY1(float aY1
, ErrorResult
& rv
);
357 void SetX2(float aX2
, ErrorResult
& rv
);
359 void SetY2(float aY2
, ErrorResult
& rv
);
365 class DOMSVGPathSegCurvetoQuadraticAbs
: public DOMSVGPathSeg
{
367 DOMSVGPathSegCurvetoQuadraticAbs(float x1
, float y1
, float x
, float y
)
375 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
377 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS
)
380 void SetX(float aX
, ErrorResult
& rv
);
382 void SetY(float aY
, ErrorResult
& rv
);
384 void SetX1(float aX1
, ErrorResult
& rv
);
386 void SetY1(float aY1
, ErrorResult
& rv
);
392 class DOMSVGPathSegCurvetoQuadraticRel
: public DOMSVGPathSeg
{
394 DOMSVGPathSegCurvetoQuadraticRel(float x1
, float y1
, float x
, float y
)
402 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
404 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL
)
407 void SetX(float aX
, ErrorResult
& rv
);
409 void SetY(float aY
, ErrorResult
& rv
);
411 void SetX1(float aX1
, ErrorResult
& rv
);
413 void SetY1(float aY1
, ErrorResult
& rv
);
419 class DOMSVGPathSegArcAbs
: public DOMSVGPathSeg
{
421 DOMSVGPathSegArcAbs(float r1
, float r2
, float angle
, bool largeArcFlag
,
422 bool sweepFlag
, float x
, float y
)
427 mArgs
[3] = largeArcFlag
;
428 mArgs
[4] = sweepFlag
;
433 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcAbs
,
434 dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS
)
437 void SetX(float aX
, ErrorResult
& rv
);
439 void SetY(float aY
, ErrorResult
& rv
);
441 void SetR1(float aR1
, ErrorResult
& rv
);
443 void SetR2(float aR2
, ErrorResult
& rv
);
445 void SetAngle(float aAngle
, ErrorResult
& rv
);
447 void SetLargeArcFlag(bool aLargeArcFlag
, ErrorResult
& rv
);
449 void SetSweepFlag(bool aSweepFlag
, ErrorResult
& rv
);
455 class DOMSVGPathSegArcRel
: public DOMSVGPathSeg
{
457 DOMSVGPathSegArcRel(float r1
, float r2
, float angle
, bool largeArcFlag
,
458 bool sweepFlag
, float x
, float y
)
463 mArgs
[3] = largeArcFlag
;
464 mArgs
[4] = sweepFlag
;
469 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcRel
,
470 dom::SVGPathSeg_Binding::PATHSEG_ARC_REL
)
473 void SetX(float aX
, ErrorResult
& rv
);
475 void SetY(float aY
, ErrorResult
& rv
);
477 void SetR1(float aR1
, ErrorResult
& rv
);
479 void SetR2(float aR2
, ErrorResult
& rv
);
481 void SetAngle(float aAngle
, ErrorResult
& rv
);
483 void SetLargeArcFlag(bool aLargeArcFlag
, ErrorResult
& rv
);
485 void SetSweepFlag(bool aSweepFlag
, ErrorResult
& rv
);
491 class DOMSVGPathSegLinetoHorizontalAbs
: public DOMSVGPathSeg
{
493 explicit DOMSVGPathSegLinetoHorizontalAbs(float x
) : DOMSVGPathSeg() {
497 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
499 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_ABS
)
502 void SetX(float aX
, ErrorResult
& rv
);
508 class DOMSVGPathSegLinetoHorizontalRel
: public DOMSVGPathSeg
{
510 explicit DOMSVGPathSegLinetoHorizontalRel(float x
) : DOMSVGPathSeg() {
514 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
516 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_REL
)
519 void SetX(float aX
, ErrorResult
& rv
);
525 class DOMSVGPathSegLinetoVerticalAbs
: public DOMSVGPathSeg
{
527 explicit DOMSVGPathSegLinetoVerticalAbs(float y
) : DOMSVGPathSeg() {
531 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
532 LinetoVerticalAbs
, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_ABS
)
535 void SetY(float aY
, ErrorResult
& rv
);
541 class DOMSVGPathSegLinetoVerticalRel
: public DOMSVGPathSeg
{
543 explicit DOMSVGPathSegLinetoVerticalRel(float y
) : DOMSVGPathSeg() {
547 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
548 LinetoVerticalRel
, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_REL
)
551 void SetY(float aY
, ErrorResult
& rv
);
557 class DOMSVGPathSegCurvetoCubicSmoothAbs
: public DOMSVGPathSeg
{
559 DOMSVGPathSegCurvetoCubicSmoothAbs(float x2
, float y2
, float x
, float y
)
567 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
568 CurvetoCubicSmoothAbs
,
569 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
)
572 void SetX(float aX
, ErrorResult
& rv
);
574 void SetY(float aY
, ErrorResult
& rv
);
576 void SetX2(float aX2
, ErrorResult
& rv
);
578 void SetY2(float aY2
, ErrorResult
& rv
);
584 class DOMSVGPathSegCurvetoCubicSmoothRel
: public DOMSVGPathSeg
{
586 DOMSVGPathSegCurvetoCubicSmoothRel(float x2
, float y2
, float x
, float y
)
594 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
595 CurvetoCubicSmoothRel
,
596 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL
)
599 void SetX(float aX
, ErrorResult
& rv
);
601 void SetY(float aY
, ErrorResult
& rv
);
603 void SetX2(float aX2
, ErrorResult
& rv
);
605 void SetY2(float aY2
, ErrorResult
& rv
);
611 class DOMSVGPathSegCurvetoQuadraticSmoothAbs
: public DOMSVGPathSeg
{
613 DOMSVGPathSegCurvetoQuadraticSmoothAbs(float x
, float y
) : DOMSVGPathSeg() {
618 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
619 CurvetoQuadraticSmoothAbs
,
620 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
)
623 void SetX(float aX
, ErrorResult
& rv
);
625 void SetY(float aY
, ErrorResult
& rv
);
631 class DOMSVGPathSegCurvetoQuadraticSmoothRel
: public DOMSVGPathSeg
{
633 DOMSVGPathSegCurvetoQuadraticSmoothRel(float x
, float y
) : DOMSVGPathSeg() {
638 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
639 CurvetoQuadraticSmoothRel
,
640 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
)
643 void SetX(float aX
, ErrorResult
& rv
);
645 void SetY(float aY
, ErrorResult
& rv
);
651 } // namespace mozilla::dom
653 #undef MOZ_SVG_LIST_INDEX_BIT_COUNT
655 #endif // DOM_SVG_DOMSVGPATHSEG_H_