embedded_graphics_core/primitives/rectangle/
points.rs

1use core::ops::Range;
2
3use crate::{geometry::Point, primitives::Rectangle};
4
5/// Iterator over all points inside the rectangle.
6#[derive(Clone, Eq, PartialEq, Hash, Debug)]
7#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
8pub struct Points {
9    x: Range<i32>,
10    y: Range<i32>,
11    x_start: i32,
12}
13
14impl Points {
15    pub(in crate::primitives::rectangle) fn new(rectangle: &Rectangle) -> Self {
16        // Return `Self::empty` for all zero sized rectangles.
17        // The iterator would behave correctly without this check, but would loop unnecessarily for
18        // rectangles with zero width.
19        if rectangle.is_zero_sized() {
20            return Self::empty();
21        }
22
23        let x = rectangle.columns();
24        let y = rectangle.rows();
25        let x_start = x.start;
26
27        Self { x, y, x_start }
28    }
29
30    /// Create a points iterator that returns no items.
31    pub const fn empty() -> Self {
32        Self {
33            x: 0..0,
34            y: 0..0,
35            x_start: 0,
36        }
37    }
38}
39
40impl Iterator for Points {
41    type Item = Point;
42
43    #[inline]
44    fn next(&mut self) -> Option<Self::Item> {
45        while !self.y.is_empty() {
46            if let Some(x) = self.x.next() {
47                return Some(Point::new(x, self.y.start));
48            }
49
50            self.y.next();
51            self.x.start = self.x_start;
52        }
53
54        None
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::{
62        geometry::{Point, Size},
63        primitives::{PointsIter, Rectangle},
64    };
65
66    #[test]
67    fn points_iter() {
68        let rectangle = Rectangle::new(Point::new(10, 20), Size::new(2, 3));
69
70        let mut points = rectangle.points();
71        assert_eq!(points.next(), Some(Point::new(10, 20)));
72        assert_eq!(points.next(), Some(Point::new(11, 20)));
73        assert_eq!(points.next(), Some(Point::new(10, 21)));
74        assert_eq!(points.next(), Some(Point::new(11, 21)));
75        assert_eq!(points.next(), Some(Point::new(10, 22)));
76        assert_eq!(points.next(), Some(Point::new(11, 22)));
77        assert_eq!(points.next(), None);
78    }
79
80    #[test]
81    fn points_iter_zero_size() {
82        let rectangle = Rectangle::new(Point::new(1, 2), Size::zero());
83
84        let mut points = rectangle.points();
85        assert_eq!(points.next(), None);
86    }
87
88    #[test]
89    fn points_iter_zero_size_x() {
90        let rectangle = Rectangle::new(Point::new(1, 2), Size::new(0, 1));
91
92        let mut points = rectangle.points();
93        assert_eq!(points.next(), None);
94    }
95
96    #[test]
97    fn points_iter_zero_size_y() {
98        let rectangle = Rectangle::new(Point::new(1, 2), Size::new(1, 0));
99
100        let mut points = rectangle.points();
101        assert_eq!(points.next(), None);
102    }
103
104    #[test]
105    fn points_iter_empty() {
106        let mut points = Points::empty();
107        assert_eq!(points.next(), None);
108    }
109}