iced_core/
size.rs

1use crate::{Length, 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()
62                + (self.height * radians.sin()).abs(),
63            height: (self.width * radians.sin()).abs()
64                + (self.height * radians.cos()).abs(),
65        }
66    }
67
68    /// Applies an aspect ratio to this [`Size`] without
69    /// exceeding its bounds.
70    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    /// Returns true if either `width` or `height` are 0-sized.
80    #[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}