use crate::{
Buffered, ControllerInterface, DoubleBuffered, DriverError, ResetInterface, St77916,
St77916Color, Unbuffered,
};
use embedded_graphics_core::draw_target::DrawTarget;
use embedded_graphics_core::prelude::*;
use embedded_graphics_core::primitives::Rectangle;
impl<IFACE, RST, COLOR> DrawTarget for St77916<IFACE, RST, Buffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
type Color = COLOR;
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
let w = self.config.width as i32;
let h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let mut y_min: i32 = i32::MAX;
let mut y_max: i32 = 0;
for Pixel(coord, color) in pixels.into_iter() {
if coord.x >= 0 && coord.x < w && coord.y >= 0 && coord.y < h {
let offset = coord.y as usize * stride + coord.x as usize * bpp;
color.encode(&mut self.buffer.data[offset..offset + bpp]);
y_min = y_min.min(coord.y);
y_max = y_max.max(coord.y);
}
}
if y_min <= y_max {
self.buffer.dirty.mark(y_min as u16, y_max as u16);
}
Ok(())
}
#[inline]
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Self::Color>,
{
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let x0 = area.top_left.x.max(0);
let y0 = area.top_left.y.max(0);
let x1 = (area.top_left.x + area.size.width as i32).min(disp_w);
let y1 = (area.top_left.y + area.size.height as i32).min(disp_h);
if x0 >= x1 || y0 >= y1 {
return Ok(());
}
self.buffer.dirty.mark(y0 as u16, (y1 - 1) as u16);
let area_w = area.size.width as usize;
let clipped_w = (x1 - x0) as usize;
let skip_left = (x0 - area.top_left.x) as usize;
let skip_right = (area_w as i32 - (x1 - area.top_left.x)) as usize;
let skip_top = ((y0 - area.top_left.y) as usize) * area_w;
let fb = self.buffer.data.as_mut_slice();
let mut iter = colors.into_iter();
for _ in 0..skip_top {
iter.next();
}
for y in y0..y1 {
let row_start = y as usize * stride + x0 as usize * bpp;
for _ in 0..skip_left {
iter.next();
}
let row = &mut fb[row_start..row_start + clipped_w * bpp];
for (chunk, color) in row.chunks_exact_mut(bpp).zip(&mut iter) {
color.encode(chunk);
}
for _ in 0..skip_right {
iter.next();
}
}
Ok(())
}
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let x0 = area.top_left.x.max(0) as usize;
let y0 = area.top_left.y.max(0) as usize;
let x1 = (area.top_left.x + area.size.width as i32).min(disp_w) as usize;
let y1 = (area.top_left.y + area.size.height as i32).min(disp_h) as usize;
if x0 >= x1 || y0 >= y1 {
return Ok(());
}
self.buffer.dirty.mark(y0 as u16, (y1 - 1) as u16);
let row_bytes = (x1 - x0) * bpp;
let fb = self.buffer.data.as_mut_slice();
for y in y0..y1 {
let start = y * stride + x0 * bpp;
COLOR::fill_row(color, &mut fb[start..start + row_bytes]);
}
Ok(())
}
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
COLOR::fill_buf(color, &mut self.buffer.data);
self.buffer.dirty.mark_all(self.config.height);
Ok(())
}
}
impl<IFACE, RST, COLOR> OriginDimensions for St77916<IFACE, RST, Buffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
fn size(&self) -> Size {
Size::new(self.config.width as u32, self.config.height as u32)
}
}
impl<IFACE, RST, COLOR> DrawTarget for St77916<IFACE, RST, Unbuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
type Color = COLOR;
type Error = DriverError<IFACE::Error, RST::Error>;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
let w = self.config.width as i32;
let h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
for Pixel(coord, color) in pixels.into_iter() {
if coord.x >= 0 && coord.x < w && coord.y >= 0 && coord.y < h {
let x = coord.x as u16;
let y = coord.y as u16;
self.set_window(x, y, x, y)?;
let mut buf = [0u8; 4];
color.encode(&mut buf[..bpp]);
self.send_pixels(&buf[..bpp])?;
}
}
Ok(())
}
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Self::Color>,
{
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let x0 = area.top_left.x.max(0);
let y0 = area.top_left.y.max(0);
let x1 = (area.top_left.x + area.size.width as i32).min(disp_w);
let y1 = (area.top_left.y + area.size.height as i32).min(disp_h);
if x0 >= x1 || y0 >= y1 {
return Ok(());
}
let area_w = area.size.width as usize;
let clipped_w = (x1 - x0) as usize;
let skip_left = (x0 - area.top_left.x) as usize;
let skip_right = (area_w as i32 - (x1 - area.top_left.x)) as usize;
let skip_top = ((y0 - area.top_left.y) as usize) * area_w;
self.set_window(x0 as u16, y0 as u16, (x1 - 1) as u16, (y1 - 1) as u16)?;
let mut iter = colors.into_iter();
let row_bytes = clipped_w * bpp;
let mut row_buf = alloc::vec![0u8; row_bytes];
for _ in 0..skip_top {
iter.next();
}
for _y in y0..y1 {
for _ in 0..skip_left {
iter.next();
}
for chunk in row_buf.chunks_exact_mut(bpp) {
if let Some(color) = iter.next() {
color.encode(chunk);
} else {
return Ok(());
}
}
self.send_pixels(&row_buf)?;
for _ in 0..skip_right {
iter.next();
}
}
Ok(())
}
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let x0 = area.top_left.x.max(0) as u16;
let y0 = area.top_left.y.max(0) as u16;
let x1 = ((area.top_left.x + area.size.width as i32).min(disp_w) - 1) as u16;
let y1 = ((area.top_left.y + area.size.height as i32).min(disp_h) - 1) as u16;
if x0 > x1 || y0 > y1 {
return Ok(());
}
self.set_window(x0, y0, x1, y1)?;
let width = (x1 - x0 + 1) as usize;
let height = (y1 - y0 + 1) as usize;
let row_bytes = width * bpp;
let mut row_buf = alloc::vec![0u8; row_bytes];
COLOR::fill_row(color, &mut row_buf);
for _ in 0..height {
self.send_pixels(&row_buf)?;
}
Ok(())
}
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
let w = self.config.width;
let h = self.config.height;
let bpp = COLOR::BYTES_PER_PIXEL;
self.set_window(0, 0, w - 1, h - 1)?;
let row_bytes = w as usize * bpp;
let mut row_buf = alloc::vec![0u8; row_bytes];
COLOR::fill_row(color, &mut row_buf);
for _ in 0..h {
self.send_pixels(&row_buf)?;
}
Ok(())
}
}
impl<IFACE, RST, COLOR> DrawTarget for St77916<IFACE, RST, DoubleBuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
type Color = COLOR;
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
let w = self.config.width as i32;
let h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let fb = self.buffer.back_mut().as_mut_slice();
for Pixel(coord, color) in pixels.into_iter() {
if coord.x >= 0 && coord.x < w && coord.y >= 0 && coord.y < h {
let offset = coord.y as usize * stride + coord.x as usize * bpp;
color.encode(&mut fb[offset..offset + bpp]);
}
}
Ok(())
}
fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Self::Color>,
{
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let fb = self.buffer.back_mut().as_mut_slice();
let x0 = area.top_left.x.max(0) as usize;
let y0 = area.top_left.y.max(0) as usize;
let x1 = (area.top_left.x + area.size.width as i32).min(disp_w) as usize;
let y1 = (area.top_left.y + area.size.height as i32).min(disp_h) as usize;
if x0 >= x1 || y0 >= y1 {
for _ in colors {}
return Ok(());
}
let src_w = area.size.width as usize;
let mut iter = colors.into_iter();
for src_row in 0..area.size.height as usize {
let dst_row = area.top_left.y as usize + src_row;
if dst_row < y0 || dst_row >= y1 {
for _ in 0..src_w {
iter.next();
}
continue;
}
for src_col in 0..src_w {
if let Some(c) = iter.next() {
let dst_col = area.top_left.x as usize + src_col;
if dst_col >= x0 && dst_col < x1 {
let offset = dst_row * stride + dst_col * bpp;
c.encode(&mut fb[offset..offset + bpp]);
}
}
}
}
Ok(())
}
fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
let disp_w = self.config.width as i32;
let disp_h = self.config.height as i32;
let bpp = COLOR::BYTES_PER_PIXEL;
let stride = self.config.width as usize * bpp;
let x0 = area.top_left.x.max(0) as usize;
let y0 = area.top_left.y.max(0) as usize;
let x1 = (area.top_left.x + area.size.width as i32).min(disp_w) as usize;
let y1 = (area.top_left.y + area.size.height as i32).min(disp_h) as usize;
if x0 >= x1 || y0 >= y1 {
return Ok(());
}
let row_bytes = (x1 - x0) * bpp;
let fb = self.buffer.back_mut().as_mut_slice();
for y in y0..y1 {
let start = y * stride + x0 * bpp;
COLOR::fill_row(color, &mut fb[start..start + row_bytes]);
}
Ok(())
}
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
COLOR::fill_buf(color, self.buffer.back_mut().as_mut_slice());
Ok(())
}
}
impl<IFACE, RST, COLOR> OriginDimensions for St77916<IFACE, RST, DoubleBuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
fn size(&self) -> Size {
Size::new(self.config.width as u32, self.config.height as u32)
}
}
impl<IFACE, RST, COLOR> OriginDimensions for St77916<IFACE, RST, Unbuffered<COLOR>>
where
IFACE: ControllerInterface,
RST: ResetInterface,
COLOR: St77916Color,
{
fn size(&self) -> Size {
Size::new(self.config.width as u32, self.config.height as u32)
}
}