1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use embedded_graphics::{
    pixelcolor::BinaryColor,
    prelude::{Dimensions, DrawTarget},
    primitives::{ContainsPoint, Rectangle},
    Pixel,
};

pub struct ColorInvertingOverlay<'a, T, S> {
    parent: &'a mut T,
    area: S,
}

impl<T, S> Dimensions for ColorInvertingOverlay<'_, T, S>
where
    T: Dimensions,
{
    fn bounding_box(&self) -> Rectangle {
        self.parent.bounding_box()
    }
}

impl<T, S> DrawTarget for ColorInvertingOverlay<'_, T, S>
where
    T: DrawTarget<Color = BinaryColor>,
    S: ContainsPoint,
{
    type Color = BinaryColor;
    type Error = T::Error;

    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
    where
        I: IntoIterator<Item = Pixel<Self::Color>>,
    {
        self.parent
            .draw_iter(pixels.into_iter().map(|Pixel(pos, color)| {
                let color = if self.area.contains(pos) {
                    color.invert()
                } else {
                    color
                };
                Pixel(pos, color)
            }))
    }
}

pub trait BinaryColorDrawTargetExt: Sized {
    fn invert_area<S>(&mut self, area: &S) -> ColorInvertingOverlay<'_, Self, S>
    where
        S: Clone + ContainsPoint;
}

impl<T> BinaryColorDrawTargetExt for T
where
    T: DrawTarget<Color = BinaryColor>,
{
    fn invert_area<S>(&mut self, area: &S) -> ColorInvertingOverlay<'_, Self, S>
    where
        S: Clone + ContainsPoint,
    {
        ColorInvertingOverlay {
            parent: self,
            area: area.clone(),
        }
    }
}