use crate::color::Color;
pub const LANES: u32 = 0x00FF_00FF;
#[inline(always)]
pub const fn mul_lanes(x: u32, a: u32) -> u32 {
let t = x * a + 0x0080_0080;
((t + ((t >> 8) & LANES)) >> 8) & LANES
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Paint {
premul: u32,
alpha: u32,
}
impl Paint {
#[inline]
pub const fn new(color: Color) -> Self {
let a = color.a as u32;
let rb = mul_lanes(((color.r as u32) << 16) | color.b as u32, a);
let g = mul_lanes(color.g as u32, a);
Self {
premul: (a << 24) | rb | (g << 8),
alpha: a,
}
}
#[inline]
pub const fn premultiplied(self) -> u32 {
self.premul
}
#[inline]
pub const fn alpha(self) -> u32 {
self.alpha
}
#[inline]
pub const fn is_opaque(self) -> bool {
self.alpha == 255
}
#[inline]
pub const fn is_invisible(self) -> bool {
self.alpha == 0
}
#[inline]
pub const fn scaled(self, coverage: u32) -> Self {
let premul = scale_premul(self.premul, coverage);
Self {
premul,
alpha: premul >> 24,
}
}
}
impl From<Color> for Paint {
#[inline]
fn from(color: Color) -> Self {
Paint::new(color)
}
}
#[inline(always)]
pub const fn scale_premul(px: u32, coverage: u32) -> u32 {
let rb = mul_lanes(px & LANES, coverage);
let ag = mul_lanes((px >> 8) & LANES, coverage);
rb | (ag << 8)
}