Skip to main content

iced_core/
size.rs

1use crate::{Alignment, Radians, Vector};
2
3/// An amount of space in 2 dimensions.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
5pub struct Size<T = f32> {
6    /// The width.
7    pub width: T,
8    /// The height.
9    pub height: T,
10}
11
12impl<T> Size<T> {
13    /// Creates a new  [`Size`] with the given width and height.
14    pub const fn new(width: T, height: T) -> Self {
15        Size { width, height }
16    }
17}
18
19impl Size {
20    /// A [`Size`] with zero width and height.
21    pub const ZERO: Size = Size::new(0., 0.);
22
23    /// A [`Size`] with a width and height of 1 unit.
24    pub const UNIT: Size = Size::new(1., 1.);
25
26    /// A [`Size`] with infinite width and height.
27    pub const INFINITE: Size = Size::new(f32::INFINITY, f32::INFINITY);
28
29    /// Returns the minimum of each component of this size and another.
30    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    /// Returns the maximum of each component of this size and another.
38    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    /// Expands this [`Size`] by the given amount.
46    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    /// Rotates this [`Size`] and returns the minimum [`Size`]
56    /// containing it.
57    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    /// Applies an aspect ratio to this [`Size`] without
67    /// exceeding its bounds.
68    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    /// Returns the offset needed to align this [`Size`] within the given
76    /// `container` using the provided alignments.
77    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}