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
23 #define CHECK_ARG_COUNT_IN_SYNC(segType) \
25 ArrayLength(mArgs) == \
26 SVGPathSegUtils::ArgCountForType(uint32_t(segType)) || \
27 uint32_t(segType) == dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH, \
28 "Arg count/array size out of sync")
30 #define IMPL_SVGPATHSEG_SUBCLASS_COMMON(segName, segType) \
31 explicit DOMSVGPathSeg##segName(const float* aArgs) : DOMSVGPathSeg() { \
32 CHECK_ARG_COUNT_IN_SYNC(segType); \
35 SVGPathSegUtils::ArgCountForType(uint32_t(segType)) * sizeof(float)); \
37 DOMSVGPathSeg##segName(DOMSVGPathSegList* aList, uint32_t aListIndex, \
38 bool aIsAnimValItem) \
39 : DOMSVGPathSeg(aList, aListIndex, aIsAnimValItem) { \
40 CHECK_ARG_COUNT_IN_SYNC(segType); \
42 /* From DOMSVGPathSeg: */ \
43 virtual uint32_t Type() const override { return segType; } \
44 virtual DOMSVGPathSeg* Clone() override { \
45 /* InternalItem() + 1, because we're skipping the encoded seg type */ \
46 float* args = IsInList() ? InternalItem() + 1 : mArgs; \
47 return new DOMSVGPathSeg##segName(args); \
49 virtual float* PtrToMemberArgs() override { return mArgs; } \
51 virtual JSObject* WrapObject(JSContext* aCx, \
52 JS::Handle<JSObject*> aGivenProto) override { \
53 return dom::SVGPathSeg##segName##_Binding::Wrap(aCx, this, aGivenProto); \
59 * This class is the base class of the classes that create the DOM objects that
60 * wrap the internal path segments that are encoded in an SVGPathData. Its
61 * sub-classes are also used to create the objects returned by
62 * SVGPathElement.createSVGPathSegXxx().
64 * See the architecture comment in DOMSVGPathSegList.h for an overview of the
65 * important points regarding these DOM wrapper structures.
67 * See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
68 * of the important points regarding how this specific class works.
70 * The main differences between this class and DOMSVGLength is that we have
71 * sub-classes (it does not), and the "internal counterpart" that we provide a
72 * DOM wrapper for is a list of floats, not an instance of an internal class.
74 class DOMSVGPathSeg
: public nsWrapperCache
{
76 friend class AutoChangePathSegListNotifier
;
79 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGPathSeg
)
80 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGPathSeg
)
83 * Unlike the other list classes, we hide our ctor (because no one should be
84 * creating instances of this class directly). This factory method in exposed
85 * instead to take care of creating instances of the correct sub-class.
87 static DOMSVGPathSeg
* CreateFor(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
91 * Create an unowned copy of this object. The caller is responsible for the
94 virtual DOMSVGPathSeg
* Clone() = 0;
96 bool IsInList() const { return !!mList
; }
99 * Returns true if our attribute is animating (in which case our animVal is
100 * not simply a mirror of our baseVal).
102 bool AttrIsAnimating() const { return mList
&& mList
->AttrIsAnimating(); }
105 * In future, if this class is used for non-list segments, this will be
106 * different to IsInList().
108 bool HasOwner() const { return !!mList
; }
111 * This method is called to notify this DOM object that it is being inserted
112 * into a list, and give it the information it needs as a result.
114 * This object MUST NOT already belong to a list when this method is called.
115 * That's not to say that script can't move these DOM objects between
116 * lists - it can - it's just that the logic to handle that (and send out
117 * the necessary notifications) is located elsewhere (in DOMSVGPathSegList).)
119 void InsertingIntoList(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
120 bool aIsAnimValItem
);
122 static uint32_t MaxListIndex() {
123 return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT
) - 1;
126 /// This method is called to notify this object that its list index changed.
127 void UpdateListIndex(uint32_t aListIndex
) { mListIndex
= aListIndex
; }
130 * This method is called to notify this DOM object that it is about to be
131 * removed from its current DOM list so that it can first make a copy of its
132 * internal counterpart's values. (If it didn't do this, then it would
133 * "lose" its value on being removed.)
135 void RemovingFromList();
138 * This method converts the segment to a string of floats as found in
139 * SVGPathData (i.e. the first float contains the type of the segment,
140 * encoded into a float, followed by its arguments in the same order as they
141 * are given in the <path> element's 'd' attribute).
143 void ToSVGPathSegEncodedData(float* aRaw
);
146 * The type of this path segment.
148 virtual uint32_t Type() const = 0;
151 DOMSVGPathSegList
* GetParentObject() { return mList
; }
152 uint16_t PathSegType() const { return Type(); }
153 void GetPathSegTypeAsLetter(nsAString
& aPathSegTypeAsLetter
) {
154 aPathSegTypeAsLetter
= SVGPathSegUtils::GetPathSegTypeAsLetter(Type());
156 virtual JSObject
* WrapObject(JSContext
* aCx
,
157 JS::Handle
<JSObject
*> aGivenProto
) override
= 0;
161 * Generic ctor for DOMSVGPathSeg objects that are created for an attribute.
163 DOMSVGPathSeg(DOMSVGPathSegList
* aList
, uint32_t aListIndex
,
164 bool aIsAnimValItem
);
167 * Ctor for creating the objects returned by
168 * SVGPathElement.createSVGPathSegXxx(), which do not initially belong to an
173 virtual ~DOMSVGPathSeg() {
174 // Our mList's weak ref to us must be nulled out when we die. If GC has
175 // unlinked us using the cycle collector code, then that has already
176 // happened, and mList is null.
178 mList
->ItemAt(mListIndex
) = nullptr;
182 dom::SVGElement
* Element() { return mList
->Element(); }
185 * Get a reference to the internal SVGPathSeg list item that this DOM wrapper
186 * object currently wraps.
188 * To simplify the code we just have this one method for obtaining both
189 * baseVal and animVal internal items. This means that animVal items don't
190 * get const protection, but then our setter methods guard against changing
193 float* InternalItem();
195 virtual float* PtrToMemberArgs() = 0;
201 RefPtr
<DOMSVGPathSegList
> mList
;
203 // Bounds for the following are checked in the ctor, so be sure to update
204 // that if you change the capacity of any of the following.
206 uint32_t mListIndex
: MOZ_SVG_LIST_INDEX_BIT_COUNT
;
207 uint32_t mIsAnimValItem
: 1; // uint32_t because MSVC won't pack otherwise
210 class DOMSVGPathSegClosePath
: public DOMSVGPathSeg
{
212 DOMSVGPathSegClosePath() : DOMSVGPathSeg() {}
214 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ClosePath
,
215 dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH
)
218 // To allow IMPL_SVGPATHSEG_SUBCLASS_COMMON above to compile we need an
219 // mArgs, but since C++ doesn't allow zero-sized arrays we need to give it
220 // one (unused) element.
224 class DOMSVGPathSegMovetoAbs
: public DOMSVGPathSeg
{
226 DOMSVGPathSegMovetoAbs(float x
, float y
) : DOMSVGPathSeg() {
231 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoAbs
,
232 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS
)
235 void SetX(float aX
, ErrorResult
& rv
);
237 void SetY(float aY
, ErrorResult
& rv
);
243 class DOMSVGPathSegMovetoRel
: public DOMSVGPathSeg
{
245 DOMSVGPathSegMovetoRel(float x
, float y
) : DOMSVGPathSeg() {
250 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoRel
,
251 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_REL
)
254 void SetX(float aX
, ErrorResult
& rv
);
256 void SetY(float aY
, ErrorResult
& rv
);
262 class DOMSVGPathSegLinetoAbs
: public DOMSVGPathSeg
{
264 DOMSVGPathSegLinetoAbs(float x
, float y
) : DOMSVGPathSeg() {
269 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoAbs
,
270 dom::SVGPathSeg_Binding::PATHSEG_LINETO_ABS
)
273 void SetX(float aX
, ErrorResult
& rv
);
275 void SetY(float aY
, ErrorResult
& rv
);
281 class DOMSVGPathSegLinetoRel
: public DOMSVGPathSeg
{
283 DOMSVGPathSegLinetoRel(float x
, float y
) : DOMSVGPathSeg() {
288 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoRel
,
289 dom::SVGPathSeg_Binding::PATHSEG_LINETO_REL
)
292 void SetX(float aX
, ErrorResult
& rv
);
294 void SetY(float aY
, ErrorResult
& rv
);
300 class DOMSVGPathSegCurvetoCubicAbs
: public DOMSVGPathSeg
{
302 DOMSVGPathSegCurvetoCubicAbs(float x1
, float y1
, float x2
, float y2
, float x
,
314 void SetX(float aX
, ErrorResult
& rv
);
316 void SetY(float aY
, ErrorResult
& rv
);
318 void SetX1(float aX1
, ErrorResult
& rv
);
320 void SetY1(float aY1
, ErrorResult
& rv
);
322 void SetX2(float aX2
, ErrorResult
& rv
);
324 void SetY2(float aY2
, ErrorResult
& rv
);
326 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
327 CurvetoCubicAbs
, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS
)
333 class DOMSVGPathSegCurvetoCubicRel
: public DOMSVGPathSeg
{
335 DOMSVGPathSegCurvetoCubicRel(float x1
, float y1
, float x2
, float y2
, float x
,
346 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
347 CurvetoCubicRel
, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL
)
350 void SetX(float aX
, ErrorResult
& rv
);
352 void SetY(float aY
, ErrorResult
& rv
);
354 void SetX1(float aX1
, ErrorResult
& rv
);
356 void SetY1(float aY1
, ErrorResult
& rv
);
358 void SetX2(float aX2
, ErrorResult
& rv
);
360 void SetY2(float aY2
, ErrorResult
& rv
);
366 class DOMSVGPathSegCurvetoQuadraticAbs
: public DOMSVGPathSeg
{
368 DOMSVGPathSegCurvetoQuadraticAbs(float x1
, float y1
, float x
, float y
)
376 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
378 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS
)
381 void SetX(float aX
, ErrorResult
& rv
);
383 void SetY(float aY
, ErrorResult
& rv
);
385 void SetX1(float aX1
, ErrorResult
& rv
);
387 void SetY1(float aY1
, ErrorResult
& rv
);
393 class DOMSVGPathSegCurvetoQuadraticRel
: public DOMSVGPathSeg
{
395 DOMSVGPathSegCurvetoQuadraticRel(float x1
, float y1
, float x
, float y
)
403 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
405 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL
)
408 void SetX(float aX
, ErrorResult
& rv
);
410 void SetY(float aY
, ErrorResult
& rv
);
412 void SetX1(float aX1
, ErrorResult
& rv
);
414 void SetY1(float aY1
, ErrorResult
& rv
);
420 class DOMSVGPathSegArcAbs
: public DOMSVGPathSeg
{
422 DOMSVGPathSegArcAbs(float r1
, float r2
, float angle
, bool largeArcFlag
,
423 bool sweepFlag
, float x
, float y
)
428 mArgs
[3] = largeArcFlag
;
429 mArgs
[4] = sweepFlag
;
434 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcAbs
,
435 dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS
)
438 void SetX(float aX
, ErrorResult
& rv
);
440 void SetY(float aY
, ErrorResult
& rv
);
442 void SetR1(float aR1
, ErrorResult
& rv
);
444 void SetR2(float aR2
, ErrorResult
& rv
);
446 void SetAngle(float aAngle
, ErrorResult
& rv
);
448 void SetLargeArcFlag(bool aLargeArcFlag
, ErrorResult
& rv
);
450 void SetSweepFlag(bool aSweepFlag
, ErrorResult
& rv
);
456 class DOMSVGPathSegArcRel
: public DOMSVGPathSeg
{
458 DOMSVGPathSegArcRel(float r1
, float r2
, float angle
, bool largeArcFlag
,
459 bool sweepFlag
, float x
, float y
)
464 mArgs
[3] = largeArcFlag
;
465 mArgs
[4] = sweepFlag
;
470 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcRel
,
471 dom::SVGPathSeg_Binding::PATHSEG_ARC_REL
)
474 void SetX(float aX
, ErrorResult
& rv
);
476 void SetY(float aY
, ErrorResult
& rv
);
478 void SetR1(float aR1
, ErrorResult
& rv
);
480 void SetR2(float aR2
, ErrorResult
& rv
);
482 void SetAngle(float aAngle
, ErrorResult
& rv
);
484 void SetLargeArcFlag(bool aLargeArcFlag
, ErrorResult
& rv
);
486 void SetSweepFlag(bool aSweepFlag
, ErrorResult
& rv
);
492 class DOMSVGPathSegLinetoHorizontalAbs
: public DOMSVGPathSeg
{
494 explicit DOMSVGPathSegLinetoHorizontalAbs(float x
) : DOMSVGPathSeg() {
498 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
500 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_ABS
)
503 void SetX(float aX
, ErrorResult
& rv
);
509 class DOMSVGPathSegLinetoHorizontalRel
: public DOMSVGPathSeg
{
511 explicit DOMSVGPathSegLinetoHorizontalRel(float x
) : DOMSVGPathSeg() {
515 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
517 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_REL
)
520 void SetX(float aX
, ErrorResult
& rv
);
526 class DOMSVGPathSegLinetoVerticalAbs
: public DOMSVGPathSeg
{
528 explicit DOMSVGPathSegLinetoVerticalAbs(float y
) : DOMSVGPathSeg() {
532 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
533 LinetoVerticalAbs
, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_ABS
)
536 void SetY(float aY
, ErrorResult
& rv
);
542 class DOMSVGPathSegLinetoVerticalRel
: public DOMSVGPathSeg
{
544 explicit DOMSVGPathSegLinetoVerticalRel(float y
) : DOMSVGPathSeg() {
548 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
549 LinetoVerticalRel
, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_REL
)
552 void SetY(float aY
, ErrorResult
& rv
);
558 class DOMSVGPathSegCurvetoCubicSmoothAbs
: public DOMSVGPathSeg
{
560 DOMSVGPathSegCurvetoCubicSmoothAbs(float x2
, float y2
, float x
, float y
)
568 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
569 CurvetoCubicSmoothAbs
,
570 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
)
573 void SetX(float aX
, ErrorResult
& rv
);
575 void SetY(float aY
, ErrorResult
& rv
);
577 void SetX2(float aX2
, ErrorResult
& rv
);
579 void SetY2(float aY2
, ErrorResult
& rv
);
585 class DOMSVGPathSegCurvetoCubicSmoothRel
: public DOMSVGPathSeg
{
587 DOMSVGPathSegCurvetoCubicSmoothRel(float x2
, float y2
, float x
, float y
)
595 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
596 CurvetoCubicSmoothRel
,
597 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL
)
600 void SetX(float aX
, ErrorResult
& rv
);
602 void SetY(float aY
, ErrorResult
& rv
);
604 void SetX2(float aX2
, ErrorResult
& rv
);
606 void SetY2(float aY2
, ErrorResult
& rv
);
612 class DOMSVGPathSegCurvetoQuadraticSmoothAbs
: public DOMSVGPathSeg
{
614 DOMSVGPathSegCurvetoQuadraticSmoothAbs(float x
, float y
) : DOMSVGPathSeg() {
619 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
620 CurvetoQuadraticSmoothAbs
,
621 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
)
624 void SetX(float aX
, ErrorResult
& rv
);
626 void SetY(float aY
, ErrorResult
& rv
);
632 class DOMSVGPathSegCurvetoQuadraticSmoothRel
: public DOMSVGPathSeg
{
634 DOMSVGPathSegCurvetoQuadraticSmoothRel(float x
, float y
) : DOMSVGPathSeg() {
639 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
640 CurvetoQuadraticSmoothRel
,
641 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
)
644 void SetX(float aX
, ErrorResult
& rv
);
646 void SetY(float aY
, ErrorResult
& rv
);
653 } // namespace mozilla
655 #undef MOZ_SVG_LIST_INDEX_BIT_COUNT
657 #endif // DOM_SVG_DOMSVGPATHSEG_H_