1use std::{
2 f32,
3 ops::{Add, AddAssign, Div, DivAssign, Index, Mul, MulAssign, Neg, Sub, SubAssign},
4 slice,
5};
6
7use skia_bindings::{self as sb, SkM44, SkV2, SkV3, SkV4};
8
9use crate::{prelude::*, private::is_finite, scalar, Matrix, Rect};
10
11#[repr(C)]
12#[derive(Copy, Clone, PartialEq, Default, Debug)]
13pub struct V2 {
14 pub x: f32,
15 pub y: f32,
16}
17
18native_transmutable!(SkV2, V2, v2_layout);
19
20impl V2 {
21 pub const fn new(x: f32, y: f32) -> Self {
22 Self { x, y }
23 }
24
25 pub fn dot(self, b: Self) -> scalar {
26 self.x * b.x + self.y * b.y
27 }
28
29 pub fn cross(self, b: Self) -> scalar {
30 self.x * b.y - self.y * b.x
31 }
32
33 #[must_use]
34 pub fn normalize(self) -> Self {
35 self * (1.0 / self.length())
36 }
37
38 pub fn length_squared(self) -> scalar {
39 Self::dot(self, self)
40 }
41
42 pub fn length(self) -> scalar {
43 self.length_squared().sqrt()
44 }
45
46 const COMPONENTS: usize = 2;
47
48 pub fn as_array(&self) -> &[f32; Self::COMPONENTS] {
49 unsafe { slice::from_raw_parts(&self.x, Self::COMPONENTS) }
50 .try_into()
51 .unwrap()
52 }
53
54 pub fn as_mut_array(&mut self) -> &mut [f32; Self::COMPONENTS] {
55 unsafe { slice::from_raw_parts_mut(&mut self.x, Self::COMPONENTS) }
56 .try_into()
57 .unwrap()
58 }
59}
60
61impl Neg for V2 {
62 type Output = Self;
63
64 fn neg(self) -> Self::Output {
65 Self::new(-self.x, -self.y)
66 }
67}
68
69impl Add for V2 {
70 type Output = Self;
71
72 fn add(self, v: Self) -> Self::Output {
73 Self::new(self.x + v.x, self.y + v.y)
74 }
75}
76
77impl Sub for V2 {
78 type Output = Self;
79
80 fn sub(self, v: Self) -> Self::Output {
81 Self::new(self.x - v.x, self.y - v.y)
82 }
83}
84
85impl Mul for V2 {
86 type Output = Self;
87
88 fn mul(self, v: Self) -> Self::Output {
89 Self::new(self.x * v.x, self.y * v.y)
90 }
91}
92
93impl Mul<scalar> for V2 {
94 type Output = Self;
95
96 fn mul(self, s: scalar) -> Self::Output {
97 Self::new(self.x * s, self.y * s)
98 }
99}
100
101impl Mul<V2> for scalar {
102 type Output = V2;
103
104 fn mul(self, v: V2) -> Self::Output {
105 V2::new(v.x * self, v.y * self)
106 }
107}
108
109impl Div<V2> for scalar {
110 type Output = V2;
111
112 fn div(self, v: V2) -> Self::Output {
113 V2::new(self / v.x, self / v.y)
114 }
115}
116
117impl Div<scalar> for V2 {
118 type Output = V2;
119 fn div(self, s: scalar) -> Self::Output {
120 V2::new(self.x / s, self.y / s)
121 }
122}
123
124impl AddAssign for V2 {
125 fn add_assign(&mut self, v: Self) {
126 *self = *self + v
127 }
128}
129
130impl SubAssign for V2 {
131 fn sub_assign(&mut self, v: Self) {
132 *self = *self - v
133 }
134}
135
136impl MulAssign for V2 {
137 fn mul_assign(&mut self, v: Self) {
138 *self = *self * v
139 }
140}
141
142impl MulAssign<scalar> for V2 {
143 fn mul_assign(&mut self, s: scalar) {
144 *self = *self * s
145 }
146}
147
148impl DivAssign<scalar> for V2 {
149 fn div_assign(&mut self, s: scalar) {
150 *self = *self / s
151 }
152}
153
154#[repr(C)]
155#[derive(Copy, Clone, PartialEq, Default, Debug)]
156pub struct V3 {
157 pub x: f32,
158 pub y: f32,
159 pub z: f32,
160}
161
162native_transmutable!(SkV3, V3, v3_layout);
163
164impl V3 {
165 pub const fn new(x: f32, y: f32, z: f32) -> Self {
166 Self { x, y, z }
167 }
168
169 pub fn dot(&self, b: &Self) -> scalar {
170 self.x * b.x + self.y * b.y + self.z * b.z
171 }
172
173 #[must_use]
174 pub fn cross(&self, b: &Self) -> Self {
175 Self::new(
176 self.y * b.z - self.z * b.y,
177 self.z * b.x - self.x * b.z,
178 self.x * b.y - self.y * b.x,
179 )
180 }
181
182 #[must_use]
183 pub fn normalize(&self) -> Self {
184 *self * (1.0 / self.length())
185 }
186
187 pub fn length_squared(&self) -> scalar {
188 Self::dot(self, self)
189 }
190
191 pub fn length(&self) -> scalar {
192 Self::dot(self, self).sqrt()
193 }
194
195 const COMPONENTS: usize = 3;
196
197 pub fn as_array(&self) -> &[f32; Self::COMPONENTS] {
198 unsafe { slice::from_raw_parts(&self.x, Self::COMPONENTS) }
199 .try_into()
200 .unwrap()
201 }
202
203 pub fn as_mut_array(&mut self) -> &mut [f32; Self::COMPONENTS] {
204 unsafe { slice::from_raw_parts_mut(&mut self.x, Self::COMPONENTS) }
205 .try_into()
206 .unwrap()
207 }
208}
209
210impl Neg for V3 {
211 type Output = Self;
212
213 fn neg(self) -> Self::Output {
214 Self::new(-self.x, -self.y, -self.z)
215 }
216}
217
218impl Add for V3 {
219 type Output = Self;
220
221 fn add(self, v: Self) -> Self::Output {
222 Self::new(self.x + v.x, self.y + v.y, self.z + v.z)
223 }
224}
225
226impl Sub for V3 {
227 type Output = Self;
228
229 fn sub(self, v: Self) -> Self::Output {
230 Self::new(self.x - v.x, self.y - v.y, self.z - v.z)
231 }
232}
233
234impl Mul for V3 {
235 type Output = Self;
236
237 fn mul(self, v: Self) -> Self::Output {
238 Self::new(self.x * v.x, self.y * v.y, self.z * v.z)
239 }
240}
241
242impl Mul<scalar> for V3 {
243 type Output = Self;
244
245 fn mul(self, s: scalar) -> Self::Output {
246 Self::new(self.x * s, self.y * s, self.z * s)
247 }
248}
249
250impl Mul<V3> for scalar {
251 type Output = V3;
252
253 fn mul(self, v: V3) -> Self::Output {
254 V3::new(v.x * self, v.y * self, v.z * self)
255 }
256}
257
258impl AddAssign for V3 {
259 fn add_assign(&mut self, v: Self) {
260 *self = *self + v
261 }
262}
263
264impl SubAssign for V3 {
265 fn sub_assign(&mut self, v: Self) {
266 *self = *self - v
267 }
268}
269
270impl MulAssign for V3 {
271 fn mul_assign(&mut self, v: Self) {
272 *self = *self * v
273 }
274}
275
276impl MulAssign<scalar> for V3 {
277 fn mul_assign(&mut self, s: scalar) {
278 *self = *self * s
279 }
280}
281
282#[repr(C)]
283#[derive(Copy, Clone, PartialEq, Default, Debug)]
284pub struct V4 {
285 pub x: f32,
286 pub y: f32,
287 pub z: f32,
288 pub w: f32,
289}
290
291native_transmutable!(SkV4, V4, v4_layout);
292
293impl V4 {
294 pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
295 Self { x, y, z, w }
296 }
297
298 pub fn length_squared(&self) -> scalar {
299 Self::dot(self, self)
300 }
301
302 pub fn length(&self) -> scalar {
303 scalar::sqrt(Self::dot(self, self))
304 }
305
306 pub fn dot(&self, b: &Self) -> scalar {
307 self.x * b.x + self.y * b.y + self.z * b.z + self.w * b.w
308 }
309
310 pub fn normalize(&self) -> Self {
311 (*self) * (1.0 / self.length())
312 }
313
314 const COMPONENTS: usize = 4;
315
316 pub fn as_array(&self) -> &[f32; Self::COMPONENTS] {
317 unsafe { slice::from_raw_parts(&self.x, Self::COMPONENTS) }
318 .try_into()
319 .unwrap()
320 }
321
322 pub fn as_mut_array(&mut self) -> &mut [f32; Self::COMPONENTS] {
323 unsafe { slice::from_raw_parts_mut(&mut self.x, Self::COMPONENTS) }
324 .try_into()
325 .unwrap()
326 }
327}
328
329impl Neg for V4 {
330 type Output = Self;
331
332 fn neg(self) -> Self::Output {
333 Self::new(-self.x, -self.y, -self.z, -self.w)
334 }
335}
336
337impl Add for V4 {
338 type Output = Self;
339
340 fn add(self, v: Self) -> Self::Output {
341 Self::new(self.x + v.x, self.y + v.y, self.z + v.z, self.w + v.w)
342 }
343}
344
345impl Sub for V4 {
346 type Output = Self;
347
348 fn sub(self, v: Self) -> Self::Output {
349 Self::new(self.x - v.x, self.y - v.y, self.z - v.z, self.w - v.w)
350 }
351}
352
353impl Mul for V4 {
354 type Output = Self;
355
356 fn mul(self, v: Self) -> Self::Output {
357 Self::new(self.x * v.x, self.y * v.y, self.z * v.z, self.w * v.w)
358 }
359}
360
361impl Mul<scalar> for V4 {
362 type Output = Self;
363
364 fn mul(self, s: scalar) -> Self::Output {
365 Self::new(self.x * s, self.y * s, self.z * s, self.w * s)
366 }
367}
368
369impl Mul<V4> for scalar {
370 type Output = V4;
371
372 fn mul(self, v: V4) -> Self::Output {
373 V4::new(v.x * self, v.y * self, v.z * self, v.w * self)
374 }
375}
376
377impl AddAssign for V4 {
378 fn add_assign(&mut self, v: Self) {
379 *self = *self + v
380 }
381}
382
383impl SubAssign for V4 {
384 fn sub_assign(&mut self, v: Self) {
385 *self = *self - v
386 }
387}
388
389impl MulAssign for V4 {
390 fn mul_assign(&mut self, v: Self) {
391 *self = *self * v
392 }
393}
394
395impl MulAssign<scalar> for V4 {
396 fn mul_assign(&mut self, s: scalar) {
397 *self = *self * s
398 }
399}
400
401impl Index<usize> for V4 {
402 type Output = f32;
403
404 fn index(&self, index: usize) -> &Self::Output {
405 &self.as_array()[index]
406 }
407}
408
409#[repr(C)]
410#[derive(Clone, Debug)]
411pub struct M44 {
412 mat: [f32; Self::COMPONENTS],
413}
414
415native_transmutable!(SkM44, M44, m44_layout);
416
417impl Default for M44 {
418 fn default() -> Self {
419 Self::new_identity()
420 }
421}
422
423impl PartialEq for M44 {
424 fn eq(&self, other: &Self) -> bool {
425 unsafe { sb::C_SkM44_equals(self.native(), other.native()) }
426 }
427}
428
429impl M44 {
430 const COMPONENTS: usize = 16;
431
432 pub const fn new_identity() -> Self {
433 Self {
434 mat: [
435 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
436 ],
437 }
438 }
439
440 pub fn concat(a: &Self, b: &Self) -> Self {
441 let mut m = Self::default();
442 m.set_concat(a, b);
443 m
444 }
445
446 pub const fn nan() -> Self {
447 Self {
448 mat: [f32::NAN; Self::COMPONENTS],
449 }
450 }
451
452 #[allow(clippy::too_many_arguments)]
453 pub const fn new(
454 m0: scalar,
455 m4: scalar,
456 m8: scalar,
457 m12: scalar,
458 m1: scalar,
459 m5: scalar,
460 m9: scalar,
461 m13: scalar,
462 m2: scalar,
463 m6: scalar,
464 m10: scalar,
465 m14: scalar,
466 m3: scalar,
467 m7: scalar,
468 m11: scalar,
469 m15: scalar,
470 ) -> Self {
471 Self {
472 mat: [
473 m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15,
474 ],
475 }
476 }
477
478 pub fn rows(r0: &V4, r1: &V4, r2: &V4, r3: &V4) -> Self {
479 let mut m = Self::default();
480 m.set_row(0, r0);
481 m.set_row(1, r1);
482 m.set_row(2, r2);
483 m.set_row(3, r3);
484 m
485 }
486
487 pub fn cols(c0: &V4, c1: &V4, c2: &V4, c3: &V4) -> Self {
488 let mut m = Self::default();
489 m.set_col(0, c0);
490 m.set_col(1, c1);
491 m.set_col(2, c2);
492 m.set_col(3, c3);
493 m
494 }
495
496 pub fn row_major(r: &[scalar; Self::COMPONENTS]) -> Self {
497 Self::new(
498 r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13],
499 r[14], r[15],
500 )
501 }
502
503 pub fn col_major(c: &[scalar; Self::COMPONENTS]) -> Self {
504 Self::new(
505 c[0], c[4], c[8], c[12], c[1], c[5], c[9], c[13], c[2], c[6], c[10], c[14], c[3], c[7],
506 c[11], c[15],
507 )
508 }
509
510 pub fn translate(x: scalar, y: scalar, z: scalar) -> Self {
511 Self::new(
512 1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, y, 0.0, 0.0, 1.0, z, 0.0, 0.0, 0.0, 1.0,
513 )
514 }
515
516 pub fn scale(x: scalar, y: scalar, z: scalar) -> Self {
517 Self::new(
518 x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0,
519 )
520 }
521
522 pub fn rotate(axis: V3, radians: scalar) -> Self {
523 let mut m = Self::default();
524 m.set_rotate(axis, radians);
525 m
526 }
527
528 pub fn rect_to_rect(src: impl AsRef<Rect>, dst: impl AsRef<Rect>) -> Self {
529 let (src, dst) = (src.as_ref(), dst.as_ref());
530 Self::construct(|m| unsafe { sb::C_SkM44_RectToRect(src.native(), dst.native(), m) })
531 }
532
533 pub fn look_at(eye: &V3, center: &V3, up: &V3) -> Self {
534 Self::construct(|m| unsafe {
535 sb::C_SkM44_LookAt(eye.native(), center.native(), up.native(), m)
536 })
537 }
538
539 pub fn perspective(near: f32, far: f32, angle: f32) -> Self {
540 Self::construct(|m| unsafe { sb::C_SkM44_Perspective(near, far, angle, m) })
541 }
542
543 pub fn get_col_major(&self, v: &mut [scalar; Self::COMPONENTS]) {
544 v.copy_from_slice(&self.mat)
545 }
546
547 pub fn get_row_major(&self, v: &mut [scalar; Self::COMPONENTS]) {
548 unsafe { self.native().getRowMajor(v.as_mut_ptr()) }
549 }
550
551 #[deprecated(since = "0.30.0", note = "use M44::col_major() instead")]
552 pub fn set_col_major(&mut self, v: &[scalar; Self::COMPONENTS]) -> &mut Self {
553 *self = Self::col_major(v);
554 self
555 }
556
557 #[deprecated(since = "0.30.0", note = "use M44::row_major() instead")]
558 pub fn set_row_major(&mut self, v: &[scalar; Self::COMPONENTS]) -> &mut Self {
559 *self = Self::row_major(v);
560 self
561 }
562
563 #[allow(clippy::too_many_arguments)]
564 #[deprecated(since = "0.30.0", note = "use Self::new() instead")]
565 pub fn set_44(
566 &mut self,
567 m0: scalar,
568 m1: scalar,
569 m2: scalar,
570 m3: scalar,
571 m4: scalar,
572 m5: scalar,
573 m6: scalar,
574 m7: scalar,
575 m8: scalar,
576 m9: scalar,
577 m10: scalar,
578 m11: scalar,
579 m12: scalar,
580 m13: scalar,
581 m14: scalar,
582 m15: scalar,
583 ) -> &mut Self {
584 *self = Self::new(
585 m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15,
586 );
587 self
588 }
589
590 pub fn rc(&self, r: usize, c: usize) -> scalar {
591 assert!(r <= 3);
592 assert!(c <= 3);
593 self.mat[c * 4 + r]
594 }
595
596 pub fn set_rc(&mut self, r: usize, c: usize, value: scalar) {
597 assert!(r <= 3);
598 assert!(c <= 3);
599 self.mat[c * 4 + r] = value;
600 }
601
602 pub fn row(&self, i: usize) -> V4 {
603 assert!(i <= 3);
604 V4::new(
605 self.mat[i],
606 self.mat[i + 4],
607 self.mat[i + 8],
608 self.mat[i + 12],
609 )
610 }
611
612 pub fn col(&self, i: usize) -> V4 {
613 assert!(i <= 3);
614 V4::new(
615 self.mat[i * 4],
616 self.mat[i * 4 + 1],
617 self.mat[i * 4 + 2],
618 self.mat[i * 4 + 3],
619 )
620 }
621
622 pub fn set_row(&mut self, i: usize, v: &V4) {
623 assert!(i <= 3);
624 self.mat[i] = v.x;
625 self.mat[i + 4] = v.y;
626 self.mat[i + 8] = v.z;
627 self.mat[i + 12] = v.w;
628 }
629
630 pub fn set_col(&mut self, i: usize, v: &V4) {
631 assert!(i <= 3);
632 self.mat[(i * 4)..(i * 4 + V4::COMPONENTS)].copy_from_slice(v.as_array());
633 }
634
635 pub fn set_identity(&mut self) -> &mut Self {
636 *self = Self {
637 mat: [
638 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
639 ],
640 };
641 self
642 }
643
644 pub fn set_translate(&mut self, x: scalar, y: scalar, z: scalar) -> &mut Self {
645 *self = Self {
646 mat: [
647 1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, y, 0.0, 0.0, 1.0, z, 0.0, 0.0, 0.0, 1.0,
648 ],
649 };
650 self
651 }
652
653 pub fn set_scale(&mut self, x: scalar, y: scalar, z: scalar) -> &mut Self {
654 *self = Self {
655 mat: [
656 x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0,
657 ],
658 };
659 self
660 }
661
662 pub fn set_rotate_unit_sin_cos(
663 &mut self,
664 axis: V3,
665 sin_angle: scalar,
666 cos_angle: scalar,
667 ) -> &mut Self {
668 unsafe {
669 self.native_mut()
670 .setRotateUnitSinCos(axis.into_native(), sin_angle, cos_angle)
671 };
672 self
673 }
674
675 pub fn set_rotate_unit(&mut self, axis: V3, radians: scalar) -> &mut Self {
676 self.set_rotate_unit_sin_cos(axis, radians.sin(), radians.cos())
677 }
678
679 pub fn set_rotate(&mut self, axis: V3, radians: scalar) -> &mut Self {
680 unsafe { self.native_mut().setRotate(axis.into_native(), radians) };
681 self
682 }
683
684 #[deprecated(since = "0.30.0", note = "use M44::col_major() and M44::set_concat()")]
685 pub fn set_concat_16(&mut self, a: &M44, col_major: &[scalar; Self::COMPONENTS]) -> &mut Self {
686 self.set_concat(a, &Self::col_major(col_major))
687 }
688
689 pub fn set_concat(&mut self, a: &M44, b: &M44) -> &mut Self {
690 unsafe {
691 self.native_mut().setConcat(a.native(), b.native());
692 }
693 self
694 }
695
696 #[deprecated(since = "0.30.0", note = "use M44::col_major() and M44::pre_concat()")]
697 #[allow(deprecated)]
698 pub fn pre_concat_16(&mut self, col_major: &[scalar; Self::COMPONENTS]) -> &mut Self {
699 self.set_concat_16(&self.clone(), col_major)
700 }
701
702 pub fn pre_concat(&mut self, m: &M44) -> &mut Self {
703 unsafe {
704 let self_ptr = self.native() as *const _;
705 self.native_mut().setConcat(self_ptr, m.native());
706 }
707 self
708 }
709
710 pub fn post_concat(&mut self, m: &M44) -> &mut Self {
711 unsafe {
712 let self_ptr = self.native() as *const _;
713 self.native_mut().setConcat(m.native(), self_ptr);
714 }
715 self
716 }
717
718 pub fn normalize_perspective(&mut self) {
719 unsafe { self.native_mut().normalizePerspective() }
720 }
721
722 pub fn is_finite(&self) -> bool {
723 is_finite(&self.mat)
724 }
725
726 #[must_use]
727 pub fn invert(&self) -> Option<M44> {
728 let mut m = Self::default();
729 unsafe { self.native().invert(m.native_mut()) }.if_true_some(m)
730 }
731
732 #[must_use]
733 pub fn transpose(&self) -> Self {
734 Self::construct(|m| unsafe { sb::C_SkM44_transpose(self.native(), m) })
735 }
736
737 pub fn dump(&self) {
738 unsafe { self.native().dump() }
739 }
740
741 pub fn map(&self, x: f32, y: f32, z: f32, w: f32) -> V4 {
742 V4::from_native_c(unsafe { sb::C_SkM44_map(self.native(), x, y, z, w) })
743 }
744
745 pub fn to_m33(&self) -> Matrix {
746 let m = &self.mat;
747 Matrix::new_all(m[0], m[4], m[12], m[1], m[5], m[13], m[3], m[7], m[15])
748 }
749
750 pub fn pre_translate(
751 &mut self,
752 x: scalar,
753 y: scalar,
754 z: impl Into<Option<scalar>>,
755 ) -> &mut Self {
756 unsafe {
757 self.native_mut()
758 .preTranslate(x, y, z.into().unwrap_or(0.0))
759 };
760 self
761 }
762
763 pub fn post_translate(
764 &mut self,
765 x: scalar,
766 y: scalar,
767 z: impl Into<Option<scalar>>,
768 ) -> &mut Self {
769 unsafe {
770 self.native_mut()
771 .postTranslate(x, y, z.into().unwrap_or(0.0))
772 };
773 self
774 }
775
776 pub fn pre_scale(&mut self, x: scalar, y: scalar) -> &mut Self {
777 unsafe { self.native_mut().preScale(x, y) };
778 self
779 }
780
781 pub fn pre_scale_xyz(&mut self, x: scalar, y: scalar, z: scalar) -> &mut Self {
782 unsafe { self.native_mut().preScale1(x, y, z) };
783 self
784 }
785}
786
787impl Mul for &M44 {
788 type Output = M44;
789
790 fn mul(self, m: Self) -> Self::Output {
791 M44::concat(self, m)
792 }
793}
794
795impl Mul<V4> for &M44 {
796 type Output = V4;
797
798 fn mul(self, v: V4) -> Self::Output {
799 self.map(v.x, v.y, v.z, v.w)
800 }
801}
802
803impl Mul<V3> for &M44 {
804 type Output = V3;
805
806 fn mul(self, v: V3) -> Self::Output {
807 let v4 = self.map(v.x, v.y, v.z, 0.0);
808 V3::new(v4.x, v4.y, v4.z)
809 }
810}
811
812impl From<&Matrix> for M44 {
813 fn from(src: &Matrix) -> Self {
814 use crate::matrix::Member::*;
815
816 Self::new(
817 src[ScaleX],
818 src[SkewX],
819 0.0,
820 src[TransX],
821 src[SkewY],
822 src[ScaleY],
823 0.0,
824 src[TransY],
825 0.0,
826 0.0,
827 1.0,
828 0.0,
829 src[Persp0],
830 src[Persp1],
831 0.0,
832 src[Persp2],
833 )
834 }
835}
836
837impl From<Matrix> for M44 {
838 fn from(m: Matrix) -> Self {
839 M44::from(&m)
840 }
841}
842
843#[cfg(test)]
844mod tests {
845 use crate::{matrix, Matrix, Rect, M44};
846
847 #[test]
848 pub fn convert_from_matrix_and_back() {
849 let vr = Rect::new(-4.5, -4.0, 4.5, 2.0);
851 let dst = Rect::new(0.0, 0.0, 1350.0, 900.0);
852
853 let m = Matrix::from_rect_to_rect(vr, dst, matrix::ScaleToFit::Center).unwrap();
854 let m44 = M44::from(m);
855 let m3 = m44.to_m33();
856 assert_eq!(m, m3);
857 }
858}