Newer
Older
// Uses too much RAM to be useful ):
// 320 * 240 * 2 * 2 bytes/pixel = 307KB of RAM
use embedded_graphics::{
draw_target::DrawTarget, geometry::Dimensions, pixelcolor::PixelColor, Pixel,
};
pub struct BufferedDisplay<const L: usize, C: 'static, E, DT: DrawTarget<Color = C, Error = E>> {
target: DT,
width: usize,
height: usize,
cur: &'static mut [C; L],
}
impl<const L: usize, C: PixelColor, E, DT: DrawTarget<Color = C, Error = E>>
BufferedDisplay<L, C, E, DT>
{
pub fn new(mut target: DT, color: C, cur: &'static mut [C; L]) -> Result<Self, E> {
let size = target.bounding_box().size;
let width = size.width.try_into().unwrap();
let height = size.height.try_into().unwrap();
assert_eq!(L, width * height);
target.fill_solid(&target.bounding_box(), color)?;
Ok(Self {
target,
width,
height,
cur,
})
}
}
impl<const L: usize, C: PixelColor, E, DT: DrawTarget<Color = C, Error = E>> Dimensions
for BufferedDisplay<L, C, E, DT>
{
fn bounding_box(&self) -> embedded_graphics::primitives::Rectangle {
self.target.bounding_box()
}
}
impl<const L: usize, C: PixelColor, E, DT: DrawTarget<Color = C, Error = E>> DrawTarget
for BufferedDisplay<L, C, E, DT>
{
type Color = C;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = embedded_graphics::prelude::Pixel<Self::Color>>,
{
self.target
.draw_iter(pixels.into_iter().filter(|Pixel(p, c)| {
if let Some(idx) = index(self.width, self.height, p.x, p.y) {
if self.cur[idx] != *c {
self.cur[idx] = *c;
return true;
}
}
false
}))
#[inline(always)]
fn index<X: TryInto<usize>, Y: TryInto<usize>>(
x: X,
y: Y,
) -> Option<usize> {
let x: usize = x.try_into().ok()?;
let y: usize = y.try_into().ok()?;
if y >= height || x >= width {
return None;