cranpose-render-common 0.19.0

Scene, renderer and hit-test contracts for Cranpose backends
Documentation
/// Draws a straight-alpha byte pixel over `dst`, source over, with the bytes
/// a float blend would work out. Each channel is the rational
/// `(s * a + d * (255 - a)) / 255` rounded: its fraction is a multiple of
/// 1/255, never one half, and the float error stays far below that gap, so
/// whole numbers round it the same way.
pub fn blend_byte_pixel(dst: &mut [u8; 4], src: [u8; 4]) {
    let alpha = u32::from(src[3]);
    match alpha {
        0 => {}
        255 => *dst = src,
        _ => {
            *dst = [
                mix_byte(src[0], dst[0], alpha),
                mix_byte(src[1], dst[1], alpha),
                mix_byte(src[2], dst[2], alpha),
                mix_byte(255, dst[3], alpha),
            ];
        }
    }
}

// One channel of `blend_byte_pixel`: `source` at `alpha` over `under`.
pub(crate) fn mix_byte(source: u8, under: u8, alpha: u32) -> u8 {
    ((u32::from(source) * alpha + u32::from(under) * (255 - alpha) + 127) / 255) as u8
}