embedded_graphics/drawable.rs
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//! `Drawable` trait and helpers
use crate::{geometry::Point, pixelcolor::PixelColor, DrawTarget};
/// Marks an object as "drawable". Must be implemented for all graphics objects
///
/// The `Drawable` trait describes how a particular graphical object is drawn. A `Drawable` object
/// can define its `draw` method as a collection of graphical primitives or as an iterator
/// over pixels being rendered with [`DrawTarget`]'s [`draw_iter`] method.
///
/// ```rust
/// use embedded_graphics::{
/// egrectangle, egtext,
/// fonts::Font6x8,
/// geometry::Point,
/// pixelcolor::{BinaryColor, PixelColor, Rgb888},
/// prelude::*,
/// primitive_style, text_style,
/// };
///
/// struct Button<'a, C: PixelColor> {
/// top_left: Point,
/// bottom_right: Point,
/// bg_color: C,
/// fg_color: C,
/// text: &'a str,
/// }
///
/// impl<'a, C: 'a> Drawable<C> for &Button<'a, C>
/// where
/// C: PixelColor + From<BinaryColor>,
/// {
/// fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
/// egrectangle!(
/// top_left = self.top_left,
/// bottom_right = self.bottom_right,
/// style = primitive_style!(fill_color = self.bg_color)
/// )
/// .draw(display);
/// egtext!(
/// text = self.text,
/// top_left = (20, 20),
/// style = text_style!(font = Font6x8, text_color = self.fg_color)
/// )
/// .draw(display)
/// }
/// }
///
/// let mut button = Button {
/// top_left: Point::zero(),
/// bottom_right: Point::new(100, 50),
/// bg_color: Rgb888::RED,
/// fg_color: Rgb888::BLUE,
/// text: "Click me!",
/// };
///
/// # use embedded_graphics::mock_display::MockDisplay;
/// # let mut display = MockDisplay::default();
/// button.draw(&mut display)?;
/// # Ok::<(), core::convert::Infallible>(())
/// ```
///
/// [`DrawTarget`]: ../trait.DrawTarget.html
/// [`draw_iter`]: ../trait.DrawTarget.html#method.draw_iter
pub trait Drawable<C>
where
C: PixelColor,
{
/// Draw the graphics object using the supplied DrawTarget.
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error>;
}
/// A single pixel.
///
/// `Pixel` objects are used to specify the position and color of drawn pixels.
///
/// # Examples
///
/// The [`Drawable`] trait is implemented for `Pixel` which allows single pixels
/// to be drawn to a [`DrawTarget`]:
/// ```
/// use embedded_graphics::{pixelcolor::BinaryColor, prelude::*};
/// # use embedded_graphics::mock_display::MockDisplay;
/// # let mut display = MockDisplay::new();
///
/// Pixel(Point::new(1, 2), BinaryColor::On).draw(&mut display)?;
/// # Ok::<(), core::convert::Infallible>(())
/// ```
///
/// Iterators with `Pixel` items can also be drawn:
///
/// ```
/// use embedded_graphics::{pixelcolor::BinaryColor, prelude::*};
/// # use embedded_graphics::mock_display::MockDisplay;
/// # let mut display = MockDisplay::new();
///
/// (0..100)
/// .map(|i| Pixel(Point::new(i, i * 2), BinaryColor::On))
/// .draw(&mut display)?;
/// # Ok::<(), core::convert::Infallible>(())
/// ```
///
/// [`Drawable`]: trait.Drawable.html
/// [`DrawTarget`]: ../trait.DrawTarget.html
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct Pixel<C: PixelColor>(pub Point, pub C);
impl<C> Drawable<C> for Pixel<C>
where
C: PixelColor,
{
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
display.draw_pixel(self)
}
}
impl<C, T> Drawable<C> for &mut T
where
C: PixelColor,
T: Iterator<Item = Pixel<C>>,
{
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
display.draw_iter(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{mock_display::MockDisplay, pixelcolor::BinaryColor};
#[test]
fn draw_pixel() -> Result<(), core::convert::Infallible> {
let mut display = MockDisplay::new();
Pixel(Point::new(0, 0), BinaryColor::On).draw(&mut display)?;
Pixel(Point::new(2, 1), BinaryColor::On).draw(&mut display)?;
Pixel(Point::new(1, 2), BinaryColor::On).draw(&mut display)?;
#[rustfmt::skip]
assert_eq!(
MockDisplay::from_pattern(&[
"# ",
" #",
" # ",
]),
display
);
Ok(())
}
}