use crate::{
bitmap::{BitmapAccess, BitmapRawDataMut},
colour::{read_from_bytes, write_as_bytes, BlendMode, Colour},
formats::{PixelFormatSpec, Rgba32, A8},
math::{PixelBox, PixelPoint},
op::binary_map_pixel_data_with,
};
use super::{
dispatch::{GenericUnary, UnaryDispatch},
UnaryOpSpec,
};
#[cfg(target_arch = "x86_64")]
mod x86_64;
pub struct FillRegionMaskedOp;
type OpParams<'l> = (
&'l dyn BitmapAccess<A8>,
PixelBox,
PixelPoint,
Colour,
BlendMode,
);
#[cfg(any(test, feature = "benchmark"))]
const _: () = {
use super::generate;
impl generate::UnaryInputSpec for FillRegionMaskedOp {
fn gen<'l>() -> impl generate::ValueGeneratorList<'l, OutputTuple = Self::Params<'l>> {
(
generate::alphamap,
generate::alphamap_area,
generate::dst_point,
generate::random_colour,
generate::blend_mode,
)
}
}
};
impl<'l> GenericUnary<OpParams<'l>> for FillRegionMaskedOp {
fn perform<Format: PixelFormatSpec>(
write_data: &mut dyn BitmapRawDataMut,
params: &OpParams<'l>,
) {
let (read_alphamap, read_box, dst, colour, blend) = params;
binary_map_pixel_data_with::<0usize, Format, A8>(
write_data,
*read_alphamap,
read_box.size(),
*dst,
read_box.min,
|dst_slice, src_slice| {
let mut dx = 0;
let mut sx = 0;
while dx < dst_slice.len() {
let existing = read_from_bytes::<Format>(&dst_slice[dx..]);
let new_alpha = src_slice[sx];
let new_colour = blend.blend(
&Colour {
a: new_alpha,
..*colour
},
&existing,
);
write_as_bytes::<Format>(&new_colour, &mut dst_slice[dx..]);
dx += Format::PIXEL_STRIDE;
sx += A8::PIXEL_STRIDE;
}
},
);
}
}
impl UnaryOpSpec for FillRegionMaskedOp {
type Params<'l> = OpParams<'l>;
fn build<'l>() -> UnaryDispatch<Self::Params<'l>> {
UnaryDispatch::from_generic::<Self>().with_avx::<Rgba32>(x86_64::avx_rbga32)
}
}