rive_rs/math/
mat.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::ops::Mul;
6
7use crate::math::Vec;
8
9#[derive(Clone, Copy, Debug, PartialEq)]
10pub struct Mat {
11    pub scale_x: f32,
12    pub shear_y: f32,
13    pub shear_x: f32,
14    pub scale_y: f32,
15    pub translate_x: f32,
16    pub translate_y: f32,
17}
18
19impl Mat {
20    pub fn zero() -> Self {
21        Self {
22            scale_x: 0.0,
23            shear_y: 0.0,
24            shear_x: 0.0,
25            scale_y: 0.0,
26            translate_x: 0.0,
27            translate_y: 0.0,
28        }
29    }
30
31    pub fn from_rotation(rad: f32) -> Self {
32        let (sin, cos) = rad.sin_cos();
33        Self { scale_x: cos, shear_y: sin, shear_x: -sin, scale_y: cos, ..Default::default() }
34    }
35
36    pub fn scale(mut self, scale: Vec) -> Self {
37        self.scale_x *= scale.x;
38        self.shear_y *= scale.x;
39        self.shear_x *= scale.y;
40        self.scale_y *= scale.y;
41
42        self
43    }
44
45    pub fn invert(self) -> Option<Self> {
46        let mut det = self.scale_x * self.scale_y - self.shear_y * self.shear_x;
47
48        if det == 0.0 {
49            return None;
50        }
51
52        det = det.recip();
53
54        Some(Mat {
55            scale_x: self.scale_y * det,
56            shear_y: -self.shear_y * det,
57            shear_x: -self.shear_x * det,
58            scale_y: self.scale_x * det,
59            translate_x: (self.shear_x * self.translate_y - self.scale_y * self.translate_x) * det,
60            translate_y: (self.shear_y * self.translate_x - self.scale_x * self.translate_y) * det,
61        })
62    }
63}
64
65impl Default for Mat {
66    fn default() -> Self {
67        Self {
68            scale_x: 1.0,
69            shear_y: 0.0,
70            shear_x: 0.0,
71            scale_y: 1.0,
72            translate_x: 0.0,
73            translate_y: 0.0,
74        }
75    }
76}
77
78impl Eq for Mat {}
79
80impl Mul for Mat {
81    type Output = Self;
82
83    fn mul(self, rhs: Self) -> Self::Output {
84        Self {
85            scale_x: self.scale_x * rhs.scale_x + self.shear_x * rhs.shear_y,
86            shear_y: self.shear_y * rhs.scale_x + self.scale_y * rhs.shear_y,
87            shear_x: self.scale_x * rhs.shear_x + self.shear_x * rhs.scale_y,
88            scale_y: self.shear_y * rhs.shear_x + self.scale_y * rhs.scale_y,
89            translate_x: self.scale_x * rhs.translate_x
90                + self.shear_x * rhs.translate_y
91                + self.translate_x,
92            translate_y: self.shear_y * rhs.translate_x
93                + self.scale_y * rhs.translate_y
94                + self.translate_y,
95        }
96    }
97}
98
99impl Mul<Vec> for Mat {
100    type Output = Vec;
101
102    fn mul(self, rhs: Vec) -> Self::Output {
103        Vec::new(
104            rhs.x * self.scale_x + rhs.y * self.shear_x + self.translate_x,
105            rhs.x * self.shear_y + rhs.y * self.scale_y + self.translate_y,
106        )
107    }
108}