diff --git a/Cargo.toml b/Cargo.toml index f03bffd..569913d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,13 @@ embedded-hal = "0.2.4" optional = true version = "0.6.2" +[dependencies.embedded-graphics-core] +optional = true +version = "0.3" + + [features] default = ["graphics"] graphics = ["embedded-graphics"] +graphics-core = ["embedded-graphics-core"] + diff --git a/src/graphics.rs b/src/graphics.rs index 5aa5b85..5b77566 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -31,7 +31,7 @@ where return Ok(()); } - self.draw_raw( + self.draw_raw_slice( pos.x as u16, pos.y as u16, pos.x as u16, @@ -64,7 +64,7 @@ where let y0 = clamp(y0, h - 1); let x1 = clamp(x1, w - 1); let y1 = clamp(y1, h - 1); - self.draw_iter( + self.draw_raw_iter( x0, y0, x1, @@ -81,7 +81,7 @@ where fn clear(&mut self, color: Rgb565) -> Result<(), Self::Error> { let color = RawU16::from(color).into_inner(); - self.draw_iter( + self.draw_raw_iter( 0, 0, (self.width - 1) as u16, diff --git a/src/graphics_core.rs b/src/graphics_core.rs new file mode 100644 index 0000000..fcd2e55 --- /dev/null +++ b/src/graphics_core.rs @@ -0,0 +1,85 @@ +use crate::Ili9341; + +use embedded_graphics_core::{ + pixelcolor::{raw::RawU16, Rgb565}, + prelude::*, + primitives::Rectangle, +}; + +impl OriginDimensions for Ili9341 { + fn size(&self) -> Size { + Size::new(self.width() as u32, self.height() as u32) + } +} + +impl DrawTarget for Ili9341 +where + IFACE: display_interface::WriteOnlyDataCommand, +{ + type Error = display_interface::DisplayError; + + type Color = Rgb565; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for Pixel(point, color) in pixels { + if self.bounding_box().contains(point) { + let x = point.x as u16; + let y = point.y as u16; + + self.draw_raw_iter( + x, + y, + x, + y, + core::iter::once(RawU16::from(color).into_inner()), + )?; + } + } + Ok(()) + } + + fn fill_contiguous(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error> + where + I: IntoIterator, + { + let drawable_area = area.intersection(&self.bounding_box()); + + if let Some(drawable_bottom_right) = drawable_area.bottom_right() { + let x0 = drawable_area.top_left.x as u16; + let y0 = drawable_area.top_left.y as u16; + let x1 = drawable_bottom_right.x as u16; + let y1 = drawable_bottom_right.y as u16; + + if area == &drawable_area { + // All pixels are on screen + self.draw_raw_iter( + x0, + y0, + x1, + y1, + area.points() + .zip(colors) + .map(|(_, color)| RawU16::from(color).into_inner()), + ) + } else { + // Some pixels are on screen + self.draw_raw_iter( + x0, + y0, + x1, + y1, + area.points() + .zip(colors) + .filter(|(point, _)| drawable_area.contains(*point)) + .map(|(_, color)| RawU16::from(color).into_inner()), + ) + } + } else { + // No pixels are on screen + Ok(()) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index b54f2a5..1a11f0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,5 @@ #![no_std] -#[cfg(feature = "graphics")] -extern crate embedded_graphics; - use embedded_hal::blocking::delay::DelayMs; use embedded_hal::digital::v2::OutputPin; @@ -10,6 +7,12 @@ use core::iter::once; use display_interface::DataFormat::{U16BEIter, U8Iter}; use display_interface::WriteOnlyDataCommand; +#[cfg(feature = "graphics")] +mod graphics; + +#[cfg(feature = "graphics-core")] +mod graphics_core; + pub use embedded_hal::spi::MODE_0 as SPI_MODE; pub use display_interface::DisplayError; @@ -49,8 +52,7 @@ pub enum Orientation { } /// There are two method for drawing to the screen: -/// [draw_raw](struct.Ili9341.html#method.draw_raw) and -/// [draw_iter](struct.Ili9341.html#method.draw_iter). +/// [Ili9341::draw_raw_iter] and [Ili9341::draw_raw_slice] /// /// In both cases the expected pixel format is rgb565. /// @@ -219,7 +221,7 @@ where /// /// The iterator is useful to avoid wasting memory by holding a buffer for /// the whole screen when it is not necessary. - pub fn draw_iter>( + pub fn draw_raw_iter>( &mut self, x0: u16, y0: u16, @@ -240,9 +242,8 @@ where /// video memory. /// /// The expected format is rgb565. - pub fn draw_raw(&mut self, x0: u16, y0: u16, x1: u16, y1: u16, data: &[u16]) -> Result { - self.set_window(x0, y0, x1, y1)?; - self.write_iter(data.iter().cloned()) + pub fn draw_raw_slice(&mut self, x0: u16, y0: u16, x1: u16, y1: u16, data: &[u16]) -> Result { + self.draw_raw_iter(x0, y0, x1, y1, data.iter().copied()) } /// Change the orientation of the screen @@ -309,9 +310,6 @@ impl Scroller { } } -#[cfg(feature = "graphics")] -mod graphics; - #[derive(Clone, Copy)] enum Command { SoftwareReset = 0x01,