Bug 1805294 [wpt PR 37463] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / dom / svg / DOMSVGPathSeg.h
blob706a2040640bae28636d78bd595aa548abe65d66
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 {
20 class SVGElement;
22 #define CHECK_ARG_COUNT_IN_SYNC(segType) \
23 MOZ_ASSERT( \
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); \
32 memcpy( \
33 mArgs, aArgs, \
34 SVGPathSegUtils::ArgCountForType(uint32_t(segType)) * sizeof(float)); \
35 } \
36 DOMSVGPathSeg##segName(DOMSVGPathSegList* aList, uint32_t aListIndex, \
37 bool aIsAnimValItem) \
38 : DOMSVGPathSeg(aList, aListIndex, aIsAnimValItem) { \
39 CHECK_ARG_COUNT_IN_SYNC(segType); \
40 } \
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); \
47 } \
48 float* PtrToMemberArgs() override { return mArgs; } \
50 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) \
51 override { \
52 return dom::SVGPathSeg##segName##_Binding::Wrap(aCx, this, aGivenProto); \
55 /**
56 * Class DOMSVGPathSeg
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 {
74 template <class T>
75 friend class AutoChangePathSegListNotifier;
77 public:
78 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGPathSeg)
79 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGPathSeg)
81 /**
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,
87 bool aIsAnimValItem);
89 /**
90 * Create an unowned copy of this object. The caller is responsible for the
91 * first AddRef()!
93 virtual DOMSVGPathSeg* Clone() = 0;
95 bool IsInList() const { return !!mList; }
97 /**
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;
149 // WebIDL
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;
158 protected:
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
168 * attribute.
170 DOMSVGPathSeg();
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.
176 if (mList) {
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
190 * animVal items.
192 float* InternalItem();
194 virtual float* PtrToMemberArgs() = 0;
196 #ifdef DEBUG
197 bool IndexIsValid();
198 #endif
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 {
210 public:
211 DOMSVGPathSegClosePath() : DOMSVGPathSeg() {}
213 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ClosePath,
214 dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH)
216 protected:
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.
220 float mArgs[1];
223 class DOMSVGPathSegMovetoAbs : public DOMSVGPathSeg {
224 public:
225 DOMSVGPathSegMovetoAbs(float x, float y) : DOMSVGPathSeg() {
226 mArgs[0] = x;
227 mArgs[1] = y;
230 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoAbs,
231 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS)
233 float X();
234 void SetX(float aX, ErrorResult& rv);
235 float Y();
236 void SetY(float aY, ErrorResult& rv);
238 protected:
239 float mArgs[2];
242 class DOMSVGPathSegMovetoRel : public DOMSVGPathSeg {
243 public:
244 DOMSVGPathSegMovetoRel(float x, float y) : DOMSVGPathSeg() {
245 mArgs[0] = x;
246 mArgs[1] = y;
249 IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoRel,
250 dom::SVGPathSeg_Binding::PATHSEG_MOVETO_REL)
252 float X();
253 void SetX(float aX, ErrorResult& rv);
254 float Y();
255 void SetY(float aY, ErrorResult& rv);
257 protected:
258 float mArgs[2];
261 class DOMSVGPathSegLinetoAbs : public DOMSVGPathSeg {
262 public:
263 DOMSVGPathSegLinetoAbs(float x, float y) : DOMSVGPathSeg() {
264 mArgs[0] = x;
265 mArgs[1] = y;
268 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoAbs,
269 dom::SVGPathSeg_Binding::PATHSEG_LINETO_ABS)
271 float X();
272 void SetX(float aX, ErrorResult& rv);
273 float Y();
274 void SetY(float aY, ErrorResult& rv);
276 protected:
277 float mArgs[2];
280 class DOMSVGPathSegLinetoRel : public DOMSVGPathSeg {
281 public:
282 DOMSVGPathSegLinetoRel(float x, float y) : DOMSVGPathSeg() {
283 mArgs[0] = x;
284 mArgs[1] = y;
287 IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoRel,
288 dom::SVGPathSeg_Binding::PATHSEG_LINETO_REL)
290 float X();
291 void SetX(float aX, ErrorResult& rv);
292 float Y();
293 void SetY(float aY, ErrorResult& rv);
295 protected:
296 float mArgs[2];
299 class DOMSVGPathSegCurvetoCubicAbs : public DOMSVGPathSeg {
300 public:
301 DOMSVGPathSegCurvetoCubicAbs(float x1, float y1, float x2, float y2, float x,
302 float y)
303 : DOMSVGPathSeg() {
304 mArgs[0] = x1;
305 mArgs[1] = y1;
306 mArgs[2] = x2;
307 mArgs[3] = y2;
308 mArgs[4] = x;
309 mArgs[5] = y;
312 float X();
313 void SetX(float aX, ErrorResult& rv);
314 float Y();
315 void SetY(float aY, ErrorResult& rv);
316 float X1();
317 void SetX1(float aX1, ErrorResult& rv);
318 float Y1();
319 void SetY1(float aY1, ErrorResult& rv);
320 float X2();
321 void SetX2(float aX2, ErrorResult& rv);
322 float Y2();
323 void SetY2(float aY2, ErrorResult& rv);
325 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
326 CurvetoCubicAbs, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS)
328 protected:
329 float mArgs[6];
332 class DOMSVGPathSegCurvetoCubicRel : public DOMSVGPathSeg {
333 public:
334 DOMSVGPathSegCurvetoCubicRel(float x1, float y1, float x2, float y2, float x,
335 float y)
336 : DOMSVGPathSeg() {
337 mArgs[0] = x1;
338 mArgs[1] = y1;
339 mArgs[2] = x2;
340 mArgs[3] = y2;
341 mArgs[4] = x;
342 mArgs[5] = y;
345 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
346 CurvetoCubicRel, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL)
348 float X();
349 void SetX(float aX, ErrorResult& rv);
350 float Y();
351 void SetY(float aY, ErrorResult& rv);
352 float X1();
353 void SetX1(float aX1, ErrorResult& rv);
354 float Y1();
355 void SetY1(float aY1, ErrorResult& rv);
356 float X2();
357 void SetX2(float aX2, ErrorResult& rv);
358 float Y2();
359 void SetY2(float aY2, ErrorResult& rv);
361 protected:
362 float mArgs[6];
365 class DOMSVGPathSegCurvetoQuadraticAbs : public DOMSVGPathSeg {
366 public:
367 DOMSVGPathSegCurvetoQuadraticAbs(float x1, float y1, float x, float y)
368 : DOMSVGPathSeg() {
369 mArgs[0] = x1;
370 mArgs[1] = y1;
371 mArgs[2] = x;
372 mArgs[3] = y;
375 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
376 CurvetoQuadraticAbs,
377 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS)
379 float X();
380 void SetX(float aX, ErrorResult& rv);
381 float Y();
382 void SetY(float aY, ErrorResult& rv);
383 float X1();
384 void SetX1(float aX1, ErrorResult& rv);
385 float Y1();
386 void SetY1(float aY1, ErrorResult& rv);
388 protected:
389 float mArgs[4];
392 class DOMSVGPathSegCurvetoQuadraticRel : public DOMSVGPathSeg {
393 public:
394 DOMSVGPathSegCurvetoQuadraticRel(float x1, float y1, float x, float y)
395 : DOMSVGPathSeg() {
396 mArgs[0] = x1;
397 mArgs[1] = y1;
398 mArgs[2] = x;
399 mArgs[3] = y;
402 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
403 CurvetoQuadraticRel,
404 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL)
406 float X();
407 void SetX(float aX, ErrorResult& rv);
408 float Y();
409 void SetY(float aY, ErrorResult& rv);
410 float X1();
411 void SetX1(float aX1, ErrorResult& rv);
412 float Y1();
413 void SetY1(float aY1, ErrorResult& rv);
415 protected:
416 float mArgs[4];
419 class DOMSVGPathSegArcAbs : public DOMSVGPathSeg {
420 public:
421 DOMSVGPathSegArcAbs(float r1, float r2, float angle, bool largeArcFlag,
422 bool sweepFlag, float x, float y)
423 : DOMSVGPathSeg() {
424 mArgs[0] = r1;
425 mArgs[1] = r2;
426 mArgs[2] = angle;
427 mArgs[3] = largeArcFlag;
428 mArgs[4] = sweepFlag;
429 mArgs[5] = x;
430 mArgs[6] = y;
433 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcAbs,
434 dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS)
436 float X();
437 void SetX(float aX, ErrorResult& rv);
438 float Y();
439 void SetY(float aY, ErrorResult& rv);
440 float R1();
441 void SetR1(float aR1, ErrorResult& rv);
442 float R2();
443 void SetR2(float aR2, ErrorResult& rv);
444 float Angle();
445 void SetAngle(float aAngle, ErrorResult& rv);
446 bool LargeArcFlag();
447 void SetLargeArcFlag(bool aLargeArcFlag, ErrorResult& rv);
448 bool SweepFlag();
449 void SetSweepFlag(bool aSweepFlag, ErrorResult& rv);
451 protected:
452 float mArgs[7];
455 class DOMSVGPathSegArcRel : public DOMSVGPathSeg {
456 public:
457 DOMSVGPathSegArcRel(float r1, float r2, float angle, bool largeArcFlag,
458 bool sweepFlag, float x, float y)
459 : DOMSVGPathSeg() {
460 mArgs[0] = r1;
461 mArgs[1] = r2;
462 mArgs[2] = angle;
463 mArgs[3] = largeArcFlag;
464 mArgs[4] = sweepFlag;
465 mArgs[5] = x;
466 mArgs[6] = y;
469 IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcRel,
470 dom::SVGPathSeg_Binding::PATHSEG_ARC_REL)
472 float X();
473 void SetX(float aX, ErrorResult& rv);
474 float Y();
475 void SetY(float aY, ErrorResult& rv);
476 float R1();
477 void SetR1(float aR1, ErrorResult& rv);
478 float R2();
479 void SetR2(float aR2, ErrorResult& rv);
480 float Angle();
481 void SetAngle(float aAngle, ErrorResult& rv);
482 bool LargeArcFlag();
483 void SetLargeArcFlag(bool aLargeArcFlag, ErrorResult& rv);
484 bool SweepFlag();
485 void SetSweepFlag(bool aSweepFlag, ErrorResult& rv);
487 protected:
488 float mArgs[7];
491 class DOMSVGPathSegLinetoHorizontalAbs : public DOMSVGPathSeg {
492 public:
493 explicit DOMSVGPathSegLinetoHorizontalAbs(float x) : DOMSVGPathSeg() {
494 mArgs[0] = x;
497 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
498 LinetoHorizontalAbs,
499 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_ABS)
501 float X();
502 void SetX(float aX, ErrorResult& rv);
504 protected:
505 float mArgs[1];
508 class DOMSVGPathSegLinetoHorizontalRel : public DOMSVGPathSeg {
509 public:
510 explicit DOMSVGPathSegLinetoHorizontalRel(float x) : DOMSVGPathSeg() {
511 mArgs[0] = x;
514 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
515 LinetoHorizontalRel,
516 dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_REL)
518 float X();
519 void SetX(float aX, ErrorResult& rv);
521 protected:
522 float mArgs[1];
525 class DOMSVGPathSegLinetoVerticalAbs : public DOMSVGPathSeg {
526 public:
527 explicit DOMSVGPathSegLinetoVerticalAbs(float y) : DOMSVGPathSeg() {
528 mArgs[0] = y;
531 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
532 LinetoVerticalAbs, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_ABS)
534 float Y();
535 void SetY(float aY, ErrorResult& rv);
537 protected:
538 float mArgs[1];
541 class DOMSVGPathSegLinetoVerticalRel : public DOMSVGPathSeg {
542 public:
543 explicit DOMSVGPathSegLinetoVerticalRel(float y) : DOMSVGPathSeg() {
544 mArgs[0] = y;
547 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
548 LinetoVerticalRel, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_REL)
550 float Y();
551 void SetY(float aY, ErrorResult& rv);
553 protected:
554 float mArgs[1];
557 class DOMSVGPathSegCurvetoCubicSmoothAbs : public DOMSVGPathSeg {
558 public:
559 DOMSVGPathSegCurvetoCubicSmoothAbs(float x2, float y2, float x, float y)
560 : DOMSVGPathSeg() {
561 mArgs[0] = x2;
562 mArgs[1] = y2;
563 mArgs[2] = x;
564 mArgs[3] = y;
567 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
568 CurvetoCubicSmoothAbs,
569 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS)
571 float X();
572 void SetX(float aX, ErrorResult& rv);
573 float Y();
574 void SetY(float aY, ErrorResult& rv);
575 float X2();
576 void SetX2(float aX2, ErrorResult& rv);
577 float Y2();
578 void SetY2(float aY2, ErrorResult& rv);
580 protected:
581 float mArgs[4];
584 class DOMSVGPathSegCurvetoCubicSmoothRel : public DOMSVGPathSeg {
585 public:
586 DOMSVGPathSegCurvetoCubicSmoothRel(float x2, float y2, float x, float y)
587 : DOMSVGPathSeg() {
588 mArgs[0] = x2;
589 mArgs[1] = y2;
590 mArgs[2] = x;
591 mArgs[3] = y;
594 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
595 CurvetoCubicSmoothRel,
596 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL)
598 float X();
599 void SetX(float aX, ErrorResult& rv);
600 float Y();
601 void SetY(float aY, ErrorResult& rv);
602 float X2();
603 void SetX2(float aX2, ErrorResult& rv);
604 float Y2();
605 void SetY2(float aY2, ErrorResult& rv);
607 protected:
608 float mArgs[4];
611 class DOMSVGPathSegCurvetoQuadraticSmoothAbs : public DOMSVGPathSeg {
612 public:
613 DOMSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y) : DOMSVGPathSeg() {
614 mArgs[0] = x;
615 mArgs[1] = y;
618 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
619 CurvetoQuadraticSmoothAbs,
620 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS)
622 float X();
623 void SetX(float aX, ErrorResult& rv);
624 float Y();
625 void SetY(float aY, ErrorResult& rv);
627 protected:
628 float mArgs[2];
631 class DOMSVGPathSegCurvetoQuadraticSmoothRel : public DOMSVGPathSeg {
632 public:
633 DOMSVGPathSegCurvetoQuadraticSmoothRel(float x, float y) : DOMSVGPathSeg() {
634 mArgs[0] = x;
635 mArgs[1] = y;
638 IMPL_SVGPATHSEG_SUBCLASS_COMMON(
639 CurvetoQuadraticSmoothRel,
640 dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL)
642 float X();
643 void SetX(float aX, ErrorResult& rv);
644 float Y();
645 void SetY(float aY, ErrorResult& rv);
647 protected:
648 float mArgs[2];
651 } // namespace mozilla::dom
653 #undef MOZ_SVG_LIST_INDEX_BIT_COUNT
655 #endif // DOM_SVG_DOMSVGPATHSEG_H_