#![cfg_attr(not(test), no_std)]
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
use embedded_graphics_core::prelude::{DrawTarget, Point};
use embedded_graphics_core::primitives::Rectangle;
#[cfg(feature = "completion")]
pub mod completion;
pub trait PixelRead: DrawTarget {
fn get_pixel(&self, point: Point) -> Self::Color;
}
pub trait WindowedDrawTarget: DrawTarget {
fn set_window(&mut self, area: &Rectangle) -> Result<(), Self::Error>;
}
pub trait DirtyTracking: DrawTarget {
fn dirty_area(&self) -> Option<Rectangle>;
fn clear_dirty(&mut self);
fn mark_all_dirty(&mut self);
}
#[cfg(feature = "framebuf")]
mod framebuf {
use super::PixelRead;
use embedded_graphics_core::prelude::{PixelColor, Point};
use embedded_graphics_framebuf::{FrameBuf, backends::FrameBufferBackend};
impl<C, B> PixelRead for FrameBuf<C, B>
where
C: PixelColor + Default,
B: FrameBufferBackend<Color = C>,
{
#[inline]
fn get_pixel(&self, point: Point) -> C {
if point.x < 0
|| point.y < 0
|| point.x >= self.width() as i32
|| point.y >= self.height() as i32
{
return C::default();
}
self.get_color_at(point)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use embedded_graphics::pixelcolor::Rgb565;
use embedded_graphics::prelude::*;
use embedded_graphics::primitives::{PrimitiveStyle, Rectangle as EgRectangle};
use embedded_graphics_framebuf::FrameBuf;
#[test]
fn framebuf_reads_back_what_embedded_graphics_drew() {
let mut data = [Rgb565::BLACK; 8 * 4];
let mut fb = FrameBuf::new(&mut data, 8, 4);
EgRectangle::new(Point::new(2, 1), Size::new(3, 2))
.into_styled(PrimitiveStyle::with_fill(Rgb565::RED))
.draw(&mut fb)
.unwrap();
assert_eq!(fb.get_pixel(Point::new(2, 1)), Rgb565::RED);
assert_eq!(fb.get_pixel(Point::new(4, 2)), Rgb565::RED);
assert_eq!(fb.get_pixel(Point::new(5, 2)), Rgb565::BLACK);
}
#[test]
fn out_of_bounds_reads_are_neutral_not_panics() {
let mut data = [Rgb565::WHITE; 4 * 4];
let fb = FrameBuf::new(&mut data, 4, 4);
for p in [
Point::new(-1, 0),
Point::new(0, -1),
Point::new(4, 0),
Point::new(0, 4),
Point::new(i32::MIN, i32::MAX),
] {
assert_eq!(fb.get_pixel(p), Rgb565::BLACK);
}
}
fn darken<T: PixelRead<Color = Rgb565>>(target: &mut T, at: Point) -> Result<(), T::Error> {
let c = target.get_pixel(at);
let half = Rgb565::new(c.r() / 2, c.g() / 2, c.b() / 2);
target.draw_iter(core::iter::once(Pixel(at, half)))
}
#[test]
fn generic_readback_consumer_works_on_framebuf() {
let mut data = [Rgb565::WHITE; 2 * 2];
let mut fb = FrameBuf::new(&mut data, 2, 2);
darken(&mut fb, Point::new(1, 1)).unwrap();
assert_eq!(fb.get_pixel(Point::new(0, 0)), Rgb565::WHITE);
assert_eq!(
fb.get_pixel(Point::new(1, 1)),
Rgb565::new(Rgb565::MAX_R / 2, Rgb565::MAX_G / 2, Rgb565::MAX_B / 2)
);
}
}