Skip to main content

multi_mono_font/
mono_image.rs

1use crate::draw_target::MultiMonoFontDrawTarget;
2use embedded_graphics::{
3    Drawable,
4    geometry::{OriginDimensions, Point},
5    image::{Image, ImageDrawable, ImageRaw},
6    pixelcolor::BinaryColor,
7    prelude::{DrawTarget, PixelColor, Size},
8    primitives::{Primitive, PrimitiveStyle, Rectangle},
9};
10
11/// A static binary image drawable.
12///
13/// The image is drawn with the foreground color where the pixel is set to `BinaryColor::On`,
14/// and with the background color where the pixel is set to `BinaryColor::Off`.
15#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
16#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
17pub struct MonoImage<'a, C> {
18    image: &'a ImageRaw<'a, BinaryColor>,
19    foreground_color: C,
20    background_color: Option<C>,
21}
22
23impl<'a, C> MonoImage<'a, C> {
24    /// Creates a text drawable with foreground color.
25    pub const fn new(image: &'a ImageRaw<'a, BinaryColor>, foreground_color: C) -> Self {
26        Self {
27            image,
28            foreground_color,
29            background_color: None,
30        }
31    }
32
33    /// Creates a text drawable with foreground color and background color.
34    pub const fn new_with_background_color(
35        image: &'a ImageRaw<'a, BinaryColor>,
36        foreground_color: C,
37        background_color: C,
38    ) -> Self {
39        Self {
40            image,
41            foreground_color,
42            background_color: Some(background_color),
43        }
44    }
45
46    /// Sets the background color.
47    pub fn with_background_color(mut self, background_color: C) -> Self {
48        self.background_color = Some(background_color);
49        self
50    }
51
52    /// Clears the background color.
53    pub fn clear_background_color(&mut self) {
54        self.background_color = None;
55    }
56}
57
58impl<C> OriginDimensions for MonoImage<'_, C>
59where
60    C: PixelColor + From<<C as PixelColor>::Raw>,
61{
62    fn size(&self) -> Size {
63        self.image.size()
64    }
65}
66
67impl<'a, C> ImageDrawable for MonoImage<'a, C>
68where
69    C: PixelColor + From<<C as PixelColor>::Raw>,
70{
71    type Color = C;
72
73    fn draw<D>(&self, target: &mut D) -> Result<(), D::Error>
74    where
75        D: DrawTarget<Color = C>,
76    {
77        let mut bin_target =
78            MultiMonoFontDrawTarget::new(target, self.foreground_color, self.background_color);
79
80        self.image.draw(&mut bin_target)
81    }
82
83    fn draw_sub_image<D>(&self, target: &mut D, area: &Rectangle) -> Result<(), D::Error>
84    where
85        D: DrawTarget<Color = Self::Color>,
86    {
87        let mut bin_target =
88            MultiMonoFontDrawTarget::new(target, self.foreground_color, self.background_color);
89
90        self.image.draw_sub_image(&mut bin_target, area)
91    }
92}
93
94/// A static binary run-length encoded font drawable.
95///
96/// The image is drawn with the foreground color where the pixel is set to `BinaryColor::On`,
97/// and with the background color where the pixel is set to `BinaryColor::Off`.
98#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
99#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
100pub struct MonoRleImage<C> {
101    glyph: &'static [u8],
102    x: i16,
103    y: i16,
104    width: u16,
105    height: u16,
106    foreground_color: C,
107    background_color: Option<C>,
108}
109
110impl<C> MonoRleImage<C> {
111    /// Creates a text drawable with foreground color.
112    pub const fn new(glyph: &'static [u8], width: u16, height: u16, foreground_color: C) -> Self {
113        Self {
114            glyph,
115            x: 0,
116            y: 0,
117            width,
118            height,
119            foreground_color,
120            background_color: None,
121        }
122    }
123
124    /// Creates a text drawable with foreground color and background color.
125    pub const fn new_with_background_color(
126        glyph: &'static [u8],
127        width: u16,
128        height: u16,
129        foreground_color: C,
130        background_color: C,
131    ) -> Self {
132        Self {
133            glyph,
134            x: 0,
135            y: 0,
136            width,
137            height,
138            foreground_color,
139            background_color: Some(background_color),
140        }
141    }
142
143    pub const fn with_offset(mut self, x: i16, y: i16) -> Self {
144        self.x = x;
145        self.y = y;
146        self
147    }
148
149    /// Sets the background color.
150    pub fn with_background_color(mut self, background_color: C) -> Self {
151        self.background_color = Some(background_color);
152        self
153    }
154
155    /// Clears the background color.
156    pub fn clear_background_color(&mut self) {
157        self.background_color = None;
158    }
159
160    pub fn rectangle(&self) -> Rectangle {
161        Rectangle::new(
162            Point::new(self.x as i32, self.y as i32),
163            Size::new(self.width as u32, self.height as u32),
164        )
165    }
166}
167
168impl<C> OriginDimensions for MonoRleImage<C>
169where
170    C: PixelColor + From<<C as PixelColor>::Raw>,
171{
172    fn size(&self) -> Size {
173        Size::new(self.width as u32, self.height as u32)
174    }
175}
176
177impl<C> ImageDrawable for MonoRleImage<C>
178where
179    C: PixelColor + From<<C as PixelColor>::Raw>,
180{
181    type Color = C;
182
183    fn draw<D>(&self, target: &mut D) -> Result<(), D::Error>
184    where
185        D: DrawTarget<Color = C>,
186    {
187        let mut target =
188            MultiMonoFontDrawTarget::new(target, self.foreground_color, self.background_color);
189
190        let glyph_rder = crate::glyph_reader::GlyphReader::new(self.glyph);
191        crate::glyph_reader::render_glyph_as_box_fill(&self.rectangle(), glyph_rder, &mut target)
192    }
193
194    fn draw_sub_image<D>(&self, target: &mut D, area: &Rectangle) -> Result<(), D::Error>
195    where
196        D: DrawTarget<Color = Self::Color>,
197    {
198        let mut target =
199            MultiMonoFontDrawTarget::new(target, self.foreground_color, self.background_color);
200
201        let glyph_rder = crate::glyph_reader::GlyphReader::new(self.glyph);
202        crate::glyph_reader::render_glyph_as_box_fill(area, glyph_rder, &mut target)
203    }
204}
205
206/// A stack of images.
207///
208/// The images are drawn in the stack in the order they are in the vector.
209pub struct MonoImageStack<'a, T: ImageDrawable> {
210    images: &'a [&'a T],
211    position: Point,
212    size: Size,
213    background_color: Option<T::Color>,
214}
215
216impl<'a, T: ImageDrawable> MonoImageStack<'a, T> {
217    pub const fn new(images: &'a [&'a T], position: Point) -> Self {
218        Self {
219            images,
220            position,
221            size: Size::zero(),
222            background_color: None,
223        }
224    }
225
226    pub const fn new_with_background_color(
227        images: &'a [&'a T],
228        area: Rectangle,
229        background_color: T::Color,
230    ) -> Self {
231        Self {
232            images,
233            position: area.top_left,
234            size: area.size,
235            background_color: Some(background_color),
236        }
237    }
238
239    pub fn draw<D: DrawTarget<Color = T::Color>>(&self, target: &mut D) -> Result<(), D::Error> {
240        if let Some(bg_color) = self.background_color {
241            let area = Rectangle::new(self.position, self.size);
242            area.into_styled(PrimitiveStyle::with_fill(bg_color))
243                .draw(target)?;
244        }
245        for image in self.images {
246            Image::new(*image, self.position).draw(target)?
247        }
248
249        Ok(())
250    }
251}