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/. */
6
7 #include "mozilla/dom/DOMQuad.h"
8
9 #include <algorithm>
10 #include "mozilla/FloatingPoint.h"
11 #include "mozilla/MacroForEach.h"
12 #include "mozilla/dom/BindingDeclarations.h"
13 #include "mozilla/dom/DOMPoint.h"
14 #include "mozilla/dom/DOMQuadBinding.h"
15 #include "mozilla/dom/DOMRect.h"
16 #include "mozilla/dom/DOMRectBinding.h"
17 #include "mozilla/gfx/BasePoint.h"
18 #include "mozilla/gfx/MatrixFwd.h"
19 #include "nsIGlobalObject.h"
20
21 using namespace mozilla;
22 using namespace mozilla::dom;
23 using namespace mozilla::gfx;
24
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMQuad,mParent,mPoints[0],mPoints[1],mPoints[2],mPoints[3])25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMQuad, mParent, mPoints[0], mPoints[1],
26 mPoints[2], mPoints[3])
27
28 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMQuad, AddRef)
29 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMQuad, Release)
30
31 DOMQuad::DOMQuad(nsISupports* aParent, CSSPoint aPoints[4]) : mParent(aParent) {
32 for (uint32_t i = 0; i < 4; ++i) {
33 mPoints[i] = new DOMPoint(aParent, aPoints[i].x, aPoints[i].y);
34 }
35 }
36
DOMQuad(nsISupports * aParent)37 DOMQuad::DOMQuad(nsISupports* aParent) : mParent(aParent) {}
38
39 DOMQuad::~DOMQuad() = default;
40
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)41 JSObject* DOMQuad::WrapObject(JSContext* aCx,
42 JS::Handle<JSObject*> aGivenProto) {
43 return DOMQuad_Binding::Wrap(aCx, this, aGivenProto);
44 }
45
FromRect(const GlobalObject & aGlobal,const DOMRectInit & aInit)46 already_AddRefed<DOMQuad> DOMQuad::FromRect(const GlobalObject& aGlobal,
47 const DOMRectInit& aInit) {
48 nsISupports* parent = aGlobal.GetAsSupports();
49 RefPtr<DOMQuad> obj = new DOMQuad(parent);
50 obj->mPoints[0] = new DOMPoint(parent, aInit.mX, aInit.mY, 0, 1);
51 obj->mPoints[1] =
52 new DOMPoint(parent, aInit.mX + aInit.mWidth, aInit.mY, 0, 1);
53 obj->mPoints[2] = new DOMPoint(parent, aInit.mX + aInit.mWidth,
54 aInit.mY + aInit.mHeight, 0, 1);
55 obj->mPoints[3] =
56 new DOMPoint(parent, aInit.mX, aInit.mY + aInit.mHeight, 0, 1);
57 return obj.forget();
58 }
59
FromQuad(const GlobalObject & aGlobal,const DOMQuadInit & aInit)60 already_AddRefed<DOMQuad> DOMQuad::FromQuad(const GlobalObject& aGlobal,
61 const DOMQuadInit& aInit) {
62 RefPtr<DOMQuad> obj = new DOMQuad(aGlobal.GetAsSupports());
63 obj->mPoints[0] = DOMPoint::FromPoint(aGlobal, aInit.mP1);
64 obj->mPoints[1] = DOMPoint::FromPoint(aGlobal, aInit.mP2);
65 obj->mPoints[2] = DOMPoint::FromPoint(aGlobal, aInit.mP3);
66 obj->mPoints[3] = DOMPoint::FromPoint(aGlobal, aInit.mP4);
67 return obj.forget();
68 }
69
Constructor(const GlobalObject & aGlobal,const DOMPointInit & aP1,const DOMPointInit & aP2,const DOMPointInit & aP3,const DOMPointInit & aP4)70 already_AddRefed<DOMQuad> DOMQuad::Constructor(const GlobalObject& aGlobal,
71 const DOMPointInit& aP1,
72 const DOMPointInit& aP2,
73 const DOMPointInit& aP3,
74 const DOMPointInit& aP4) {
75 RefPtr<DOMQuad> obj = new DOMQuad(aGlobal.GetAsSupports());
76 obj->mPoints[0] = DOMPoint::FromPoint(aGlobal, aP1);
77 obj->mPoints[1] = DOMPoint::FromPoint(aGlobal, aP2);
78 obj->mPoints[2] = DOMPoint::FromPoint(aGlobal, aP3);
79 obj->mPoints[3] = DOMPoint::FromPoint(aGlobal, aP4);
80 return obj.forget();
81 }
82
Constructor(const GlobalObject & aGlobal,const DOMRectReadOnly & aRect)83 already_AddRefed<DOMQuad> DOMQuad::Constructor(const GlobalObject& aGlobal,
84 const DOMRectReadOnly& aRect) {
85 CSSPoint points[4];
86 Float x = aRect.X(), y = aRect.Y(), w = aRect.Width(), h = aRect.Height();
87 points[0] = CSSPoint(x, y);
88 points[1] = CSSPoint(x + w, y);
89 points[2] = CSSPoint(x + w, y + h);
90 points[3] = CSSPoint(x, y + h);
91 RefPtr<DOMQuad> obj = new DOMQuad(aGlobal.GetAsSupports(), points);
92 return obj.forget();
93 }
94
GetHorizontalMinMax(double * aX1,double * aX2) const95 void DOMQuad::GetHorizontalMinMax(double* aX1, double* aX2) const {
96 double x1, x2;
97 x1 = x2 = Point(0)->X();
98 for (uint32_t i = 1; i < 4; ++i) {
99 double x = Point(i)->X();
100 x1 = NaNSafeMin(x1, x);
101 x2 = NaNSafeMax(x2, x);
102 }
103 *aX1 = x1;
104 *aX2 = x2;
105 }
106
GetVerticalMinMax(double * aY1,double * aY2) const107 void DOMQuad::GetVerticalMinMax(double* aY1, double* aY2) const {
108 double y1, y2;
109 y1 = y2 = Point(0)->Y();
110 for (uint32_t i = 1; i < 4; ++i) {
111 double y = Point(i)->Y();
112 y1 = NaNSafeMin(y1, y);
113 y2 = NaNSafeMax(y2, y);
114 }
115 *aY1 = y1;
116 *aY2 = y2;
117 }
118
GetBounds() const119 already_AddRefed<DOMRectReadOnly> DOMQuad::GetBounds() const {
120 double x1, x2;
121 double y1, y2;
122
123 GetHorizontalMinMax(&x1, &x2);
124 GetVerticalMinMax(&y1, &y2);
125
126 RefPtr<DOMRectReadOnly> rval =
127 new DOMRectReadOnly(GetParentObject(), x1, y1, x2 - x1, y2 - y1);
128 return rval.forget();
129 }
130
131 // https://drafts.fxtf.org/geometry/#structured-serialization
WriteStructuredClone(JSContext * aCx,JSStructuredCloneWriter * aWriter) const132 bool DOMQuad::WriteStructuredClone(JSContext* aCx,
133 JSStructuredCloneWriter* aWriter) const {
134 for (const auto& point : mPoints) {
135 if (!point->WriteStructuredClone(aCx, aWriter)) {
136 return false;
137 }
138 }
139 return true;
140 }
141
142 // static
ReadStructuredClone(JSContext * aCx,nsIGlobalObject * aGlobal,JSStructuredCloneReader * aReader)143 already_AddRefed<DOMQuad> DOMQuad::ReadStructuredClone(
144 JSContext* aCx, nsIGlobalObject* aGlobal,
145 JSStructuredCloneReader* aReader) {
146 RefPtr<DOMQuad> quad = new DOMQuad(aGlobal);
147 for (auto& point : quad->mPoints) {
148 point = DOMPoint::ReadStructuredClone(aCx, aGlobal, aReader);
149 if (!point) {
150 return nullptr;
151 }
152 }
153 return quad.forget();
154 }
155