1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is the Mozilla SVG project.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Crocodile Clips Ltd..
20 : * Portions created by the Initial Developer are Copyright (C) 2001
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "DOMSVGMatrix.h"
41 : #include "nsDOMError.h"
42 : #include <math.h>
43 : #include "nsContentUtils.h"
44 :
45 : const double radPerDegree = 2.0*3.1415926535 / 360.0;
46 :
47 : namespace mozilla {
48 :
49 : //----------------------------------------------------------------------
50 : // nsISupports methods:
51 :
52 : // Make sure we clear the weak ref in the owning transform (if there is one)
53 : // upon unlink.
54 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGMatrix)
55 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGMatrix)
56 0 : if (tmp->mTransform) {
57 0 : tmp->mTransform->ClearMatrixTearoff(tmp);
58 : }
59 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransform)
60 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
61 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGMatrix)
62 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTransform)
63 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
64 :
65 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGMatrix)
66 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGMatrix)
67 :
68 : } // namespace mozilla
69 : DOMCI_DATA(SVGMatrix, mozilla::DOMSVGMatrix)
70 : namespace mozilla {
71 :
72 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGMatrix)
73 0 : NS_INTERFACE_MAP_ENTRY(mozilla::DOMSVGMatrix) // pseudo-interface
74 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGMatrix)
75 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
76 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMatrix)
77 0 : NS_INTERFACE_MAP_END
78 :
79 : //----------------------------------------------------------------------
80 : // nsIDOMSVGMatrix methods:
81 :
82 : /* attribute float a; */
83 0 : NS_IMETHODIMP DOMSVGMatrix::GetA(float *aA)
84 : {
85 0 : *aA = static_cast<float>(Matrix().xx);
86 0 : return NS_OK;
87 : }
88 0 : NS_IMETHODIMP DOMSVGMatrix::SetA(float aA)
89 : {
90 0 : if (IsAnimVal()) {
91 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
92 : }
93 0 : NS_ENSURE_FINITE(aA, NS_ERROR_ILLEGAL_VALUE);
94 :
95 0 : gfxMatrix mx = Matrix();
96 0 : mx.xx = aA;
97 0 : SetMatrix(mx);
98 0 : return NS_OK;
99 : }
100 :
101 : /* attribute float b; */
102 0 : NS_IMETHODIMP DOMSVGMatrix::GetB(float *aB)
103 : {
104 0 : *aB = static_cast<float>(Matrix().yx);
105 0 : return NS_OK;
106 : }
107 0 : NS_IMETHODIMP DOMSVGMatrix::SetB(float aB)
108 : {
109 0 : if (IsAnimVal()) {
110 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
111 : }
112 0 : NS_ENSURE_FINITE(aB, NS_ERROR_ILLEGAL_VALUE);
113 :
114 0 : gfxMatrix mx = Matrix();
115 0 : mx.yx = aB;
116 0 : SetMatrix(mx);
117 0 : return NS_OK;
118 : }
119 :
120 : /* attribute float c; */
121 0 : NS_IMETHODIMP DOMSVGMatrix::GetC(float *aC)
122 : {
123 0 : *aC = static_cast<float>(Matrix().xy);
124 0 : return NS_OK;
125 : }
126 0 : NS_IMETHODIMP DOMSVGMatrix::SetC(float aC)
127 : {
128 0 : if (IsAnimVal()) {
129 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
130 : }
131 0 : NS_ENSURE_FINITE(aC, NS_ERROR_ILLEGAL_VALUE);
132 :
133 0 : gfxMatrix mx = Matrix();
134 0 : mx.xy = aC;
135 0 : SetMatrix(mx);
136 0 : return NS_OK;
137 : }
138 :
139 : /* attribute float d; */
140 0 : NS_IMETHODIMP DOMSVGMatrix::GetD(float *aD)
141 : {
142 0 : *aD = static_cast<float>(Matrix().yy);
143 0 : return NS_OK;
144 : }
145 0 : NS_IMETHODIMP DOMSVGMatrix::SetD(float aD)
146 : {
147 0 : if (IsAnimVal()) {
148 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
149 : }
150 0 : NS_ENSURE_FINITE(aD, NS_ERROR_ILLEGAL_VALUE);
151 :
152 0 : gfxMatrix mx = Matrix();
153 0 : mx.yy = aD;
154 0 : SetMatrix(mx);
155 0 : return NS_OK;
156 : }
157 :
158 : /* attribute float e; */
159 0 : NS_IMETHODIMP DOMSVGMatrix::GetE(float *aE)
160 : {
161 0 : *aE = static_cast<float>(Matrix().x0);
162 0 : return NS_OK;
163 : }
164 0 : NS_IMETHODIMP DOMSVGMatrix::SetE(float aE)
165 : {
166 0 : if (IsAnimVal()) {
167 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
168 : }
169 0 : NS_ENSURE_FINITE(aE, NS_ERROR_ILLEGAL_VALUE);
170 :
171 0 : gfxMatrix mx = Matrix();
172 0 : mx.x0 = aE;
173 0 : SetMatrix(mx);
174 0 : return NS_OK;
175 : }
176 :
177 : /* attribute float f; */
178 0 : NS_IMETHODIMP DOMSVGMatrix::GetF(float *aF)
179 : {
180 0 : *aF = static_cast<float>(Matrix().y0);
181 0 : return NS_OK;
182 : }
183 0 : NS_IMETHODIMP DOMSVGMatrix::SetF(float aF)
184 : {
185 0 : if (IsAnimVal()) {
186 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
187 : }
188 0 : NS_ENSURE_FINITE(aF, NS_ERROR_ILLEGAL_VALUE);
189 :
190 0 : gfxMatrix mx = Matrix();
191 0 : mx.y0 = aF;
192 0 : SetMatrix(mx);
193 0 : return NS_OK;
194 : }
195 :
196 : /* nsIDOMSVGMatrix multiply (in nsIDOMSVGMatrix secondMatrix); */
197 0 : NS_IMETHODIMP DOMSVGMatrix::Multiply(nsIDOMSVGMatrix *secondMatrix,
198 : nsIDOMSVGMatrix **_retval)
199 : {
200 0 : *_retval = nsnull;
201 0 : nsCOMPtr<DOMSVGMatrix> domMatrix = do_QueryInterface(secondMatrix);
202 0 : if (!domMatrix)
203 0 : return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
204 :
205 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(domMatrix->Matrix() * Matrix()));
206 0 : return NS_OK;
207 : }
208 :
209 : /* nsIDOMSVGMatrix inverse (); */
210 0 : NS_IMETHODIMP DOMSVGMatrix::Inverse(nsIDOMSVGMatrix **_retval)
211 : {
212 0 : *_retval = nsnull;
213 0 : if (Matrix().IsSingular())
214 0 : return NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE;
215 :
216 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(gfxMatrix(Matrix()).Invert()));
217 0 : return NS_OK;
218 : }
219 :
220 : /* nsIDOMSVGMatrix translate (in float x, in float y); */
221 0 : NS_IMETHODIMP DOMSVGMatrix::Translate(float x, float y,
222 : nsIDOMSVGMatrix **_retval)
223 : {
224 0 : *_retval = nsnull;
225 0 : NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
226 :
227 0 : NS_ADDREF(*_retval =
228 0 : new DOMSVGMatrix(gfxMatrix(Matrix()).Translate(gfxPoint(x, y))));
229 0 : return NS_OK;
230 : }
231 :
232 : /* nsIDOMSVGMatrix scale (in float scaleFactor); */
233 0 : NS_IMETHODIMP DOMSVGMatrix::Scale(float scaleFactor, nsIDOMSVGMatrix **_retval)
234 : {
235 0 : return ScaleNonUniform(scaleFactor, scaleFactor, _retval);
236 : }
237 :
238 : /* nsIDOMSVGMatrix scaleNonUniform (in float scaleFactorX,
239 : * in float scaleFactorY); */
240 0 : NS_IMETHODIMP DOMSVGMatrix::ScaleNonUniform(float scaleFactorX,
241 : float scaleFactorY,
242 : nsIDOMSVGMatrix **_retval)
243 : {
244 0 : *_retval = nsnull;
245 0 : NS_ENSURE_FINITE2(scaleFactorX, scaleFactorY, NS_ERROR_ILLEGAL_VALUE);
246 :
247 0 : NS_ADDREF(*_retval =
248 0 : new DOMSVGMatrix(gfxMatrix(Matrix()).Scale(scaleFactorX, scaleFactorY)));
249 0 : return NS_OK;
250 : }
251 :
252 : /* nsIDOMSVGMatrix rotate (in float angle); */
253 0 : NS_IMETHODIMP DOMSVGMatrix::Rotate(float angle, nsIDOMSVGMatrix **_retval)
254 : {
255 0 : *_retval = nsnull;
256 0 : NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
257 :
258 0 : NS_ADDREF(*_retval =
259 0 : new DOMSVGMatrix(gfxMatrix(Matrix()).Rotate(angle*radPerDegree)));
260 0 : return NS_OK;
261 : }
262 :
263 : /* nsIDOMSVGMatrix rotateFromVector (in float x, in float y); */
264 0 : NS_IMETHODIMP DOMSVGMatrix::RotateFromVector(float x, float y,
265 : nsIDOMSVGMatrix **_retval)
266 : {
267 0 : *_retval = nsnull;
268 0 : NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
269 :
270 0 : if (x == 0.0 || y == 0.0)
271 0 : return NS_ERROR_DOM_SVG_INVALID_VALUE_ERR;
272 :
273 0 : NS_ADDREF(*_retval =
274 0 : new DOMSVGMatrix(gfxMatrix(Matrix()).Rotate(atan2(y, x))));
275 0 : return NS_OK;
276 : }
277 :
278 : /* nsIDOMSVGMatrix flipX (); */
279 0 : NS_IMETHODIMP DOMSVGMatrix::FlipX(nsIDOMSVGMatrix **_retval)
280 : {
281 0 : const gfxMatrix& mx = Matrix();
282 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(gfxMatrix(-mx.xx, -mx.yx,
283 : mx.xy, mx.yy,
284 0 : mx.x0, mx.y0)));
285 0 : return NS_OK;
286 : }
287 :
288 : /* nsIDOMSVGMatrix flipY (); */
289 0 : NS_IMETHODIMP DOMSVGMatrix::FlipY(nsIDOMSVGMatrix **_retval)
290 : {
291 0 : const gfxMatrix& mx = Matrix();
292 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(gfxMatrix(mx.xx, mx.yx,
293 : -mx.xy, -mx.yy,
294 0 : mx.x0, mx.y0)));
295 0 : return NS_OK;
296 : }
297 :
298 : /* nsIDOMSVGMatrix skewX (in float angle); */
299 0 : NS_IMETHODIMP DOMSVGMatrix::SkewX(float angle, nsIDOMSVGMatrix **_retval)
300 : {
301 0 : *_retval = nsnull;
302 0 : NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
303 :
304 0 : double ta = tan( angle*radPerDegree );
305 0 : NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
306 :
307 0 : const gfxMatrix& mx = Matrix();
308 : gfxMatrix skewMx(mx.xx, mx.yx,
309 : (float) (mx.xy + mx.xx*ta), (float) (mx.yy + mx.yx*ta),
310 0 : mx.x0, mx.y0);
311 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(skewMx));
312 0 : return NS_OK;
313 : }
314 :
315 : /* nsIDOMSVGMatrix skewY (in float angle); */
316 0 : NS_IMETHODIMP DOMSVGMatrix::SkewY(float angle, nsIDOMSVGMatrix **_retval)
317 : {
318 0 : *_retval = nsnull;
319 0 : NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
320 :
321 0 : double ta = tan( angle*radPerDegree );
322 0 : NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
323 :
324 0 : const gfxMatrix& mx = Matrix();
325 : gfxMatrix skewMx((float) (mx.xx + mx.xy*ta), (float) (mx.yx + mx.yy*ta),
326 : mx.xy, mx.yy,
327 0 : mx.x0, mx.y0);
328 0 : NS_ADDREF(*_retval = new DOMSVGMatrix(skewMx));
329 0 : return NS_OK;
330 : }
331 :
332 4392 : } // namespace mozilla
|