use embedded_graphics_core::pixelcolor::*; use linfb::shape::Color; use slint::platform::software_renderer::TargetPixel; /// Simple RGBA color wrapper. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Rgba(C, u8); #[allow(unused)] #[inline(always)] fn mul_blend_u8(delta: u32, a: u32) -> u32 { // Exact (delta * a) / 255 using the div255 trick (no slow integer division). // Valid for 0..=65535 inputs; see Hacker's Delight 10-16. let t = delta * a + 128; (t + (t >> 8)) >> 8 } #[allow(unused)] impl Rgba { /// Create a new RGBA color. pub const fn new(color: C, alpha: u8) -> Self { Self(color, alpha) } /// Get the color component. pub const fn rgb(&self) -> C { self.0 } pub fn r(&self) -> u8 { self.0.r() } pub fn g(&self) -> u8 { self.0.g() } pub fn b(&self) -> u8 { self.0.b() } /// Get the alpha component (0..=255). pub const fn a(&self) -> u8 { self.1 } } impl PixelColor for Rgba { type Raw = C::Raw; } #[allow(unused)] pub trait Blend { fn blend(&self, bg: T) -> T; } impl Blend for Rgba { #[inline(always)] fn blend(&self, bg: Rgb888) -> Rgb888 { let a = self.a() as u32; if a == 0 { return bg; } if a == 255 { return self.rgb(); } let fr = self.rgb().r() as u32; let fg = self.rgb().g() as u32; let fb = self.rgb().b() as u32; let br = bg.r() as u32; let bgc = bg.g() as u32; let bb = bg.b() as u32; let r = (br + mul_blend_u8(fr.wrapping_sub(br), a)) as u8; let g = (bgc + mul_blend_u8(fg.wrapping_sub(bgc), a)) as u8; let b = (bb + mul_blend_u8(fb.wrapping_sub(bb), a)) as u8; Rgb888::new(r, g, b) } } impl TargetPixel for Rgba { fn blend(&mut self, color: slint::platform::software_renderer::PremultipliedRgbaColor) { let a = self.a() as u32; // if a == 0 { // return bg; // } // if a == 255 { // return self.rgb(); // } let fr = self.rgb().r() as u32; let fg = self.rgb().g() as u32; let fb = self.rgb().b() as u32; let br = color.red as u32; let bgc = color.green as u32; let bb = color.blue as u32; let r = (br + mul_blend_u8(fr.wrapping_sub(br), a)) as u8; let g = (bgc + mul_blend_u8(fg.wrapping_sub(bgc), a)) as u8; let b = (bb + mul_blend_u8(fb.wrapping_sub(bb), a)) as u8; self.0 = Rgb888::new(r, g, b); self.1 = a as u8; } fn from_rgb(red: u8, green: u8, blue: u8) -> Self { Self(Rgb888::new(red, green, blue), 255) } } impl From<(u8, u8, u8, u8)> for Rgba { fn from(value: (u8, u8, u8, u8)) -> Self { Self(Rgb888::new(value.0, value.1, value.2), value.3) } } impl From for Rgba { fn from(value: Color) -> Self { Self(Rgb888::new(value.red, value.green, value.blue), value.alpha) } }