embedded_graphics_core/geometry/
size.rs1use core::{
2 fmt,
3 ops::{Add, AddAssign, Div, DivAssign, Index, Mul, MulAssign, Sub, SubAssign},
4};
5
6use crate::geometry::Point;
7
8#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
64#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
65pub struct Size {
66 pub width: u32,
68
69 pub height: u32,
71}
72
73impl Size {
74 pub const fn new(width: u32, height: u32) -> Self {
76 Size { width, height }
77 }
78
79 pub const fn new_equal(value: u32) -> Self {
95 Size {
96 width: value,
97 height: value,
98 }
99 }
100
101 pub const fn zero() -> Self {
103 Size {
104 width: 0,
105 height: 0,
106 }
107 }
108
109 pub const fn x_axis(self) -> Self {
127 Self {
128 width: self.width,
129 height: 0,
130 }
131 }
132
133 pub const fn y_axis(self) -> Self {
151 Self {
152 width: 0,
153 height: self.height,
154 }
155 }
156
157 pub const fn saturating_add(self, other: Self) -> Self {
161 Self {
162 width: self.width.saturating_add(other.width),
163 height: self.height.saturating_add(other.height),
164 }
165 }
166
167 pub const fn saturating_sub(self, other: Self) -> Self {
172 Self {
173 width: self.width.saturating_sub(other.width),
174 height: self.height.saturating_sub(other.height),
175 }
176 }
177
178 pub(crate) const fn div_u32(self, rhs: u32) -> Size {
182 Size::new(self.width / rhs, self.height / rhs)
183 }
184
185 pub(crate) const fn from_bounding_box(corner_1: Point, corner_2: Point) -> Self {
187 let width = (corner_1.x - corner_2.x).abs() as u32 + 1;
188 let height = (corner_1.y - corner_2.y).abs() as u32 + 1;
189
190 Self { width, height }
191 }
192
193 pub fn component_min(self, other: Self) -> Self {
203 Self::new(self.width.min(other.width), self.height.min(other.height))
204 }
205
206 pub fn component_max(self, other: Self) -> Self {
216 Self::new(self.width.max(other.width), self.height.max(other.height))
217 }
218
219 pub const fn component_mul(self, other: Self) -> Self {
229 Self::new(self.width * other.width, self.height * other.height)
230 }
231
232 pub const fn component_div(self, other: Self) -> Self {
246 Self::new(self.width / other.width, self.height / other.height)
247 }
248}
249
250impl Add for Size {
251 type Output = Size;
252
253 fn add(self, other: Size) -> Size {
254 Size::new(self.width + other.width, self.height + other.height)
255 }
256}
257
258impl AddAssign for Size {
259 fn add_assign(&mut self, other: Size) {
260 self.width += other.width;
261 self.height += other.height;
262 }
263}
264
265impl Sub for Size {
266 type Output = Size;
267
268 fn sub(self, other: Size) -> Size {
269 Size::new(self.width - other.width, self.height - other.height)
270 }
271}
272
273impl SubAssign for Size {
274 fn sub_assign(&mut self, other: Size) {
275 self.width -= other.width;
276 self.height -= other.height;
277 }
278}
279
280impl Mul<u32> for Size {
281 type Output = Size;
282
283 fn mul(self, rhs: u32) -> Size {
284 Size::new(self.width * rhs, self.height * rhs)
285 }
286}
287
288impl MulAssign<u32> for Size {
289 fn mul_assign(&mut self, rhs: u32) {
290 self.width *= rhs;
291 self.height *= rhs;
292 }
293}
294
295impl Div<u32> for Size {
296 type Output = Size;
297
298 fn div(self, rhs: u32) -> Size {
299 self.div_u32(rhs)
300 }
301}
302
303impl DivAssign<u32> for Size {
304 fn div_assign(&mut self, rhs: u32) {
305 self.width /= rhs;
306 self.height /= rhs;
307 }
308}
309
310impl Index<usize> for Size {
311 type Output = u32;
312
313 fn index(&self, idx: usize) -> &u32 {
314 match idx {
315 0 => &self.width,
316 1 => &self.height,
317 _ => panic!("index out of bounds: the len is 2 but the index is {}", idx),
318 }
319 }
320}
321
322impl From<(u32, u32)> for Size {
323 fn from(other: (u32, u32)) -> Self {
324 Size::new(other.0, other.1)
325 }
326}
327
328impl From<[u32; 2]> for Size {
329 fn from(other: [u32; 2]) -> Self {
330 Size::new(other[0], other[1])
331 }
332}
333
334impl From<&[u32; 2]> for Size {
335 fn from(other: &[u32; 2]) -> Self {
336 Size::new(other[0], other[1])
337 }
338}
339
340impl From<Size> for (u32, u32) {
341 fn from(other: Size) -> (u32, u32) {
342 (other.width, other.height)
343 }
344}
345
346impl From<Size> for [u32; 2] {
347 fn from(other: Size) -> [u32; 2] {
348 [other.width, other.height]
349 }
350}
351
352impl From<&Size> for (u32, u32) {
353 fn from(other: &Size) -> (u32, u32) {
354 (other.width, other.height)
355 }
356}
357
358impl fmt::Display for Size {
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 write!(f, "{} x {}", self.width, self.height)
361 }
362}
363
364#[cfg(feature = "nalgebra_support")]
365use nalgebra::{base::Scalar, Vector2};
366
367#[cfg(feature = "nalgebra_support")]
368impl<N> From<Vector2<N>> for Size
369where
370 N: Into<u32> + Scalar + Copy,
371{
372 fn from(other: Vector2<N>) -> Self {
373 Self::new(other[0].into(), other[1].into())
374 }
375}
376
377#[cfg(feature = "nalgebra_support")]
378impl<N> From<&Vector2<N>> for Size
379where
380 N: Into<u32> + Scalar + Copy,
381{
382 fn from(other: &Vector2<N>) -> Self {
383 Self::new(other[0].into(), other[1].into())
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 use core::fmt::Write;
392
393 #[test]
394 fn sizes_can_be_added() {
395 let left = Size::new(10, 20);
396 let right = Size::new(30, 40);
397
398 assert_eq!(left + right, Size::new(40, 60));
399 }
400
401 #[test]
402 fn sizes_can_be_subtracted() {
403 let left = Size::new(30, 40);
404 let right = Size::new(10, 20);
405
406 assert_eq!(left - right, Size::new(20, 20));
407 }
408
409 #[test]
410 fn saturating_sub() {
411 let p = Size::new(10, 20);
412
413 assert_eq!(p.saturating_sub(Size::new(9, 18)), Size::new(1, 2));
414 assert_eq!(p.saturating_sub(Size::new(11, 18)), Size::new(0, 2));
415 assert_eq!(p.saturating_sub(Size::new(9, 21)), Size::new(1, 0));
416 assert_eq!(p.saturating_sub(Size::new(11, 21)), Size::new(0, 0));
417 }
418
419 #[test]
420 fn sizes_can_be_multiplied_by_scalar() {
421 let s = Size::new(1, 2);
422 assert_eq!(s * 3, Size::new(3, 6));
423
424 let mut s = Size::new(2, 3);
425 s *= 4;
426 assert_eq!(s, Size::new(8, 12));
427 }
428
429 #[test]
430 fn sizes_can_be_divided_by_scalar() {
431 let s = Size::new(10, 20);
432 assert_eq!(s / 2, Size::new(5, 10));
433
434 let mut s = Size::new(20, 30);
435 s /= 5;
436 assert_eq!(s, Size::new(4, 6));
437 }
438
439 #[test]
440 fn from_tuple() {
441 assert_eq!(Size::from((20, 30)), Size::new(20, 30));
442 }
443
444 #[test]
445 fn from_array() {
446 assert_eq!(Size::from([20, 30]), Size::new(20, 30));
447 }
448
449 #[test]
450 fn to_array() {
451 let array: [u32; 2] = Size::new(20, 30).into();
452
453 assert_eq!(array, [20, 30]);
454 }
455
456 #[test]
457 fn from_array_ref() {
458 assert_eq!(Size::from(&[20, 30]), Size::new(20, 30));
459 }
460
461 #[test]
462 fn index() {
463 let size = Size::new(1, 2);
464
465 assert_eq!(size.width, size[0]);
466 assert_eq!(size.height, size[1]);
467 }
468
469 #[test]
470 #[should_panic]
471 fn index_out_of_bounds() {
472 let size = Size::new(1, 2);
473 let _ = size[2];
474 }
475
476 #[test]
477 #[cfg(feature = "nalgebra_support")]
478 fn nalgebra_support() {
479 let left = nalgebra::Vector2::new(30u32, 40);
480 let right = nalgebra::Vector2::new(10, 20);
481
482 assert_eq!(Size::from(left - right), Size::new(20, 20));
483 }
484
485 #[test]
486 fn component_min_max() {
487 let a = Size::new(20, 30);
488 let b = Size::new(15, 50);
489
490 assert_eq!(a.component_min(b), Size::new(15, 30));
491 assert_eq!(a.component_max(b), Size::new(20, 50));
492 }
493
494 #[test]
495 fn display() {
496 let mut buffer = arrayvec::ArrayString::<32>::new();
497 write!(buffer, "{}", Size::new(123, 456)).unwrap();
498
499 assert_eq!(&buffer, "123 x 456");
500 }
501}