|
|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
//! Graphics Support for EPDs
|
|
|
|
|
|
|
|
|
|
use crate::color::Color; |
|
|
|
|
use embedded_graphics::prelude::*; |
|
|
|
|
use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; |
|
|
|
|
|
|
|
|
|
/// Displayrotation
|
|
|
|
|
#[derive(Clone, Copy)] |
|
|
|
|
@ -22,7 +22,7 @@ impl Default for DisplayRotation {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub trait Display: Drawing<Color> { |
|
|
|
|
pub trait Display: DrawTarget<BinaryColor> { |
|
|
|
|
/// Clears the buffer of the display with the chosen background color
|
|
|
|
|
fn clear_buffer(&mut self, background_color: Color) { |
|
|
|
|
for elem in self.get_mut_buffer().iter_mut() { |
|
|
|
|
@ -45,31 +45,36 @@ pub trait Display: Drawing<Color> {
|
|
|
|
|
/// Helperfunction for the Embedded Graphics draw trait
|
|
|
|
|
///
|
|
|
|
|
/// Becomes uneccesary when const_generics become stablised
|
|
|
|
|
fn draw_helper<T>(&mut self, width: u32, height: u32, item_pixels: T) |
|
|
|
|
where |
|
|
|
|
T: IntoIterator<Item = Pixel<Color>>, |
|
|
|
|
{ |
|
|
|
|
fn draw_helper( |
|
|
|
|
&mut self, |
|
|
|
|
width: u32, |
|
|
|
|
height: u32, |
|
|
|
|
pixel: Pixel<BinaryColor>, |
|
|
|
|
) -> Result<(), Self::Error> { |
|
|
|
|
let rotation = self.rotation(); |
|
|
|
|
let buffer = self.get_mut_buffer(); |
|
|
|
|
for Pixel(UnsignedCoord(x, y), color) in item_pixels { |
|
|
|
|
if outside_display(x, y, width, height, rotation) { |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
let Pixel(point, color) = pixel; |
|
|
|
|
if outside_display(point, width, height, rotation) { |
|
|
|
|
return Ok(()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Give us index inside the buffer and the bit-position in that u8 which needs to be changed
|
|
|
|
|
let (index, bit) = find_position(x, y, width, height, rotation); |
|
|
|
|
let (index, bit) = find_position(point.x as u32, point.y as u32, width, height, rotation); |
|
|
|
|
let index = index as usize; |
|
|
|
|
|
|
|
|
|
// "Draw" the Pixel on that bit
|
|
|
|
|
match color { |
|
|
|
|
Color::Black => { |
|
|
|
|
// Black
|
|
|
|
|
BinaryColor::On => { |
|
|
|
|
buffer[index] &= !bit; |
|
|
|
|
} |
|
|
|
|
Color::White => { |
|
|
|
|
// White
|
|
|
|
|
BinaryColor::Off => { |
|
|
|
|
buffer[index] |= bit; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -83,8 +88,10 @@ pub trait Display: Drawing<Color> {
|
|
|
|
|
/// # use epd_waveshare::epd2in9::DEFAULT_BACKGROUND_COLOR;
|
|
|
|
|
/// # use epd_waveshare::prelude::*;
|
|
|
|
|
/// # use epd_waveshare::graphics::VarDisplay;
|
|
|
|
|
/// # use epd_waveshare::color::Black;
|
|
|
|
|
/// # use embedded_graphics::prelude::*;
|
|
|
|
|
/// # use embedded_graphics::primitives::{Circle, Line};
|
|
|
|
|
/// # use embedded_graphics::style::PrimitiveStyle;
|
|
|
|
|
/// let width = 128;
|
|
|
|
|
/// let height = 296;
|
|
|
|
|
///
|
|
|
|
|
@ -93,11 +100,9 @@ pub trait Display: Drawing<Color> {
|
|
|
|
|
///
|
|
|
|
|
/// display.set_rotation(DisplayRotation::Rotate90);
|
|
|
|
|
///
|
|
|
|
|
/// display.draw(
|
|
|
|
|
/// Line::new(Coord::new(0, 120), Coord::new(0, 295))
|
|
|
|
|
/// .stroke(Some(Color::Black))
|
|
|
|
|
/// .into_iter(),
|
|
|
|
|
/// );
|
|
|
|
|
/// let _ = Line::new(Point::new(0, 120), Point::new(0, 295))
|
|
|
|
|
/// .into_styled(PrimitiveStyle::with_stroke(Black, 1))
|
|
|
|
|
/// .draw(&mut display);
|
|
|
|
|
/// ```
|
|
|
|
|
pub struct VarDisplay<'a> { |
|
|
|
|
width: u32, |
|
|
|
|
@ -119,12 +124,15 @@ impl<'a> VarDisplay<'a> {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'a> Drawing<Color> for VarDisplay<'a> { |
|
|
|
|
fn draw<T>(&mut self, item_pixels: T) |
|
|
|
|
where |
|
|
|
|
T: IntoIterator<Item = Pixel<Color>>, |
|
|
|
|
{ |
|
|
|
|
self.draw_helper(self.width, self.height, item_pixels); |
|
|
|
|
impl<'a> DrawTarget<BinaryColor> for VarDisplay<'a> { |
|
|
|
|
type Error = core::convert::Infallible; |
|
|
|
|
|
|
|
|
|
fn draw_pixel(&mut self, pixel: Pixel<BinaryColor>) -> Result<(), Self::Error> { |
|
|
|
|
self.draw_helper(self.width, self.height, pixel) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn size(&self) -> Size { |
|
|
|
|
Size::new(self.width, self.height) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -147,7 +155,11 @@ impl<'a> Display for VarDisplay<'a> {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Checks if a pos is outside the defined display
|
|
|
|
|
fn outside_display(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> bool { |
|
|
|
|
fn outside_display(p: Point, width: u32, height: u32, rotation: DisplayRotation) -> bool { |
|
|
|
|
if p.x < 0 || p.y < 0 { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
let (x, y) = (p.x as u32, p.y as u32); |
|
|
|
|
match rotation { |
|
|
|
|
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => { |
|
|
|
|
if x >= width || y >= height { |
|
|
|
|
@ -189,10 +201,9 @@ fn find_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotat
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
mod tests { |
|
|
|
|
use super::{find_position, outside_display, Display, DisplayRotation, VarDisplay}; |
|
|
|
|
use crate::color::Black; |
|
|
|
|
use crate::color::Color; |
|
|
|
|
use embedded_graphics::coord::Coord; |
|
|
|
|
use embedded_graphics::prelude::*; |
|
|
|
|
use embedded_graphics::primitives::Line; |
|
|
|
|
use embedded_graphics::{prelude::*, primitives::Line, style::PrimitiveStyle}; |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn buffer_clear() { |
|
|
|
|
@ -228,7 +239,7 @@ mod tests {
|
|
|
|
|
for x in 0..(width + height) { |
|
|
|
|
//limit x because it runs too long
|
|
|
|
|
for y in 0..(u32::max_value()) { |
|
|
|
|
if outside_display(x, y, width, height, rotation2) { |
|
|
|
|
if outside_display(Point::new(x as i32, y as i32), width, height, rotation2) { |
|
|
|
|
break; |
|
|
|
|
} else { |
|
|
|
|
let (idx, _) = find_position(x, y, width, height, rotation2); |
|
|
|
|
@ -247,11 +258,9 @@ mod tests {
|
|
|
|
|
let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 128 / 8 * 296]; |
|
|
|
|
let mut display = VarDisplay::new(width, height, &mut buffer); |
|
|
|
|
|
|
|
|
|
display.draw( |
|
|
|
|
Line::new(Coord::new(0, 0), Coord::new(7, 0)) |
|
|
|
|
.stroke(Some(Color::Black)) |
|
|
|
|
.into_iter(), |
|
|
|
|
); |
|
|
|
|
let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) |
|
|
|
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) |
|
|
|
|
.draw(&mut display); |
|
|
|
|
|
|
|
|
|
let buffer = display.buffer(); |
|
|
|
|
|
|
|
|
|
@ -273,11 +282,9 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
display.set_rotation(DisplayRotation::Rotate90); |
|
|
|
|
|
|
|
|
|
display.draw( |
|
|
|
|
Line::new(Coord::new(0, 120), Coord::new(0, 295)) |
|
|
|
|
.stroke(Some(Color::Black)) |
|
|
|
|
.into_iter(), |
|
|
|
|
); |
|
|
|
|
let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) |
|
|
|
|
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) |
|
|
|
|
.draw(&mut display); |
|
|
|
|
|
|
|
|
|
let buffer = display.buffer(); |
|
|
|
|
|
|
|
|
|
|