vizia_core/style/
transform.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use skia_safe::Matrix;
use vizia_style::{Angle, Scale, Transform, Translate};

use crate::layout::BoundingBox;

/// Trait for converting a transform definition into a `Matrix`.
pub(crate) trait IntoTransform {
    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix;
}

impl IntoTransform for Translate {
    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix {
        let tx = self.x.to_pixels(bounds.w, scale_factor);
        let ty = self.y.to_pixels(bounds.h, scale_factor);

        Matrix::translate((tx, ty))
    }
}

impl IntoTransform for Scale {
    fn as_transform(&self, _bounds: BoundingBox, _scale_factor: f32) -> Matrix {
        let sx = self.x.to_factor();
        let sy = self.y.to_factor();

        Matrix::scale((sx, sy))
    }
}

impl IntoTransform for Angle {
    fn as_transform(&self, _bounds: BoundingBox, _scale_factor: f32) -> Matrix {
        let r = self.to_radians();

        Matrix::rotate_rad(r)
    }
}

impl IntoTransform for Vec<Transform> {
    fn as_transform(&self, bounds: BoundingBox, scale_factor: f32) -> Matrix {
        let mut result = Matrix::new_identity();
        for transform in self.iter() {
            let t = match transform {
                Transform::Translate(translate) => {
                    let tx = translate.0.to_pixels(bounds.w, scale_factor);
                    let ty = translate.1.to_pixels(bounds.h, scale_factor);

                    Matrix::translate((tx, ty))
                }

                Transform::TranslateX(x) => {
                    let tx = x.to_pixels(bounds.w, scale_factor);

                    Matrix::translate((tx, 0.0))
                }

                Transform::TranslateY(y) => {
                    let ty = y.to_pixels(bounds.h, scale_factor);

                    Matrix::translate((0.0, ty))
                }

                Transform::Scale(scale) => {
                    let sx = scale.0.to_factor();
                    let sy = scale.1.to_factor();

                    Matrix::scale((sx, sy))
                }

                Transform::ScaleX(x) => {
                    let sx = x.to_factor();

                    Matrix::scale((sx, 1.0))
                }

                Transform::ScaleY(y) => {
                    let sy = y.to_factor();

                    Matrix::scale((1.0, sy))
                }

                Transform::Rotate(angle) => Matrix::rotate_rad(angle.to_radians()),

                Transform::Skew(x, y) => {
                    let cx = x.to_radians().tan();
                    let cy = y.to_radians().tan();

                    Matrix::skew((cx, cy))
                }

                Transform::SkewX(angle) => {
                    let cx = angle.to_radians().tan();

                    Matrix::skew((cx, 0.0))
                }

                Transform::SkewY(angle) => {
                    let cy = angle.to_radians().tan();

                    Matrix::skew((0.0, cy))
                }

                Transform::Matrix(matrix) => Matrix::new_all(
                    matrix.a, matrix.c, matrix.e, matrix.b, matrix.d, matrix.f, 0.0, 0.0, 1.0,
                ),
            };

            result = result * t;
        }

        result
    }
}