atmos/os_lib/web_engine/
alpha_blend.rs1extern crate alloc;
15
16#[derive(Debug, PartialEq, Clone, Copy)]
18pub enum BlendError {
19 NonFiniteAlpha(f32),
22}
23
24pub fn alpha_f32_to_u8(a: f32) -> Result<u8, BlendError> {
30 if !a.is_finite() {
31 crate::error!(
32 "[BLEND] アルファが有限値ではありません: {}。不透明として扱ってください",
33 a
34 );
35 return Err(BlendError::NonFiniteAlpha(a));
36 }
37 let clamped = a.clamp(0.0, 1.0);
38 Ok((clamped * 255.0 + 0.5) as u8)
39}
40
41#[inline]
46pub fn blend_channel(src: u8, dst: u8, alpha: u8) -> u8 {
47 let s = src as u32;
48 let d = dst as u32;
49 let a = alpha as u32;
50 (((s * a) + (d * (255 - a)) + 127) / 255) as u8
51}
52
53pub fn blend_argb_over(src: u32, dst: u32) -> u32 {
58 let a = ((src >> 24) & 0xFF) as u8;
59 if a == 255 {
61 return 0xFF00_0000 | (src & 0x00FF_FFFF);
62 }
63 if a == 0 {
64 return 0xFF00_0000 | (dst & 0x00FF_FFFF);
65 }
66 let sr = ((src >> 16) & 0xFF) as u8;
67 let sg = ((src >> 8) & 0xFF) as u8;
68 let sb = (src & 0xFF) as u8;
69 let dr = ((dst >> 16) & 0xFF) as u8;
70 let dg = ((dst >> 8) & 0xFF) as u8;
71 let db = (dst & 0xFF) as u8;
72 let r = blend_channel(sr, dr, a) as u32;
73 let g = blend_channel(sg, dg, a) as u32;
74 let b = blend_channel(sb, db, a) as u32;
75 0xFF00_0000 | (r << 16) | (g << 8) | b
76}
77
78#[inline]
80pub fn needs_blend(argb: u32) -> bool {
81 ((argb >> 24) & 0xFF) != 0xFF
82}