use crate::Color;
use crate::layout::{Abgr, Argb, Bgra, Rgba};
use crate::model::{LumaAlpha, Rgb};
use crate::primaries::Primaries;
use crate::transfer::Linear;
use crate::{Premultiplied, Straight};
macro_rules! impl_blend {
($layout:ident) => {
impl<P> Color<[f32; 4], Rgb<P, Linear, $layout<Straight>>>
where
P: Primaries,
{
#[inline(always)]
pub fn premultiply(self) -> Color<[f32; 4], Rgb<P, Linear, $layout<Premultiplied>>> {
let [r, g, b, a] = self.inner();
Color::new([r * a, g * a, b * a, a])
}
}
impl<P> Color<[f32; 4], Rgb<P, Linear, $layout<Premultiplied>>>
where
P: Primaries,
{
#[inline(always)]
pub fn unpremultiply(self) -> Color<[f32; 4], Rgb<P, Linear, $layout<Straight>>> {
let [r, g, b, a] = self.inner();
if a == 0.0 {
Color::new([0.0, 0.0, 0.0, 0.0])
} else {
Color::new([r / a, g / a, b / a, a])
}
}
#[inline(always)]
pub fn over(self, dst: Self) -> Self {
let [sr, sg, sb, sa] = self.inner();
let [dr, dg, db, da] = dst.inner();
let inv = 1.0 - sa;
Color::new([sr + dr * inv, sg + dg * inv, sb + db * inv, sa + da * inv])
}
}
};
}
impl_blend!(Rgba);
impl_blend!(Bgra);
impl_blend!(Argb);
impl_blend!(Abgr);
impl<P> Color<[f32; 2], LumaAlpha<P, Linear, Straight>>
where
P: Primaries,
{
#[inline(always)]
pub fn premultiply(self) -> Color<[f32; 2], LumaAlpha<P, Linear, Premultiplied>> {
let [y, a] = self.inner();
Color::new([y * a, a])
}
}
impl<P> Color<[f32; 2], LumaAlpha<P, Linear, Premultiplied>>
where
P: Primaries,
{
#[inline(always)]
pub fn unpremultiply(self) -> Color<[f32; 2], LumaAlpha<P, Linear, Straight>> {
let [y, a] = self.inner();
if a == 0.0 {
Color::new([0.0, 0.0])
} else {
Color::new([y / a, a])
}
}
#[inline(always)]
pub fn over(self, dst: Self) -> Self {
let [sy, sa] = self.inner();
let [dy, da] = dst.inner();
let inv = 1.0 - sa;
Color::new([sy + dy * inv, sa + da * inv])
}
}