use crate::primitives::{Pixel, Point, Size, geometry::Rectangle};
mod offset_surface;
pub use offset_surface::OffsetSurface;
mod clipped_surface;
pub use clipped_surface::ClippedSurface;
#[cfg(feature = "embedded-graphics")]
mod draw_target_surface;
#[cfg(feature = "embedded-graphics")]
pub use draw_target_surface::DrawTargetSurface;
pub trait Surface {
type Color: Copy;
fn size(&self) -> Size;
fn draw_iter<I>(&mut self, pixels: I)
where
I: IntoIterator<Item = Pixel<Self::Color>>;
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I)
where
I: IntoIterator<Item = Self::Color>,
{
let x_end = area.origin.x + area.size.width as i32;
let y_end = area.origin.y + area.size.height as i32;
let points = (area.origin.y..y_end)
.flat_map(move |y| (area.origin.x..x_end).map(move |x| Point::new(x, y)));
self.draw_iter(
points
.zip(colors)
.map(|(point, color)| Pixel { color, point }),
);
}
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) {
self.fill_contiguous(area, core::iter::repeat(color));
}
fn clear(&mut self, color: Self::Color) {
let bounding_box = Rectangle::new(Point::zero(), self.size());
self.fill_solid(&bounding_box, color);
}
}
#[cfg(feature = "embedded-graphics")]
#[derive(Debug)]
pub struct EmbeddedGraphicsSurface<T>(pub T);
#[cfg(feature = "embedded-graphics")]
pub trait AsDrawTarget: Surface {
fn draw_target(
&mut self,
) -> impl embedded_graphics::prelude::DrawTarget<Color = Self::Color, Error = ()> + '_;
}
#[cfg(feature = "embedded-graphics")]
impl<T: Surface<Color = P>, P: embedded_graphics::prelude::PixelColor> AsDrawTarget for T {
fn draw_target(
&mut self,
) -> impl embedded_graphics::draw_target::DrawTarget<Color = <Self as Surface>::Color, Error = ()> + '_
{
EmbeddedGraphicsSurface(self)
}
}
#[cfg(feature = "embedded-graphics")]
impl<T: Surface> embedded_graphics::prelude::Dimensions for EmbeddedGraphicsSurface<&mut T> {
fn bounding_box(&self) -> embedded_graphics::primitives::Rectangle {
embedded_graphics::primitives::Rectangle::new(
embedded_graphics::prelude::Point::zero(),
self.0.size().into(),
)
}
}
#[cfg(feature = "embedded-graphics")]
impl<T: Surface> embedded_graphics::prelude::DrawTarget for EmbeddedGraphicsSurface<&mut T>
where
T::Color: embedded_graphics::prelude::PixelColor,
{
type Color = T::Color;
type Error = ();
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
{
self.0.draw_iter(pixels.into_iter().map(|p| Pixel {
point: p.0.into(),
color: p.1,
}));
Ok(())
}
fn fill_contiguous<I>(
&mut self,
area: &embedded_graphics::primitives::Rectangle,
colors: I,
) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Self::Color>,
{
self.0.fill_contiguous(&(*area).into(), colors);
Ok(())
}
fn fill_solid(
&mut self,
area: &embedded_graphics::primitives::Rectangle,
color: Self::Color,
) -> Result<(), Self::Error> {
let area: Rectangle = (*area).into();
self.0.fill_solid(&area, color);
Ok(())
}
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
self.0.clear(color);
Ok(())
}
}
impl<T: Surface> Surface for &mut T {
type Color = T::Color;
fn size(&self) -> Size {
(**self).size()
}
fn draw_iter<I>(&mut self, pixels: I)
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
(**self).draw_iter(pixels);
}
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I)
where
I: IntoIterator<Item = Self::Color>,
{
(**self).fill_contiguous(area, colors);
}
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) {
(**self).fill_solid(area, color);
}
fn clear(&mut self, color: Self::Color) {
(**self).clear(color);
}
}