vizia_core/style/
transform.rs

1use skia_safe::Matrix;
2use vizia_style::{Angle, Scale, Transform, Translate};
3
4use crate::layout::BoundingBox;
5
6/// Trait for converting a transform definition into a `Matrix`.
7pub(crate) trait IntoTransform {
8    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix;
9}
10
11impl IntoTransform for Translate {
12    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix {
13        let tx = self.x.to_pixels(bounds.w, scale_factor);
14        let ty = self.y.to_pixels(bounds.h, scale_factor);
15
16        Matrix::translate((tx, ty))
17    }
18}
19
20impl IntoTransform for Scale {
21    fn as_transform(&self, _bounds: BoundingBox, _scale_factor: f32) -> Matrix {
22        let sx = self.x.to_factor();
23        let sy = self.y.to_factor();
24
25        Matrix::scale((sx, sy))
26    }
27}
28
29impl IntoTransform for Angle {
30    fn as_transform(&self, _bounds: BoundingBox, _scale_factor: f32) -> Matrix {
31        let r = self.to_radians();
32
33        Matrix::rotate_rad(r)
34    }
35}
36
37impl IntoTransform for Vec<Transform> {
38    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix {
39        let mut result = Matrix::new_identity();
40        for transform in self.iter() {
41            let t = match transform {
42                Transform::Translate(translate) => {
43                    let tx = translate.0.to_pixels(bounds.w, scale_factor);
44                    let ty = translate.1.to_pixels(bounds.h, scale_factor);
45
46                    Matrix::translate((tx, ty))
47                }
48
49                Transform::TranslateX(x) => {
50                    let tx = x.to_pixels(bounds.w, scale_factor);
51
52                    Matrix::translate((tx, 0.0))
53                }
54
55                Transform::TranslateY(y) => {
56                    let ty = y.to_pixels(bounds.h, scale_factor);
57
58                    Matrix::translate((0.0, ty))
59                }
60
61                Transform::Scale(scale) => {
62                    let sx = scale.0.to_factor();
63                    let sy = scale.1.to_factor();
64
65                    Matrix::scale((sx, sy))
66                }
67
68                Transform::ScaleX(x) => {
69                    let sx = x.to_factor();
70
71                    Matrix::scale((sx, 1.0))
72                }
73
74                Transform::ScaleY(y) => {
75                    let sy = y.to_factor();
76
77                    Matrix::scale((1.0, sy))
78                }
79
80                Transform::Rotate(angle) => Matrix::rotate_rad(angle.to_radians()),
81
82                Transform::Skew(x, y) => {
83                    let cx = x.to_radians().tan();
84                    let cy = y.to_radians().tan();
85
86                    Matrix::skew((cx, cy))
87                }
88
89                Transform::SkewX(angle) => {
90                    let cx = angle.to_radians().tan();
91
92                    Matrix::skew((cx, 0.0))
93                }
94
95                Transform::SkewY(angle) => {
96                    let cy = angle.to_radians().tan();
97
98                    Matrix::skew((0.0, cy))
99                }
100
101                Transform::Matrix(matrix) => Matrix::new_all(
102                    matrix.a, matrix.c, matrix.e, matrix.b, matrix.d, matrix.f, 0.0, 0.0, 1.0,
103                ),
104            };
105
106            result = result * t;
107        }
108
109        result
110    }
111}