use embedded_graphics_core::{
geometry::{Point, Size},
primitives::Rectangle,
};
use super::PixelMap;
use crate::cmd::base::{ColumnAddressSet, RowAddressSet};
const BAND: u32 = 12;
const PAIR: u32 = 2;
const BAND_BYTES: usize = 3;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Window {
area: Rectangle,
caset_first: u8,
raset_first: u8,
}
impl Window {
pub fn covering<M: PixelMap>(area: Rectangle) -> Option<Self> {
let panel = Rectangle::new(Point::zero(), Size::new(M::WIDTH, M::HEIGHT));
let bottom_right = area.intersection(&panel).bottom_right()?; let top_left = area.intersection(&panel).top_left;
let x0 = top_left.x as u32 / PAIR * PAIR;
let y0 = top_left.y as u32 / BAND * BAND;
let x1 = (bottom_right.x as u32 / PAIR + 1) * PAIR; let y1 = (bottom_right.y as u32 / BAND + 1) * BAND;
Some(Self {
area: Rectangle::new(
Point::new(x0 as i32, y0 as i32),
Size::new(x1 - x0, y1 - y0),
),
caset_first: M::CASET_FIRST,
raset_first: M::RASET_FIRST,
})
}
pub fn full<M: PixelMap>() -> Self {
let panel = Rectangle::new(Point::zero(), Size::new(M::WIDTH, M::HEIGHT));
Self::covering::<M>(panel).expect("a panel has pixels")
}
pub const fn bounds(&self) -> Rectangle {
self.area
}
pub const fn byte_len(&self) -> usize {
(self.pairs() * self.bands()) as usize * BAND_BYTES
}
pub fn column_address_set(&self) -> ColumnAddressSet {
let xs = u32::from(self.caset_first) + self.band0();
ColumnAddressSet::new(xs as u8, (xs + self.bands() - 1) as u8)
}
pub fn row_address_set(&self) -> RowAddressSet {
let ys = u32::from(self.raset_first) + self.pair0();
RowAddressSet::new(ys as u8, (ys + self.pairs() - 1) as u8)
}
const fn pair0(&self) -> u32 {
self.area.top_left.x as u32 / PAIR
}
const fn pairs(&self) -> u32 {
self.area.size.width / PAIR
}
const fn band0(&self) -> u32 {
self.area.top_left.y as u32 / BAND
}
const fn bands(&self) -> u32 {
self.area.size.height / BAND
}
pub(super) fn copy_from<'a>(&self, buf: &[u8], height: u32, out: &'a mut [u8]) -> &'a [u8] {
let out = &mut out[..self.byte_len()];
let column = (height / 4) as usize; let width = self.bands() as usize * BAND_BYTES;
let offset = column - (self.band0() + self.bands()) as usize * BAND_BYTES;
let pair0 = self.pair0() as usize;
for (i, chunk) in out.chunks_exact_mut(width).enumerate() {
let start = (pair0 + i) * column + offset;
chunk.copy_from_slice(&buf[start..start + width]);
}
out
}
}