embedded_graphics/draw_target/
translated.rs1use crate::{
2 draw_target::DrawTarget,
3 geometry::{Dimensions, Point},
4 iterator::PixelIteratorExt,
5 primitives::Rectangle,
6 transform::Transform,
7 Pixel,
8};
9
10#[derive(Debug)]
17#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
18pub struct Translated<'a, T>
19where
20 T: DrawTarget,
21{
22 parent: &'a mut T,
23 offset: Point,
24}
25
26impl<'a, T> Translated<'a, T>
27where
28 T: DrawTarget,
29{
30 pub(super) fn new(parent: &'a mut T, offset: Point) -> Self {
31 Self { parent, offset }
32 }
33}
34
35impl<T> DrawTarget for Translated<'_, T>
36where
37 T: DrawTarget,
38{
39 type Color = T::Color;
40 type Error = T::Error;
41
42 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
43 where
44 I: IntoIterator<Item = Pixel<Self::Color>>,
45 {
46 self.parent
47 .draw_iter(pixels.into_iter().translated(self.offset))
48 }
49
50 fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
51 where
52 I: IntoIterator<Item = Self::Color>,
53 {
54 let area = area.translate(self.offset);
55 self.parent.fill_contiguous(&area, colors)
56 }
57
58 fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
59 let area = area.translate(self.offset);
60 self.parent.fill_solid(&area, color)
61 }
62
63 fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
64 self.parent.clear(color)
65 }
66}
67
68impl<T> Dimensions for Translated<'_, T>
69where
70 T: DrawTarget,
71{
72 fn bounding_box(&self) -> Rectangle {
73 self.parent.bounding_box().translate(-self.offset)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use crate::{
80 draw_target::{DrawTarget, DrawTargetExt},
81 geometry::Dimensions,
82 geometry::{Point, Size},
83 mock_display::MockDisplay,
84 pixelcolor::BinaryColor,
85 primitives::Rectangle,
86 transform::Transform,
87 Pixel,
88 };
89
90 #[test]
91 fn draw_iter() {
92 let mut display = MockDisplay::new();
93
94 let mut translated = display.translated(Point::new(2, 3));
95
96 let pixels = [
97 Pixel(Point::new(0, 0), BinaryColor::On),
98 Pixel(Point::new(1, 2), BinaryColor::Off),
99 ];
100 translated.draw_iter(pixels.iter().copied()).unwrap();
101
102 display.assert_pattern(&[
103 " ", " ", " ", " # ", " ", " .", ]);
110 }
111
112 #[test]
113 fn fill_contiguous() {
114 let mut display = MockDisplay::new();
115
116 let mut translated = display.translated(Point::new(3, 2));
117
118 let colors = [
119 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, ];
124 let area = Rectangle::new(Point::new(1, 2), Size::new(5, 4));
125 translated
126 .fill_contiguous(&area, colors.iter().map(|c| BinaryColor::from(*c != 0)))
127 .unwrap();
128
129 display.assert_pattern(&[
130 " ", " ", " ", " ", " #####", " ....#", " .#.##", " #.#.#", ]);
139 }
140
141 #[test]
142 fn fill_solid() {
143 let mut display = MockDisplay::new();
144
145 let mut translated = display.translated(Point::new(1, 3));
146
147 let area = Rectangle::new(Point::new(2, 1), Size::new(3, 4));
148 translated.fill_solid(&area, BinaryColor::On).unwrap();
149
150 display.assert_pattern(&[
151 " ", " ", " ", " ", " ###", " ###", " ###", " ###", ]);
160 }
161
162 #[test]
163 fn clear() {
164 let mut display = MockDisplay::new();
165 let mut translated = display.translated(Point::new(1, 3));
166 translated.clear(BinaryColor::On).unwrap();
167
168 let mut expected = MockDisplay::new();
169 expected.clear(BinaryColor::On).unwrap();
170
171 display.assert_eq(&expected);
172 }
173
174 #[test]
175 fn bounding_box() {
176 let mut display: MockDisplay<BinaryColor> = MockDisplay::new();
177 let display_bb = display.bounding_box();
178
179 let translated = display.translated(Point::new(1, 3));
180
181 assert_eq!(
182 display_bb.translate(-Point::new(1, 3)),
183 translated.bounding_box()
184 );
185 }
186}