kahlo 0.0.2

Optimized software rendering library.
Documentation
use crate::{
    bitmap::{BitmapRawData, BitmapRawDataMut},
    colour::{read_from_bytes, write_as_bytes, BlendMode},
    formats::{PixelFormatSpec, Rgba32},
    math::{PixelBox, PixelPoint},
    op::binary_map_pixel_data_with,
};

use super::{
    dispatch::{BinaryDispatch, GenericBinary},
    BinaryOpSpec,
};

pub struct CompositeOp;

#[cfg(any(test, feature = "benchmark"))]
const _: () = {
    use super::generate;
    impl generate::BinaryInputSpec for CompositeOp {
        fn gen<'l>() -> impl generate::ValueGeneratorList<'l, OutputTuple = Self::Params<'l>> {
            (
                generate::src_area,
                generate::dst_point,
                generate::blend_mode,
            )
        }
    }
};

impl<'l> GenericBinary<(PixelBox, PixelPoint, BlendMode)> for CompositeOp {
    fn perform<Format: PixelFormatSpec, SrcFormat: PixelFormatSpec>(
        write_data: &mut dyn BitmapRawDataMut,
        read_data: &dyn BitmapRawData,
        params: &(PixelBox, PixelPoint, BlendMode),
    ) {
        let (read_box, dst, bmode) = params;

        binary_map_pixel_data_with::<0usize, Format, SrcFormat>(
            write_data,
            read_data,
            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 source = read_from_bytes::<SrcFormat>(&src_slice[sx..]);
                    let blended = bmode.blend(&source, &existing);
                    write_as_bytes::<Format>(&blended, &mut dst_slice[dx..]);

                    dx += Format::PIXEL_STRIDE;
                    sx += SrcFormat::PIXEL_STRIDE;
                }
            },
        );
    }
}

#[cfg(target_arch = "x86_64")]
mod x86_64;

impl BinaryOpSpec for CompositeOp {
    type Params<'l> = (PixelBox, PixelPoint, BlendMode);
    fn build<'l>() -> BinaryDispatch<Self::Params<'l>> {
        BinaryDispatch::from_generic::<Self>().with_avx::<Rgba32, Rgba32>(x86_64::avx_rgba32_rgba32)
    }
}