use crate::{
bitmap::BitmapRawDataMut,
colour::{write_as_bytes, Colour},
formats::A8,
};
use super::{GenericUnary, UnaryDispatch, UnaryOpSpec};
pub struct FillOp;
#[cfg(test)]
const _: () = {
use super::generate;
impl generate::UnaryInputSpec for FillOp {
fn gen<'l>() -> impl generate::ValueGeneratorList<'l, OutputTuple = Self::Params<'l>> {
(generate::random_colour,)
}
}
};
impl UnaryOpSpec for FillOp {
type Params<'l> = (Colour,);
fn build<'l>() -> UnaryDispatch<Self::Params<'l>> {
UnaryDispatch::from_generic::<Self>().with::<A8>(fill_a8)
}
}
fn fill_a8(target: &mut dyn BitmapRawDataMut, with: &(Colour,)) {
let height = target.height();
let row_width = target.width();
let stride = target.stride();
let data = target.data_mut();
let alpha = with.0.a;
if stride == row_width {
data[0..(stride * height)].fill(alpha);
return;
}
for y in 0..height {
let yoff = y * stride;
data[yoff..(yoff + row_width)].fill(alpha);
}
}
fn fill_helper<const WIDTH: usize>(target: &mut dyn BitmapRawDataMut, pattern: &[u8]) {
let width = target.width();
let row_width = width * WIDTH;
let stride = target.stride();
let height = target.height();
let target_data = target.data_mut();
let mut filled = WIDTH;
target_data[0..WIDTH].copy_from_slice(pattern);
while filled < row_width {
let to_fill = row_width - filled;
let to_copy = to_fill.min(filled);
target_data.copy_within(0..to_copy, filled);
filled += to_copy;
}
for y in 1..height {
let yoff = y * stride;
target_data.copy_within(0..row_width, yoff);
}
}
impl<'l> GenericUnary<(Colour,)> for FillOp {
fn perform<Format: crate::formats::PixelFormatSpec>(
write_data: &mut dyn BitmapRawDataMut,
params: &(Colour,),
) {
if write_data.width() == 0 || write_data.height() == 0 {
return;
}
let mut cdata = [0u8; 4];
write_as_bytes::<Format>(¶ms.0, &mut cdata);
let cdata = &cdata[0..Format::PIXEL_STRIDE];
if Format::PIXEL_STRIDE == 1 {
fill_helper::<1>(write_data, cdata);
} else if Format::PIXEL_STRIDE == 2 {
fill_helper::<2>(write_data, cdata);
} else if Format::PIXEL_STRIDE == 3 {
fill_helper::<3>(write_data, cdata);
} else if Format::PIXEL_STRIDE == 4 {
fill_helper::<4>(write_data, cdata);
} else {
unreachable!()
}
}
}