skia_safe/core/
m44.rs

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        // taken from skulpin's physics example.
850        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}