embedded_graphics/primitives/rounded_rectangle/
points.rs1use crate::{
2 geometry::Point,
3 primitives::{
4 common::Scanline,
5 rounded_rectangle::{RoundedRectangle, RoundedRectangleContains},
6 ContainsPoint,
7 },
8};
9
10#[derive(Clone, Eq, PartialEq, Hash, Debug)]
12#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
13pub struct Points {
14 scanlines: Scanlines,
15 current_scanline: Scanline,
16}
17
18impl Points {
19 pub(in crate::primitives) fn new(rounded_rectangle: &RoundedRectangle) -> Self {
20 Self {
21 scanlines: Scanlines::new(rounded_rectangle),
22 current_scanline: Scanline::new_empty(0),
23 }
24 }
25}
26
27impl Iterator for Points {
28 type Item = Point;
29
30 fn next(&mut self) -> Option<Self::Item> {
31 self.current_scanline.next().or_else(|| {
32 self.current_scanline = self.scanlines.next()?;
33 self.current_scanline.next()
34 })
35 }
36}
37
38#[derive(Clone, Eq, PartialEq, Hash, Debug)]
39#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
40pub struct Scanlines {
41 rounded_rectangle: RoundedRectangleContains,
42}
43
44impl Scanlines {
45 pub fn new(rounded_rectangle: &RoundedRectangle) -> Self {
46 Self {
47 rounded_rectangle: RoundedRectangleContains::new(rounded_rectangle),
48 }
49 }
50}
51
52impl Iterator for Scanlines {
53 type Item = Scanline;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 let columns = self.rounded_rectangle.columns.clone();
57 let y = self.rounded_rectangle.rows.next()?;
58
59 let x_start = if y < self.rounded_rectangle.straight_rows_left.start {
60 columns
61 .clone()
62 .find(|x| self.rounded_rectangle.top_left.contains(Point::new(*x, y)))
63 } else if y >= self.rounded_rectangle.straight_rows_left.end {
64 columns.clone().find(|x| {
65 self.rounded_rectangle
66 .bottom_left
67 .contains(Point::new(*x, y))
68 })
69 } else {
70 None
71 }
72 .unwrap_or(columns.start);
73
74 let x_end = if y < self.rounded_rectangle.straight_rows_right.start {
75 columns
76 .clone()
77 .rfind(|x| self.rounded_rectangle.top_right.contains(Point::new(*x, y)))
78 } else if y >= self.rounded_rectangle.straight_rows_right.end {
79 columns.clone().rfind(|x| {
80 self.rounded_rectangle
81 .bottom_right
82 .contains(Point::new(*x, y))
83 })
84 } else {
85 None
86 }
87 .map(|x| x + 1)
88 .unwrap_or(columns.end);
89
90 Some(Scanline::new(y, x_start..x_end))
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use crate::{
98 geometry::Size,
99 mock_display::MockDisplay,
100 pixelcolor::BinaryColor,
101 primitives::{PointsIter, Primitive, PrimitiveStyle, Rectangle},
102 Drawable,
103 };
104
105 #[test]
106 fn points_equals_filled() {
107 let rounded_rect = RoundedRectangle::with_equal_corners(
108 Rectangle::new(Point::zero(), Size::new(10, 20)),
109 Size::new(4, 8),
110 );
111
112 let mut expected = MockDisplay::new();
113 rounded_rect
114 .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
115 .draw(&mut expected)
116 .unwrap();
117
118 MockDisplay::from_points(rounded_rect.points(), BinaryColor::On).assert_eq(&expected);
119 }
120}