1use crate::{Alignment, Radians, Vector};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
5pub struct Size<T = f32> {
6 pub width: T,
8 pub height: T,
10}
11
12impl<T> Size<T> {
13 pub const fn new(width: T, height: T) -> Self {
15 Size { width, height }
16 }
17}
18
19impl Size {
20 pub const ZERO: Size = Size::new(0., 0.);
22
23 pub const UNIT: Size = Size::new(1., 1.);
25
26 pub const INFINITE: Size = Size::new(f32::INFINITY, f32::INFINITY);
28
29 pub fn min(self, other: Self) -> Self {
31 Size {
32 width: self.width.min(other.width),
33 height: self.height.min(other.height),
34 }
35 }
36
37 pub fn max(self, other: Self) -> Self {
39 Size {
40 width: self.width.max(other.width),
41 height: self.height.max(other.height),
42 }
43 }
44
45 pub fn expand(self, other: impl Into<Size>) -> Self {
47 let other = other.into();
48
49 Size {
50 width: self.width + other.width,
51 height: self.height + other.height,
52 }
53 }
54
55 pub fn rotate(self, rotation: Radians) -> Size {
58 let radians = f32::from(rotation);
59
60 Size {
61 width: (self.width * radians.cos()).abs() + (self.height * radians.sin()).abs(),
62 height: (self.width * radians.sin()).abs() + (self.height * radians.cos()).abs(),
63 }
64 }
65
66 pub const fn ratio(self, aspect_ratio: f32) -> Size {
69 Size {
70 width: (self.height * aspect_ratio).min(self.width),
71 height: (self.width / aspect_ratio).min(self.height),
72 }
73 }
74
75 pub fn align(self, container: Size, align_x: Alignment, align_y: Alignment) -> Vector {
78 let x = match align_x {
79 Alignment::Start => 0.0,
80 Alignment::Center => (container.width - self.width) / 2.0,
81 Alignment::End => container.width - self.width,
82 };
83
84 let y = match align_y {
85 Alignment::Start => 0.0,
86 Alignment::Center => (container.height - self.height) / 2.0,
87 Alignment::End => container.height - self.height,
88 };
89
90 Vector { x, y }
91 }
92}
93
94impl<T> From<[T; 2]> for Size<T> {
95 fn from([width, height]: [T; 2]) -> Self {
96 Size { width, height }
97 }
98}
99
100impl<T> From<(T, T)> for Size<T> {
101 fn from((width, height): (T, T)) -> Self {
102 Self { width, height }
103 }
104}
105
106impl From<(u32, u32)> for Size {
107 fn from((width, height): (u32, u32)) -> Self {
108 Size::new(width as f32, height as f32)
109 }
110}
111
112impl<T> From<Vector<T>> for Size<T> {
113 fn from(vector: Vector<T>) -> Self {
114 Size {
115 width: vector.x,
116 height: vector.y,
117 }
118 }
119}
120
121impl<T> From<Size<T>> for [T; 2] {
122 fn from(size: Size<T>) -> Self {
123 [size.width, size.height]
124 }
125}
126
127impl<T> From<Size<T>> for Vector<T> {
128 fn from(size: Size<T>) -> Self {
129 Vector::new(size.width, size.height)
130 }
131}
132
133impl<T> std::ops::Add for Size<T>
134where
135 T: std::ops::Add<Output = T>,
136{
137 type Output = Size<T>;
138
139 fn add(self, rhs: Self) -> Self::Output {
140 Size {
141 width: self.width + rhs.width,
142 height: self.height + rhs.height,
143 }
144 }
145}
146
147impl<T> std::ops::Sub for Size<T>
148where
149 T: std::ops::Sub<Output = T>,
150{
151 type Output = Size<T>;
152
153 fn sub(self, rhs: Self) -> Self::Output {
154 Size {
155 width: self.width - rhs.width,
156 height: self.height - rhs.height,
157 }
158 }
159}
160
161impl<T> std::ops::Mul<T> for Size<T>
162where
163 T: std::ops::Mul<Output = T> + Copy,
164{
165 type Output = Size<T>;
166
167 fn mul(self, rhs: T) -> Self::Output {
168 Size {
169 width: self.width * rhs,
170 height: self.height * rhs,
171 }
172 }
173}
174
175impl<T> std::ops::Div<T> for Size<T>
176where
177 T: std::ops::Div<Output = T> + Copy,
178{
179 type Output = Size<T>;
180
181 fn div(self, rhs: T) -> Self::Output {
182 Size {
183 width: self.width / rhs,
184 height: self.height / rhs,
185 }
186 }
187}
188
189impl<T> std::ops::Mul<Vector<T>> for Size<T>
190where
191 T: std::ops::Mul<Output = T> + Copy,
192{
193 type Output = Size<T>;
194
195 fn mul(self, scale: Vector<T>) -> Self::Output {
196 Size {
197 width: self.width * scale.x,
198 height: self.height * scale.y,
199 }
200 }
201}