1use crate::{Length, 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()
62 + (self.height * radians.sin()).abs(),
63 height: (self.width * radians.sin()).abs()
64 + (self.height * radians.cos()).abs(),
65 }
66 }
67
68 pub const fn ratio(self, aspect_ratio: f32) -> Size {
71 Size {
72 width: (self.height * aspect_ratio).min(self.width),
73 height: (self.width / aspect_ratio).min(self.height),
74 }
75 }
76}
77
78impl Size<Length> {
79 #[inline]
81 pub fn is_void(&self) -> bool {
82 matches!(self.width, Length::Fixed(0.0))
83 || matches!(self.height, Length::Fixed(0.0))
84 }
85}
86
87impl<T> From<[T; 2]> for Size<T> {
88 fn from([width, height]: [T; 2]) -> Self {
89 Size { width, height }
90 }
91}
92
93impl<T> From<(T, T)> for Size<T> {
94 fn from((width, height): (T, T)) -> Self {
95 Self { width, height }
96 }
97}
98
99impl From<(u32, u32)> for Size {
100 fn from((width, height): (u32, u32)) -> Self {
101 Size::new(width as f32, height as f32)
102 }
103}
104
105impl<T> From<Vector<T>> for Size<T> {
106 fn from(vector: Vector<T>) -> Self {
107 Size {
108 width: vector.x,
109 height: vector.y,
110 }
111 }
112}
113
114impl<T> From<Size<T>> for [T; 2] {
115 fn from(size: Size<T>) -> Self {
116 [size.width, size.height]
117 }
118}
119
120impl<T> From<Size<T>> for Vector<T> {
121 fn from(size: Size<T>) -> Self {
122 Vector::new(size.width, size.height)
123 }
124}
125
126impl<T> std::ops::Add for Size<T>
127where
128 T: std::ops::Add<Output = T>,
129{
130 type Output = Size<T>;
131
132 fn add(self, rhs: Self) -> Self::Output {
133 Size {
134 width: self.width + rhs.width,
135 height: self.height + rhs.height,
136 }
137 }
138}
139
140impl<T> std::ops::Sub for Size<T>
141where
142 T: std::ops::Sub<Output = T>,
143{
144 type Output = Size<T>;
145
146 fn sub(self, rhs: Self) -> Self::Output {
147 Size {
148 width: self.width - rhs.width,
149 height: self.height - rhs.height,
150 }
151 }
152}
153
154impl<T> std::ops::Mul<T> for Size<T>
155where
156 T: std::ops::Mul<Output = T> + Copy,
157{
158 type Output = Size<T>;
159
160 fn mul(self, rhs: T) -> Self::Output {
161 Size {
162 width: self.width * rhs,
163 height: self.height * rhs,
164 }
165 }
166}
167
168impl<T> std::ops::Div<T> for Size<T>
169where
170 T: std::ops::Div<Output = T> + Copy,
171{
172 type Output = Size<T>;
173
174 fn div(self, rhs: T) -> Self::Output {
175 Size {
176 width: self.width / rhs,
177 height: self.height / rhs,
178 }
179 }
180}
181
182impl<T> std::ops::Mul<Vector<T>> for Size<T>
183where
184 T: std::ops::Mul<Output = T> + Copy,
185{
186 type Output = Size<T>;
187
188 fn mul(self, scale: Vector<T>) -> Self::Output {
189 Size {
190 width: self.width * scale.x,
191 height: self.height * scale.y,
192 }
193 }
194}