1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use dom::bindings::cell::DomRefCell;
6 use dom::bindings::codegen::Bindings::DOMMatrixBinding::{DOMMatrixInit, DOMMatrixMethods};
7 use dom::bindings::codegen::Bindings::DOMMatrixReadOnlyBinding::{DOMMatrixReadOnlyMethods, Wrap};
8 use dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit;
9 use dom::bindings::error;
10 use dom::bindings::error::Fallible;
11 use dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
12 use dom::bindings::root::DomRoot;
13 use dom::dommatrix::DOMMatrix;
14 use dom::dompoint::DOMPoint;
15 use dom::globalscope::GlobalScope;
16 use dom_struct::dom_struct;
17 use euclid::{Transform3D, Angle};
18 use std::cell::{Cell, Ref};
19 use std::f64;
20
21 #[dom_struct]
22 pub struct DOMMatrixReadOnly {
23 reflector_: Reflector,
24 matrix: DomRefCell<Transform3D<f64>>,
25 is2D: Cell<bool>,
26 }
27
28 impl DOMMatrixReadOnly {
29 #[allow(unrooted_must_root)]
new(global: &GlobalScope, is2D: bool, matrix: Transform3D<f64>) -> DomRoot<Self>30 pub fn new(global: &GlobalScope, is2D: bool, matrix: Transform3D<f64>) -> DomRoot<Self> {
31 let dommatrix = Self::new_inherited(is2D, matrix);
32 reflect_dom_object(Box::new(dommatrix), global, Wrap)
33 }
34
new_inherited(is2D: bool, matrix: Transform3D<f64>) -> Self35 pub fn new_inherited(is2D: bool, matrix: Transform3D<f64>) -> Self {
36 DOMMatrixReadOnly {
37 reflector_: Reflector::new(),
38 matrix: DomRefCell::new(matrix),
39 is2D: Cell::new(is2D),
40 }
41 }
42
43 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly
Constructor(global: &GlobalScope) -> Fallible<DomRoot<Self>>44 pub fn Constructor(global: &GlobalScope) -> Fallible<DomRoot<Self>> {
45 Ok(Self::new(global, true, Transform3D::identity()))
46 }
47
48 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
Constructor_(global: &GlobalScope, entries: Vec<f64>) -> Fallible<DomRoot<Self>>49 pub fn Constructor_(global: &GlobalScope, entries: Vec<f64>) -> Fallible<DomRoot<Self>> {
50 entries_to_matrix(&entries[..])
51 .map(|(is2D, matrix)| {
52 Self::new(global, is2D, matrix)
53 })
54 }
55
56 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-frommatrix
FromMatrix(global: &GlobalScope, other: &DOMMatrixInit) -> Fallible<DomRoot<Self>>57 pub fn FromMatrix(global: &GlobalScope, other: &DOMMatrixInit) -> Fallible<DomRoot<Self>> {
58 dommatrixinit_to_matrix(&other)
59 .map(|(is2D, matrix)| {
60 Self::new(global, is2D, matrix)
61 })
62 }
63
matrix(&self) -> Ref<Transform3D<f64>>64 pub fn matrix(&self) -> Ref<Transform3D<f64>> {
65 self.matrix.borrow()
66 }
67
is_2d(&self) -> bool68 pub fn is_2d(&self) -> bool {
69 self.is2D.get()
70 }
71
72 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m11
set_m11(&self, value: f64)73 pub fn set_m11(&self, value: f64) {
74 self.matrix.borrow_mut().m11 = value;
75 }
76
77 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m12
set_m12(&self, value: f64)78 pub fn set_m12(&self, value: f64) {
79 self.matrix.borrow_mut().m12 = value;
80 }
81
82 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m13
set_m13(&self, value: f64)83 pub fn set_m13(&self, value: f64) {
84 self.matrix.borrow_mut().m13 = value;
85 }
86
87 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m14
set_m14(&self, value: f64)88 pub fn set_m14(&self, value: f64) {
89 self.matrix.borrow_mut().m14 = value;
90 }
91
92 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m21
set_m21(&self, value: f64)93 pub fn set_m21(&self, value: f64) {
94 self.matrix.borrow_mut().m21 = value;
95 }
96
97 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m22
set_m22(&self, value: f64)98 pub fn set_m22(&self, value: f64) {
99 self.matrix.borrow_mut().m22 = value;
100 }
101
102 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m23
set_m23(&self, value: f64)103 pub fn set_m23(&self, value: f64) {
104 self.matrix.borrow_mut().m23 = value;
105 }
106
107 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m24
set_m24(&self, value: f64)108 pub fn set_m24(&self, value: f64) {
109 self.matrix.borrow_mut().m24 = value;
110 }
111
112 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m31
set_m31(&self, value: f64)113 pub fn set_m31(&self, value: f64) {
114 self.matrix.borrow_mut().m31 = value;
115 }
116
117 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m32
set_m32(&self, value: f64)118 pub fn set_m32(&self, value: f64) {
119 self.matrix.borrow_mut().m32 = value;
120 }
121
122 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m33
set_m33(&self, value: f64)123 pub fn set_m33(&self, value: f64) {
124 self.matrix.borrow_mut().m33 = value;
125 }
126
127 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m34
set_m34(&self, value: f64)128 pub fn set_m34(&self, value: f64) {
129 self.matrix.borrow_mut().m34 = value;
130 }
131
132 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m41
set_m41(&self, value: f64)133 pub fn set_m41(&self, value: f64) {
134 self.matrix.borrow_mut().m41 = value;
135 }
136
137 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m42
set_m42(&self, value: f64)138 pub fn set_m42(&self, value: f64) {
139 self.matrix.borrow_mut().m42 = value;
140 }
141
142 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m43
set_m43(&self, value: f64)143 pub fn set_m43(&self, value: f64) {
144 self.matrix.borrow_mut().m43 = value;
145 }
146
147 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m44
set_m44(&self, value: f64)148 pub fn set_m44(&self, value: f64) {
149 self.matrix.borrow_mut().m44 = value;
150 }
151
152
153 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-multiplyself
multiply_self(&self, other: &DOMMatrixInit) -> Fallible<()>154 pub fn multiply_self(&self, other: &DOMMatrixInit) -> Fallible<()> {
155 // Step 1.
156 dommatrixinit_to_matrix(&other).map(|(is2D, other_matrix)| {
157 // Step 2.
158 let mut matrix = self.matrix.borrow_mut();
159 *matrix = other_matrix.post_mul(&matrix);
160 // Step 3.
161 if !is2D {
162 self.is2D.set(false);
163 }
164 // Step 4 in DOMMatrix.MultiplySelf
165 })
166 }
167
168 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-premultiplyself
pre_multiply_self(&self, other: &DOMMatrixInit) -> Fallible<()>169 pub fn pre_multiply_self(&self, other: &DOMMatrixInit) -> Fallible<()> {
170 // Step 1.
171 dommatrixinit_to_matrix(&other).map(|(is2D, other_matrix)| {
172 // Step 2.
173 let mut matrix = self.matrix.borrow_mut();
174 *matrix = other_matrix.pre_mul(&matrix);
175 // Step 3.
176 if !is2D {
177 self.is2D.set(false);
178 }
179 // Step 4 in DOMMatrix.PreMultiplySelf
180 })
181 }
182
183 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-translateself
translate_self(&self, tx: f64, ty: f64, tz: f64)184 pub fn translate_self(&self, tx: f64, ty: f64, tz: f64) {
185 // Step 1.
186 let translation = Transform3D::create_translation(tx, ty, tz);
187 let mut matrix = self.matrix.borrow_mut();
188 *matrix = translation.post_mul(&matrix);
189 // Step 2.
190 if tz != 0.0 {
191 self.is2D.set(false);
192 }
193 // Step 3 in DOMMatrix.TranslateSelf
194 }
195
196 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scaleself
scale_self(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64, mut originX: f64, mut originY: f64, mut originZ: f64)197 pub fn scale_self(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
198 mut originX: f64, mut originY: f64, mut originZ: f64) {
199 // Step 1.
200 self.translate_self(originX, originY, originZ);
201 // Step 2.
202 let scaleY = scaleY.unwrap_or(scaleX);
203 // Step 3.
204 {
205 let scale3D = Transform3D::create_scale(scaleX, scaleY, scaleZ);
206 let mut matrix = self.matrix.borrow_mut();
207 *matrix = scale3D.post_mul(&matrix);
208 }
209 // Step 4.
210 originX = -originX;
211 originY = -originY;
212 originZ = -originZ;
213 // Step 5.
214 self.translate_self(originX, originY, originZ);
215 // Step 6.
216 if scaleZ != 1.0 || originZ != 0.0 {
217 self.is2D.set(false);
218 }
219 // Step 7 in DOMMatrix.ScaleSelf
220 }
221
222 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scale3dself
scale_3d_self(&self, scale: f64, originX: f64, originY: f64, originZ: f64)223 pub fn scale_3d_self(&self, scale: f64, originX: f64, originY: f64, originZ: f64) {
224 // Step 1.
225 self.translate_self(originX, originY, originZ);
226 // Step 2.
227 {
228 let scale3D = Transform3D::create_scale(scale, scale, scale);
229 let mut matrix = self.matrix.borrow_mut();
230 *matrix = scale3D.post_mul(&matrix);
231 }
232 // Step 3.
233 self.translate_self(-originX, -originY, -originZ);
234 // Step 4.
235 if scale != 1.0 {
236 self.is2D.set(false);
237 }
238 // Step 5 in DOMMatrix.Scale3dSelf
239 }
240
241 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotateself
rotate_self(&self, mut rotX: f64, mut rotY: Option<f64>, mut rotZ: Option<f64>)242 pub fn rotate_self(&self, mut rotX: f64, mut rotY: Option<f64>, mut rotZ: Option<f64>) {
243 // Step 1.
244 if rotY.is_none() && rotZ.is_none() {
245 rotZ = Some(rotX);
246 rotX = 0.0;
247 rotY = Some(0.0);
248 }
249 // Step 2.
250 let rotY = rotY.unwrap_or(0.0);
251 // Step 3.
252 let rotZ = rotZ.unwrap_or(0.0);
253 // Step 4.
254 if rotX != 0.0 || rotY != 0.0 {
255 self.is2D.set(false);
256 }
257 if rotZ != 0.0 {
258 // Step 5.
259 let rotation = Transform3D::create_rotation(0.0, 0.0, 1.0, Angle::radians(rotZ.to_radians()));
260 let mut matrix = self.matrix.borrow_mut();
261 *matrix = rotation.post_mul(&matrix);
262 }
263 if rotY != 0.0 {
264 // Step 6.
265 let rotation = Transform3D::create_rotation(0.0, 1.0, 0.0, Angle::radians(rotY.to_radians()));
266 let mut matrix = self.matrix.borrow_mut();
267 *matrix = rotation.post_mul(&matrix);
268 }
269 if rotX != 0.0 {
270 // Step 7.
271 let rotation = Transform3D::create_rotation(1.0, 0.0, 0.0, Angle::radians(rotX.to_radians()));
272 let mut matrix = self.matrix.borrow_mut();
273 *matrix = rotation.post_mul(&matrix);
274 }
275 // Step 8 in DOMMatrix.RotateSelf
276 }
277
278 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotatefromvectorself
rotate_from_vector_self(&self, x: f64, y: f64)279 pub fn rotate_from_vector_self(&self, x: f64, y: f64) {
280 // don't do anything when the rotation angle is zero or undefined
281 if y != 0.0 || x < 0.0 {
282 // Step 1.
283 let rotZ = Angle::radians(f64::atan2(y, x));
284 let rotation = Transform3D::create_rotation(0.0, 0.0, 1.0, rotZ);
285 let mut matrix = self.matrix.borrow_mut();
286 *matrix = rotation.post_mul(&matrix);
287 }
288 // Step 2 in DOMMatrix.RotateFromVectorSelf
289 }
290
291 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotateaxisangleself
rotate_axis_angle_self(&self, x: f64, y: f64, z: f64, angle: f64)292 pub fn rotate_axis_angle_self(&self, x: f64, y: f64, z: f64, angle: f64) {
293 // Step 1.
294 let (norm_x, norm_y, norm_z) = normalize_point(x, y, z);
295 let rotation = Transform3D::create_rotation(norm_x, norm_y, norm_z, Angle::radians(angle.to_radians()));
296 let mut matrix = self.matrix.borrow_mut();
297 *matrix = rotation.post_mul(&matrix);
298 // Step 2.
299 if x != 0.0 || y != 0.0 {
300 self.is2D.set(false);
301 }
302 // Step 3 in DOMMatrix.RotateAxisAngleSelf
303 }
304
305 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-skewxself
skew_x_self(&self, sx: f64)306 pub fn skew_x_self(&self, sx: f64) {
307 // Step 1.
308 let skew = Transform3D::create_skew(Angle::radians(sx.to_radians()), Angle::radians(0.0));
309 let mut matrix = self.matrix.borrow_mut();
310 *matrix = skew.post_mul(&matrix);
311 // Step 2 in DOMMatrix.SkewXSelf
312 }
313
314 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-skewyself
skew_y_self(&self, sy: f64)315 pub fn skew_y_self(&self, sy: f64) {
316 // Step 1.
317 let skew = Transform3D::create_skew(Angle::radians(0.0), Angle::radians(sy.to_radians()));
318 let mut matrix = self.matrix.borrow_mut();
319 *matrix = skew.post_mul(&matrix);
320 // Step 2 in DOMMatrix.SkewYSelf
321 }
322
323 // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-invertself
invert_self(&self)324 pub fn invert_self(&self) {
325 let mut matrix = self.matrix.borrow_mut();
326 // Step 1.
327 *matrix = matrix.inverse().unwrap_or_else(|| {
328 // Step 2.
329 self.is2D.set(false);
330 Transform3D::row_major(f64::NAN, f64::NAN, f64::NAN, f64::NAN,
331 f64::NAN, f64::NAN, f64::NAN, f64::NAN,
332 f64::NAN, f64::NAN, f64::NAN, f64::NAN,
333 f64::NAN, f64::NAN, f64::NAN, f64::NAN)
334 })
335 // Step 3 in DOMMatrix.InvertSelf
336 }
337 }
338
339
340 impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly {
341 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m11
M11(&self) -> f64342 fn M11(&self) -> f64 {
343 self.matrix.borrow().m11
344 }
345
346 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m12
M12(&self) -> f64347 fn M12(&self) -> f64 {
348 self.matrix.borrow().m12
349 }
350
351 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m13
M13(&self) -> f64352 fn M13(&self) -> f64 {
353 self.matrix.borrow().m13
354 }
355
356 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m14
M14(&self) -> f64357 fn M14(&self) -> f64 {
358 self.matrix.borrow().m14
359 }
360
361 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m21
M21(&self) -> f64362 fn M21(&self) -> f64 {
363 self.matrix.borrow().m21
364 }
365
366 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m22
M22(&self) -> f64367 fn M22(&self) -> f64 {
368 self.matrix.borrow().m22
369 }
370
371 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m23
M23(&self) -> f64372 fn M23(&self) -> f64 {
373 self.matrix.borrow().m23
374 }
375
376 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m24
M24(&self) -> f64377 fn M24(&self) -> f64 {
378 self.matrix.borrow().m24
379 }
380
381 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m31
M31(&self) -> f64382 fn M31(&self) -> f64 {
383 self.matrix.borrow().m31
384 }
385
386 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m32
M32(&self) -> f64387 fn M32(&self) -> f64 {
388 self.matrix.borrow().m32
389 }
390
391 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m33
M33(&self) -> f64392 fn M33(&self) -> f64 {
393 self.matrix.borrow().m33
394 }
395
396 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m34
M34(&self) -> f64397 fn M34(&self) -> f64 {
398 self.matrix.borrow().m34
399 }
400
401 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m41
M41(&self) -> f64402 fn M41(&self) -> f64 {
403 self.matrix.borrow().m41
404 }
405
406 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m42
M42(&self) -> f64407 fn M42(&self) -> f64 {
408 self.matrix.borrow().m42
409 }
410
411 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m43
M43(&self) -> f64412 fn M43(&self) -> f64 {
413 self.matrix.borrow().m43
414 }
415
416 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m44
M44(&self) -> f64417 fn M44(&self) -> f64 {
418 self.matrix.borrow().m44
419 }
420
421 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-a
A(&self) -> f64422 fn A(&self) -> f64 {
423 self.M11()
424 }
425
426 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-b
B(&self) -> f64427 fn B(&self) -> f64 {
428 self.M12()
429 }
430
431 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-c
C(&self) -> f64432 fn C(&self) -> f64 {
433 self.M21()
434 }
435
436 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-d
D(&self) -> f64437 fn D(&self) -> f64 {
438 self.M22()
439 }
440
441 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-e
E(&self) -> f64442 fn E(&self) -> f64 {
443 self.M41()
444 }
445
446 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-f
F(&self) -> f64447 fn F(&self) -> f64 {
448 self.M42()
449 }
450
451 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-is2d
Is2D(&self) -> bool452 fn Is2D(&self) -> bool {
453 self.is2D.get()
454 }
455
456 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-isidentity
IsIdentity(&self) -> bool457 fn IsIdentity(&self) -> bool {
458 let matrix = self.matrix.borrow();
459 matrix.m12 == 0.0 && matrix.m13 == 0.0 && matrix.m14 == 0.0 && matrix.m21 == 0.0 &&
460 matrix.m23 == 0.0 && matrix.m24 == 0.0 && matrix.m31 == 0.0 && matrix.m32 == 0.0 &&
461 matrix.m34 == 0.0 && matrix.m41 == 0.0 && matrix.m42 == 0.0 && matrix.m43 == 0.0 &&
462 matrix.m11 == 1.0 && matrix.m22 == 1.0 && matrix.m33 == 1.0 && matrix.m44 == 1.0
463 }
464
465 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-translate
Translate(&self, tx: f64, ty: f64, tz: f64) -> DomRoot<DOMMatrix>466 fn Translate(&self, tx: f64, ty: f64, tz: f64) -> DomRoot<DOMMatrix> {
467 DOMMatrix::from_readonly(&self.global(), self).TranslateSelf(tx, ty, tz)
468 }
469
470 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-scale
Scale(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64, originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix>471 fn Scale(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
472 originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
473 DOMMatrix::from_readonly(&self.global(), self)
474 .ScaleSelf(scaleX, scaleY, scaleZ, originX, originY, originZ)
475 }
476
477 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-scale3d
Scale3d(&self, scale: f64, originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix>478 fn Scale3d(&self, scale: f64, originX: f64, originY: f64, originZ: f64) -> DomRoot<DOMMatrix> {
479 DOMMatrix::from_readonly(&self.global(), self)
480 .Scale3dSelf(scale, originX, originY, originZ)
481 }
482
483 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-rotate
Rotate(&self, rotX: f64, rotY: Option<f64>, rotZ: Option<f64>) -> DomRoot<DOMMatrix>484 fn Rotate(&self, rotX: f64, rotY: Option<f64>, rotZ: Option<f64>) -> DomRoot<DOMMatrix> {
485 DOMMatrix::from_readonly(&self.global(), self).RotateSelf(rotX, rotY, rotZ)
486 }
487
488 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-rotatefromvector
RotateFromVector(&self, x: f64, y: f64) -> DomRoot<DOMMatrix>489 fn RotateFromVector(&self, x: f64, y: f64) -> DomRoot<DOMMatrix> {
490 DOMMatrix::from_readonly(&self.global(), self).RotateFromVectorSelf(x, y)
491 }
492
493 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-rotateaxisangle
RotateAxisAngle(&self, x: f64, y: f64, z: f64, angle: f64) -> DomRoot<DOMMatrix>494 fn RotateAxisAngle(&self, x: f64, y: f64, z: f64, angle: f64) -> DomRoot<DOMMatrix> {
495 DOMMatrix::from_readonly(&self.global(), self).RotateAxisAngleSelf(x, y, z, angle)
496 }
497
498 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-skewx
SkewX(&self, sx: f64) -> DomRoot<DOMMatrix>499 fn SkewX(&self, sx: f64) -> DomRoot<DOMMatrix> {
500 DOMMatrix::from_readonly(&self.global(), self).SkewXSelf(sx)
501 }
502
503 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-skewy
SkewY(&self, sy: f64) -> DomRoot<DOMMatrix>504 fn SkewY(&self, sy: f64) -> DomRoot<DOMMatrix> {
505 DOMMatrix::from_readonly(&self.global(), self).SkewYSelf(sy)
506 }
507
508 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-multiply
Multiply(&self, other: &DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>>509 fn Multiply(&self, other: &DOMMatrixInit) -> Fallible<DomRoot<DOMMatrix>> {
510 DOMMatrix::from_readonly(&self.global(), self).MultiplySelf(&other)
511 }
512
513 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipx
FlipX(&self) -> DomRoot<DOMMatrix>514 fn FlipX(&self) -> DomRoot<DOMMatrix> {
515 let is2D = self.is2D.get();
516 let flip = Transform3D::row_major(-1.0, 0.0, 0.0, 0.0,
517 0.0, 1.0, 0.0, 0.0,
518 0.0, 0.0, 1.0, 0.0,
519 0.0, 0.0, 0.0, 1.0);
520 let matrix = flip.post_mul(&self.matrix.borrow());
521 DOMMatrix::new(&self.global(), is2D, matrix)
522 }
523
524 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipy
FlipY(&self) -> DomRoot<DOMMatrix>525 fn FlipY(&self) -> DomRoot<DOMMatrix> {
526 let is2D = self.is2D.get();
527 let flip = Transform3D::row_major(1.0, 0.0, 0.0, 0.0,
528 0.0, -1.0, 0.0, 0.0,
529 0.0, 0.0, 1.0, 0.0,
530 0.0, 0.0, 0.0, 1.0);
531 let matrix = flip.post_mul(&self.matrix.borrow());
532 DOMMatrix::new(&self.global(), is2D, matrix)
533 }
534
535 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-inverse
Inverse(&self) -> DomRoot<DOMMatrix>536 fn Inverse(&self) -> DomRoot<DOMMatrix> {
537 DOMMatrix::from_readonly(&self.global(), self).InvertSelf()
538 }
539
540 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-transformpoint
TransformPoint(&self, point: &DOMPointInit) -> DomRoot<DOMPoint>541 fn TransformPoint(&self, point: &DOMPointInit) -> DomRoot<DOMPoint> {
542 // Euclid always normalizes the homogeneous coordinate which is usually the right
543 // thing but may (?) not be compliant with the CSS matrix spec (or at least is
544 // probably not the behavior web authors will expect even if it is mathematically
545 // correct in the context of geometry computations).
546 // Since this is the only place where this is needed, better implement it here
547 // than in euclid (which does not have a notion of 4d points).
548 let mat = self.matrix.borrow();
549 let x = point.x * mat.m11 + point.y * mat.m21 + point.z * mat.m31 + point.w * mat.m41;
550 let y = point.x * mat.m12 + point.y * mat.m22 + point.z * mat.m32 + point.w * mat.m42;
551 let z = point.x * mat.m13 + point.y * mat.m23 + point.z * mat.m33 + point.w * mat.m43;
552 let w = point.x * mat.m14 + point.y * mat.m24 + point.z * mat.m34 + point.w * mat.m44;
553
554 DOMPoint::new(&self.global(), x, y, z, w)
555 }
556 }
557
558
559 // https://drafts.fxtf.org/geometry-1/#create-a-2d-matrix
create_2d_matrix(entries: &[f64]) -> Transform3D<f64>560 fn create_2d_matrix(entries: &[f64]) -> Transform3D<f64> {
561 Transform3D::row_major(entries[0], entries[1], 0.0, 0.0,
562 entries[2], entries[3], 0.0, 0.0,
563 0.0, 0.0, 1.0, 0.0,
564 entries[4], entries[5], 0.0, 1.0)
565 }
566
567
568 // https://drafts.fxtf.org/geometry-1/#create-a-3d-matrix
create_3d_matrix(entries: &[f64]) -> Transform3D<f64>569 fn create_3d_matrix(entries: &[f64]) -> Transform3D<f64> {
570 Transform3D::row_major(entries[0], entries[1], entries[2], entries[3],
571 entries[4], entries[5], entries[6], entries[7],
572 entries[8], entries[9], entries[10], entries[11],
573 entries[12], entries[13], entries[14], entries[15])
574 }
575
576 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
entries_to_matrix(entries: &[f64]) -> Fallible<(bool, Transform3D<f64>)>577 pub fn entries_to_matrix(entries: &[f64]) -> Fallible<(bool, Transform3D<f64>)> {
578 if entries.len() == 6 {
579 Ok((true, create_2d_matrix(&entries)))
580 } else if entries.len() == 16 {
581 Ok((false, create_3d_matrix(&entries)))
582 } else {
583 let err_msg = format!("Expected 6 or 16 entries, but found {}.", entries.len());
584 Err(error::Error::Type(err_msg.to_owned()))
585 }
586 }
587
588
589 // https://drafts.fxtf.org/geometry-1/#validate-and-fixup
dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transform3D<f64>)>590 pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transform3D<f64>)> {
591 // Step 1.
592 if dict.a.is_some() && dict.m11.is_some() && dict.a.unwrap() != dict.m11.unwrap() ||
593 dict.b.is_some() && dict.m12.is_some() && dict.b.unwrap() != dict.m12.unwrap() ||
594 dict.c.is_some() && dict.m21.is_some() && dict.c.unwrap() != dict.m21.unwrap() ||
595 dict.d.is_some() && dict.m22.is_some() && dict.d.unwrap() != dict.m22.unwrap() ||
596 dict.e.is_some() && dict.m41.is_some() && dict.e.unwrap() != dict.m41.unwrap() ||
597 dict.f.is_some() && dict.m42.is_some() && dict.f.unwrap() != dict.m42.unwrap() ||
598 dict.is2D.is_some() && dict.is2D.unwrap() &&
599 (dict.m31 != 0.0 || dict.m32 != 0.0 || dict.m13 != 0.0 || dict.m23 != 0.0 ||
600 dict.m43 != 0.0 || dict.m14 != 0.0 || dict.m24 != 0.0 || dict.m34 != 0.0 ||
601 dict.m33 != 1.0 || dict.m44 != 1.0) {
602 Err(error::Error::Type("Invalid matrix initializer.".to_owned()))
603 } else {
604 let mut is2D = dict.is2D;
605 // Step 2.
606 let m11 = dict.m11.unwrap_or(dict.a.unwrap_or(1.0));
607 // Step 3.
608 let m12 = dict.m12.unwrap_or(dict.b.unwrap_or(0.0));
609 // Step 4.
610 let m21 = dict.m21.unwrap_or(dict.c.unwrap_or(0.0));
611 // Step 5.
612 let m22 = dict.m22.unwrap_or(dict.d.unwrap_or(1.0));
613 // Step 6.
614 let m41 = dict.m41.unwrap_or(dict.e.unwrap_or(0.0));
615 // Step 7.
616 let m42 = dict.m42.unwrap_or(dict.f.unwrap_or(0.0));
617 // Step 8.
618 if is2D.is_none() &&
619 (dict.m31 != 0.0 || dict.m32 != 0.0 || dict.m13 != 0.0 ||
620 dict.m23 != 0.0 || dict.m43 != 0.0 || dict.m14 != 0.0 ||
621 dict.m24 != 0.0 || dict.m34 != 0.0 ||
622 dict.m33 != 1.0 || dict.m44 != 1.0) {
623 is2D = Some(false);
624 }
625 // Step 9.
626 if is2D.is_none() {
627 is2D = Some(true);
628 }
629 let matrix = Transform3D::row_major(m11, m12, dict.m13, dict.m14,
630 m21, m22, dict.m23, dict.m24,
631 dict.m31, dict.m32, dict.m33, dict.m34,
632 m41, m42, dict.m43, dict.m44);
633 Ok((is2D.unwrap(), matrix))
634 }
635 }
636
637
638 #[inline]
normalize_point(x: f64, y: f64, z: f64) -> (f64, f64, f64)639 fn normalize_point(x: f64, y: f64, z: f64) -> (f64, f64, f64) {
640 let len = (x * x + y * y + z * z).sqrt();
641 if len == 0.0 {
642 (0.0, 0.0, 0.0)
643 } else {
644 (x / len, y / len, z / len)
645 }
646 }
647