use core::convert::Infallible;
use embedded_graphics_core::{
pixelcolor::BinaryColor,
prelude::{Dimensions, DrawTarget, OriginDimensions, Point, Size},
Pixel,
};
pub struct MonoScreenBuffer<'a> {
pixels: &'a mut [u8],
width: u16,
height: u16,
}
impl<'a> MonoScreenBuffer<'a> {
pub fn new(pixels: &'a mut [u8], width: u16, height: u16) -> Self {
Self {
pixels,
width,
height,
}
}
pub fn get(&self, x: u16, y: u16) -> BinaryColor {
let (byte_index, offset) = self.index_offset(x, y);
(((self.pixels[byte_index] >> offset) & 1) == 1).into()
}
pub fn set(&mut self, x: u16, y: u16, colour: BinaryColor) {
let (byte_index, offset) = self.index_offset(x, y);
match colour {
BinaryColor::Off => self.pixels[byte_index] &= !(1 << offset),
BinaryColor::On => self.pixels[byte_index] |= 1 << offset,
}
}
pub fn get_pixel(&mut self, x: u16, y: u16) -> Pixel<BinaryColor> {
Pixel(Point::new(x as i32, y as i32), self.get(x, y))
}
pub fn set_pixel(&mut self, pixel: Pixel<BinaryColor>) {
self.set(pixel.0.x as u16, pixel.0.y as u16, pixel.1);
}
fn index_offset(&self, x: u16, y: u16) -> (usize, u8) {
let bit_index = x * self.height + y;
let byte_index = (bit_index / 8) as usize;
let offset = (bit_index % 8) as u8;
(byte_index, offset)
}
pub fn height(&self) -> u16 {
self.height
}
pub fn width(&self) -> u16 {
self.width
}
}
impl DrawTarget for MonoScreenBuffer<'_> {
type Color = BinaryColor;
type Error = Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
let bounding_box = self.bounding_box();
for p in pixels {
if bounding_box.contains(p.0) {
self.set_pixel(p);
}
}
Ok(())
}
}
impl OriginDimensions for MonoScreenBuffer<'_> {
fn size(&self) -> Size {
Size::new(self.width as u32, self.height as u32)
}
}