use core::fmt::Debug;
use core::marker::PhantomData;
use embedded_graphics_core::{
Drawable, Pixel,
draw_target::DrawTarget,
geometry::{Dimensions, Point},
pixelcolor::{PixelColor, Rgb565},
primitives::Rectangle,
};
use embedded_graphics_framebuf::{FrameBuf, backends::FrameBufferBackend};
use crate::DrawPrimitive;
#[cfg(feature = "aa")]
use crate::draw::ReadPixel;
use crate::draw::draw;
#[cfg(feature = "aa")]
use embedded_graphics_core::pixelcolor::RgbColor;
pub struct ColorAdapter<'a, C, D> {
inner: &'a mut D,
_phantom: PhantomData<C>,
}
impl<C, D> Dimensions for ColorAdapter<'_, C, D>
where
C: PixelColor,
D: DrawTarget<Color = C>,
{
fn bounding_box(&self) -> Rectangle {
self.inner.bounding_box()
}
}
impl<C, D> DrawTarget for ColorAdapter<'_, C, D>
where
C: PixelColor + From<Rgb565>,
D: DrawTarget<Color = C>,
{
type Color = Rgb565;
type Error = D::Error;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Rgb565>>,
{
self.inner.draw_iter(
pixels
.into_iter()
.map(|Pixel(pos, color)| Pixel(pos, C::from(color))),
)
}
}
pub fn draw_to<C, D>(primitive: DrawPrimitive, fb: &mut D)
where
C: PixelColor + From<Rgb565>,
D: DrawTarget<Color = C>,
D::Error: Debug,
{
let mut adapter = ColorAdapter {
inner: fb,
_phantom: PhantomData,
};
draw(primitive, &mut adapter);
}
#[inline]
pub fn nalgebra_to_eg(p: nalgebra::Point2<i32>) -> Point {
Point::new(p.x, p.y)
}
#[inline]
pub fn eg_to_nalgebra(p: Point) -> nalgebra::Point2<i32> {
nalgebra::Point2::new(p.x, p.y)
}
pub trait AsEgPoint {
fn as_eg_point(&self) -> Point;
}
impl AsEgPoint for nalgebra::Point2<i32> {
#[inline]
fn as_eg_point(&self) -> Point {
Point::new(self.x, self.y)
}
}
pub trait AsNalgebraPoint {
fn as_nalgebra(&self) -> nalgebra::Point2<i32>;
}
impl AsNalgebraPoint for Point {
#[inline]
fn as_nalgebra(&self) -> nalgebra::Point2<i32> {
nalgebra::Point2::new(self.x, self.y)
}
}
#[cfg(feature = "aa")]
impl<B> ReadPixel for FrameBuf<Rgb565, B>
where
B: FrameBufferBackend<Color = Rgb565>,
{
fn read_pixel(&self, point: Point) -> Rgb565 {
let w = self.width() as i32;
let h = self.height() as i32;
if point.x < 0 || point.x >= w || point.y < 0 || point.y >= h {
return <Rgb565 as RgbColor>::BLACK;
}
self.get_color_at(point)
}
}
struct SliceBackend<'a>(pub &'a mut [Rgb565]);
impl FrameBufferBackend for SliceBackend<'_> {
type Color = Rgb565;
fn set(&mut self, index: usize, color: Rgb565) {
self.0[index] = color;
}
fn get(&self, index: usize) -> Rgb565 {
self.0[index]
}
fn nr_elements(&self) -> usize {
self.0.len()
}
}
pub fn render_drawable_to_buffer<D>(
drawable: &D,
buffer: &mut [Rgb565],
width: usize,
height: usize,
) -> Result<(), ()>
where
D: Drawable<Color = Rgb565>,
{
if buffer.len() != width * height {
return Err(());
}
let mut fb = FrameBuf::new(SliceBackend(buffer), width, height);
drawable.draw(&mut fb).map(|_| ()).map_err(|_| ())
}