rive_rs/
layout.rs
1use crate::math::{self, Aabb, Mat};
6
7#[derive(Clone, Copy, Debug)]
8pub enum Fit {
9 Fill,
10 Contain,
11 Cover,
12 FitWidth,
13 FitHeight,
14 None,
15 ScaleDown,
16}
17
18#[derive(Clone, Copy, Debug)]
19pub struct Alignment(math::Vec);
20
21impl Alignment {
22 pub const fn new(x: f32, y: f32) -> Self {
23 Self(math::Vec::new(x, y))
24 }
25
26 pub const fn top_left() -> Self {
27 Self::new(-1.0, -1.0)
28 }
29
30 pub const fn top_center() -> Self {
31 Self::new(0.0, -1.0)
32 }
33
34 pub const fn top_right() -> Self {
35 Self::new(1.0, -1.0)
36 }
37
38 pub const fn center_left() -> Self {
39 Self::new(-1.0, 0.0)
40 }
41
42 pub const fn center() -> Self {
43 Self::new(0.0, 0.0)
44 }
45
46 pub const fn center_right() -> Self {
47 Self::new(1.0, 0.0)
48 }
49
50 pub const fn bottom_left() -> Self {
51 Self::new(-1.0, 1.0)
52 }
53
54 pub const fn bottom_center() -> Self {
55 Self::new(0.0, 1.0)
56 }
57
58 pub const fn bottom_right() -> Self {
59 Self::new(1.0, 1.0)
60 }
61}
62
63pub fn align(fit: Fit, alignment: Alignment, frame: Aabb, content: Aabb) -> Mat {
64 let content_size = content.size();
65 let conent_half_size = content_size * 0.5;
66
67 let pos = -content.min - conent_half_size - alignment.0 * conent_half_size;
68
69 let scale_vec = match fit {
70 Fit::Fill => frame.size() / content_size,
71 Fit::Contain => {
72 let scaled = frame.size() / content_size;
73 let min_scale = scaled.x.min(scaled.y);
74
75 math::Vec::new(min_scale, min_scale)
76 }
77 Fit::Cover => {
78 let scaled = frame.size() / content_size;
79 let max_scale = scaled.x.max(scaled.y);
80
81 math::Vec::new(max_scale, max_scale)
82 }
83 Fit::FitWidth => {
84 let min_scale = frame.size().x / content_size.x;
85
86 math::Vec::new(min_scale, min_scale)
87 }
88 Fit::FitHeight => {
89 let min_scale = frame.size().y / content_size.y;
90
91 math::Vec::new(min_scale, min_scale)
92 }
93 Fit::None => math::Vec::new(1.0, 1.0),
94 Fit::ScaleDown => {
95 let scaled = frame.size() / content_size;
96 let min_scale = scaled.x.min(scaled.y).min(1.0);
97
98 math::Vec::new(min_scale, min_scale)
99 }
100 };
101
102 let frame_half_size = frame.size() * 0.5;
103 let translation_vec = frame.min + frame_half_size + alignment.0 * frame_half_size;
104
105 let translation = Mat {
106 translate_x: translation_vec.x,
107 translate_y: translation_vec.y,
108 ..Default::default()
109 };
110
111 let scale = Mat { scale_x: scale_vec.x, scale_y: scale_vec.y, ..Default::default() };
112
113 let translation_back = Mat { translate_x: pos.x, translate_y: pos.y, ..Default::default() };
114
115 translation * scale * translation_back
116}