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/SVGMatrix.h"
8 #include "nsError.h"
9 #include <math.h>
10 #include "mozilla/dom/SVGMatrixBinding.h"
11 #include "mozilla/FloatingPoint.h"
12
13 const double radPerDegree = 2.0 * M_PI / 360.0;
14
15 namespace mozilla {
16 namespace dom {
17
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(SVGMatrix,mTransform)18 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(SVGMatrix, mTransform)
19
20 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGMatrix, AddRef)
21 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGMatrix, Release)
22
23 SVGTransform*
24 SVGMatrix::GetParentObject() const
25 {
26 return mTransform;
27 }
28
29 JSObject*
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)30 SVGMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
31 {
32 return SVGMatrixBinding::Wrap(aCx, this, aGivenProto);
33 }
34
35 void
SetA(float aA,ErrorResult & rv)36 SVGMatrix::SetA(float aA, ErrorResult& rv)
37 {
38 if (IsAnimVal()) {
39 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
40 return;
41 }
42
43 gfxMatrix mx = GetMatrix();
44 mx._11 = aA;
45 SetMatrix(mx);
46 }
47
48 void
SetB(float aB,ErrorResult & rv)49 SVGMatrix::SetB(float aB, ErrorResult& rv)
50 {
51 if (IsAnimVal()) {
52 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
53 return;
54 }
55
56 gfxMatrix mx = GetMatrix();
57 mx._12 = aB;
58 SetMatrix(mx);
59 }
60
61 void
SetC(float aC,ErrorResult & rv)62 SVGMatrix::SetC(float aC, ErrorResult& rv)
63 {
64 if (IsAnimVal()) {
65 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
66 return;
67 }
68
69 gfxMatrix mx = GetMatrix();
70 mx._21 = aC;
71 SetMatrix(mx);
72 }
73
74 void
SetD(float aD,ErrorResult & rv)75 SVGMatrix::SetD(float aD, ErrorResult& rv)
76 {
77 if (IsAnimVal()) {
78 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
79 return;
80 }
81
82 gfxMatrix mx = GetMatrix();
83 mx._22 = aD;
84 SetMatrix(mx);
85 }
86
87 void
SetE(float aE,ErrorResult & rv)88 SVGMatrix::SetE(float aE, ErrorResult& rv)
89 {
90 if (IsAnimVal()) {
91 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
92 return;
93 }
94
95 gfxMatrix mx = GetMatrix();
96 mx._31 = aE;
97 SetMatrix(mx);
98 }
99
100 void
SetF(float aF,ErrorResult & rv)101 SVGMatrix::SetF(float aF, ErrorResult& rv)
102 {
103 if (IsAnimVal()) {
104 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
105 return;
106 }
107
108 gfxMatrix mx = GetMatrix();
109 mx._32 = aF;
110 SetMatrix(mx);
111 }
112
113 already_AddRefed<SVGMatrix>
Multiply(SVGMatrix & aMatrix)114 SVGMatrix::Multiply(SVGMatrix& aMatrix)
115 {
116 RefPtr<SVGMatrix> matrix = new SVGMatrix(aMatrix.GetMatrix() * GetMatrix());
117 return matrix.forget();
118 }
119
120 already_AddRefed<SVGMatrix>
Inverse(ErrorResult & rv)121 SVGMatrix::Inverse(ErrorResult& rv)
122 {
123 gfxMatrix mat = GetMatrix();
124 if (!mat.Invert()) {
125 rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
126 return nullptr;
127 }
128 RefPtr<SVGMatrix> matrix = new SVGMatrix(mat);
129 return matrix.forget();
130 }
131
132 already_AddRefed<SVGMatrix>
Translate(float x,float y)133 SVGMatrix::Translate(float x, float y)
134 {
135 RefPtr<SVGMatrix> matrix =
136 new SVGMatrix(gfxMatrix(GetMatrix()).Translate(gfxPoint(x, y)));
137 return matrix.forget();
138 }
139
140 already_AddRefed<SVGMatrix>
Scale(float scaleFactor)141 SVGMatrix::Scale(float scaleFactor)
142 {
143 return ScaleNonUniform(scaleFactor, scaleFactor);
144 }
145
146 already_AddRefed<SVGMatrix>
ScaleNonUniform(float scaleFactorX,float scaleFactorY)147 SVGMatrix::ScaleNonUniform(float scaleFactorX,
148 float scaleFactorY)
149 {
150 RefPtr<SVGMatrix> matrix =
151 new SVGMatrix(gfxMatrix(GetMatrix()).Scale(scaleFactorX, scaleFactorY));
152 return matrix.forget();
153 }
154
155 already_AddRefed<SVGMatrix>
Rotate(float angle)156 SVGMatrix::Rotate(float angle)
157 {
158 RefPtr<SVGMatrix> matrix =
159 new SVGMatrix(gfxMatrix(GetMatrix()).Rotate(angle*radPerDegree));
160 return matrix.forget();
161 }
162
163 already_AddRefed<SVGMatrix>
RotateFromVector(float x,float y,ErrorResult & rv)164 SVGMatrix::RotateFromVector(float x, float y, ErrorResult& rv)
165 {
166 if (x == 0.0 || y == 0.0) {
167 rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
168 return nullptr;
169 }
170
171 RefPtr<SVGMatrix> matrix =
172 new SVGMatrix(gfxMatrix(GetMatrix()).Rotate(atan2(y, x)));
173 return matrix.forget();
174 }
175
176 already_AddRefed<SVGMatrix>
FlipX()177 SVGMatrix::FlipX()
178 {
179 const gfxMatrix& mx = GetMatrix();
180 RefPtr<SVGMatrix> matrix =
181 new SVGMatrix(gfxMatrix(-mx._11, -mx._12, mx._21, mx._22, mx._31, mx._32));
182 return matrix.forget();
183 }
184
185 already_AddRefed<SVGMatrix>
FlipY()186 SVGMatrix::FlipY()
187 {
188 const gfxMatrix& mx = GetMatrix();
189 RefPtr<SVGMatrix> matrix =
190 new SVGMatrix(gfxMatrix(mx._11, mx._12, -mx._21, -mx._22, mx._31, mx._32));
191 return matrix.forget();
192 }
193
194 already_AddRefed<SVGMatrix>
SkewX(float angle,ErrorResult & rv)195 SVGMatrix::SkewX(float angle, ErrorResult& rv)
196 {
197 double ta = tan( angle*radPerDegree );
198 if (!IsFinite(ta)) {
199 rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
200 return nullptr;
201 }
202
203 const gfxMatrix& mx = GetMatrix();
204 gfxMatrix skewMx(mx._11, mx._12,
205 (float) (mx._21 + mx._11*ta), (float) (mx._22 + mx._12*ta),
206 mx._31, mx._32);
207 RefPtr<SVGMatrix> matrix = new SVGMatrix(skewMx);
208 return matrix.forget();
209 }
210
211 already_AddRefed<SVGMatrix>
SkewY(float angle,ErrorResult & rv)212 SVGMatrix::SkewY(float angle, ErrorResult& rv)
213 {
214 double ta = tan( angle*radPerDegree );
215 if (!IsFinite(ta)) {
216 rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
217 return nullptr;
218 }
219
220 const gfxMatrix& mx = GetMatrix();
221 gfxMatrix skewMx((float) (mx._11 + mx._21*ta), (float) (mx._12 + mx._22*ta),
222 mx._21, mx._22,
223 mx._31, mx._32);
224
225 RefPtr<SVGMatrix> matrix = new SVGMatrix(skewMx);
226 return matrix.forget();
227 }
228
229 } // namespace dom
230 } // namespace mozilla
231