1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.svg;
16
17 import org.htmlunit.javascript.HtmlUnitScriptable;
18 import org.htmlunit.javascript.JavaScriptEngine;
19 import org.htmlunit.javascript.configuration.JsxClass;
20 import org.htmlunit.javascript.configuration.JsxConstructor;
21 import org.htmlunit.javascript.configuration.JsxFunction;
22 import org.htmlunit.javascript.configuration.JsxGetter;
23 import org.htmlunit.javascript.configuration.JsxSetter;
24 import org.htmlunit.javascript.host.Window;
25 import org.htmlunit.javascript.host.dom.DOMException;
26
27
28
29
30
31
32
33 @JsxClass
34 public class SVGMatrix extends HtmlUnitScriptable {
35
36 private double shearX_;
37 private double shearY_;
38 private double scaleX_;
39 private double scaleY_;
40 private double translateX_;
41 private double translateY_;
42
43
44
45
46 public SVGMatrix() {
47 super();
48
49 shearX_ = 0.0;
50 shearY_ = 0.0;
51 scaleX_ = 1.0;
52 scaleY_ = 1.0;
53 translateX_ = 0.0;
54 translateY_ = 0.0;
55 }
56
57
58
59
60 @JsxConstructor
61 public void jsConstructor() {
62
63 }
64
65
66
67
68
69 public SVGMatrix(final Window scope) {
70 this();
71 setParentScope(scope);
72 setPrototype(getPrototype(getClass()));
73 }
74
75
76
77
78
79 @JsxGetter
80 public double getA() {
81 return scaleX_;
82 }
83
84
85
86
87
88 @JsxGetter
89 public double getB() {
90 return shearY_;
91 }
92
93
94
95
96
97 @JsxGetter
98 public double getC() {
99 return shearX_;
100 }
101
102
103
104
105
106 @JsxGetter
107 public double getD() {
108 return scaleY_;
109 }
110
111
112
113
114
115 @JsxGetter
116 public double getE() {
117 return translateX_;
118 }
119
120
121
122
123
124 @JsxGetter
125 public double getF() {
126 return translateY_;
127 }
128
129
130
131
132
133 @JsxSetter
134 public void setA(final double newValue) {
135 scaleX_ = newValue;
136 }
137
138
139
140
141
142 @JsxSetter
143 public void setB(final double newValue) {
144 shearY_ = newValue;
145 }
146
147
148
149
150
151 @JsxSetter
152 public void setC(final double newValue) {
153 shearX_ = newValue;
154 }
155
156
157
158
159
160 @JsxSetter
161 public void setD(final double newValue) {
162 scaleY_ = newValue;
163 }
164
165
166
167
168
169 @JsxSetter
170 public void setE(final double newValue) {
171 translateX_ = newValue;
172 }
173
174
175
176
177
178 @JsxSetter
179 public void setF(final double newValue) {
180 translateY_ = newValue;
181 }
182
183
184
185
186
187 @JsxFunction
188 public SVGMatrix flipX() {
189 final SVGMatrix result = new SVGMatrix(getWindow());
190 result.shearX_ = shearX_;
191 result.shearY_ = -shearY_;
192 result.scaleX_ = -scaleX_;
193 result.scaleY_ = scaleY_;
194 result.translateX_ = translateX_;
195 result.translateY_ = translateY_;
196
197 return result;
198 }
199
200
201
202
203
204 @JsxFunction
205 public SVGMatrix flipY() {
206 final SVGMatrix result = new SVGMatrix(getWindow());
207 result.shearX_ = -shearX_;
208 result.shearY_ = shearY_;
209 result.scaleX_ = scaleX_;
210 result.scaleY_ = -scaleY_;
211 result.translateX_ = translateX_;
212 result.translateY_ = translateY_;
213
214 return result;
215 }
216
217
218
219
220
221 @JsxFunction
222 public SVGMatrix inverse() {
223 final double determinant = scaleX_ * scaleY_ - shearX_ * shearY_;
224
225 if (Math.abs(determinant) < 1E-10) {
226 throw JavaScriptEngine.asJavaScriptException(
227 getWindow(),
228 "Failed to execute 'inverse' on 'SVGMatrix': The matrix is not invertible.",
229 DOMException.INVALID_STATE_ERR);
230 }
231
232 final SVGMatrix result = new SVGMatrix(getWindow());
233 result.shearX_ = -shearX_ / determinant;
234 result.shearY_ = -shearY_ / determinant;
235 result.scaleX_ = scaleY_ / determinant;
236 result.scaleY_ = scaleX_ / determinant;
237 result.translateX_ = (shearX_ * translateY_ - scaleY_ * translateX_) / determinant;
238 result.translateY_ = (shearY_ * translateX_ - scaleX_ * translateY_) / determinant;
239
240 return result;
241 }
242
243
244
245
246
247
248 @JsxFunction
249 public SVGMatrix multiply(final SVGMatrix by) {
250 final SVGMatrix result = new SVGMatrix(getWindow());
251
252 result.shearX_ = by.shearX_ * scaleX_ + by.scaleY_ * shearX_;
253 result.shearY_ = by.scaleX_ * shearY_ + by.shearY_ * scaleY_;
254 result.scaleX_ = by.scaleX_ * scaleX_ + by.shearY_ * shearX_;
255 result.scaleY_ = by.shearX_ * shearY_ + by.scaleY_ * scaleY_;
256 result.translateX_ = by.translateX_ * scaleX_ + by.translateY_ * shearX_ + translateX_;
257 result.translateY_ = by.translateX_ * shearY_ + by.translateY_ * scaleY_ + translateY_;
258
259 return result;
260 }
261
262
263
264
265
266
267 @JsxFunction
268 public SVGMatrix rotate(final double angle) {
269 final double theta = Math.toRadians(angle);
270 final double sin = Math.sin(theta);
271 final double cos = Math.cos(theta);
272
273 final SVGMatrix result = new SVGMatrix(getWindow());
274
275 result.shearX_ = -sin * scaleX_ + cos * shearX_;
276 result.shearY_ = cos * shearY_ + sin * scaleY_;
277 result.scaleX_ = cos * scaleX_ + sin * shearX_;
278 result.scaleY_ = -sin * shearY_ + cos * scaleY_;
279 result.translateX_ = translateX_;
280 result.translateY_ = translateY_;
281
282 return result;
283 }
284
285
286
287
288
289
290
291 @JsxFunction
292 public SVGMatrix rotateFromVector(final double x, final double y) {
293 if (x == 0 || y == 0) {
294 throw JavaScriptEngine.asJavaScriptException(
295 getWindow(),
296 "Failed to execute 'rotateFromVector' on 'SVGMatrix': Arguments cannot be zero.",
297 DOMException.INVALID_ACCESS_ERR);
298 }
299
300 final double theta = Math.atan2(y, x);
301 final double sin = Math.sin(theta);
302 final double cos = Math.cos(theta);
303
304 final SVGMatrix result = new SVGMatrix(getWindow());
305
306 result.shearX_ = -sin * scaleX_ + cos * shearX_;
307 result.shearY_ = cos * shearY_ + sin * scaleY_;
308 result.scaleX_ = cos * scaleX_ + sin * shearX_;
309 result.scaleY_ = -sin * shearY_ + cos * scaleY_;
310 result.translateX_ = translateX_;
311 result.translateY_ = translateY_;
312
313 return result;
314 }
315
316
317
318
319
320
321 @JsxFunction
322 public SVGMatrix scale(final double factor) {
323 return scaleNonUniform(factor, factor);
324 }
325
326
327
328
329
330
331
332 @JsxFunction
333 public SVGMatrix scaleNonUniform(final double factorX, final double factorY) {
334 final SVGMatrix result = new SVGMatrix(getWindow());
335
336 result.shearX_ = factorY * shearX_;
337 result.shearY_ = factorX * shearY_;
338 result.scaleX_ = factorX * scaleX_;
339 result.scaleY_ = factorY * scaleY_;
340 result.translateX_ = translateX_;
341 result.translateY_ = translateY_;
342
343 return result;
344 }
345
346
347
348
349
350
351 @JsxFunction
352 public SVGMatrix skewX(final double angle) {
353 final double shear = Math.tan(Math.toRadians(angle));
354
355 final SVGMatrix result = new SVGMatrix(getWindow());
356
357 result.shearX_ = shear * scaleX_ + shearX_;
358 result.shearY_ = shearY_;
359 result.scaleX_ = scaleX_;
360 result.scaleY_ = shear * shearY_ + scaleY_;
361 result.translateX_ = translateX_;
362 result.translateY_ = translateY_;
363
364 return result;
365 }
366
367
368
369
370
371
372 @JsxFunction
373 public SVGMatrix skewY(final double angle) {
374 final double shear = Math.tan(Math.toRadians(angle));
375
376 final SVGMatrix result = new SVGMatrix(getWindow());
377
378 result.shearX_ = shearX_;
379 result.shearY_ = shearY_ + shear * scaleY_;
380 result.scaleX_ = scaleX_ + shear * shearX_;
381 result.scaleY_ = scaleY_;
382 result.translateX_ = translateX_;
383 result.translateY_ = translateY_;
384
385 return result;
386 }
387
388
389
390
391
392
393
394 @JsxFunction
395 public SVGMatrix translate(final double x, final double y) {
396 final SVGMatrix result = new SVGMatrix(getWindow());
397
398 result.shearX_ = shearX_;
399 result.shearY_ = shearY_;
400 result.scaleX_ = scaleX_;
401 result.scaleY_ = scaleY_;
402 result.translateX_ = x * scaleX_ + y * shearX_ + translateX_;
403 result.translateY_ = x * shearY_ + y * scaleY_ + translateY_;
404
405 return result;
406 }
407 }