ass_renderer/backends/coverage/
composite.rs1use super::blend::{blend_row, mul255};
8use super::{CoverageTile, RenderBitmap};
9
10fn composite_coverage(
17 dst: &mut [u8],
18 dst_dim: (u32, u32),
19 src: (&[u8], u32, u32),
20 pos: (i32, i32),
21 color: [u8; 4],
22) {
23 let pa = u16::from(color[3]);
24 if pa == 0 {
25 return;
26 }
27 let pr = mul255(u16::from(color[0]), pa);
28 let pg = mul255(u16::from(color[1]), pa);
29 let pb = mul255(u16::from(color[2]), pa);
30
31 let (dst_w, dst_h) = dst_dim;
32 let (cov, cov_w, cov_h) = src;
33 let (x, y) = pos;
34
35 let (tw, th) = (cov_w as i32, cov_h as i32);
37 let (dw, dh) = (dst_w as i32, dst_h as i32);
38 let ty0 = (-y).max(0);
39 let ty1 = th.min(dh - y);
40 let tx0 = (-x).max(0);
41 let tx1 = tw.min(dw - x);
42 if ty1 <= ty0 || tx1 <= tx0 {
43 return;
44 }
45 let run = (tx1 - tx0) as usize;
46 for ty in ty0..ty1 {
47 let tile_base = (ty * tw + tx0) as usize;
48 let cov_row = &cov[tile_base..tile_base + run];
49 let dst_start = ((y + ty) * dw + x + tx0) as usize * 4;
50 blend_row(dst, dst_start, cov_row, pr, pg, pb, pa);
51 }
52}
53
54pub fn composite(
57 dst: &mut [u8],
58 dst_w: u32,
59 dst_h: u32,
60 tile: &CoverageTile,
61 x: i32,
62 y: i32,
63 color: [u8; 4],
64) {
65 composite_coverage(
66 dst,
67 (dst_w, dst_h),
68 (&tile.data, tile.width, tile.height),
69 (x, y),
70 color,
71 );
72}
73
74pub fn composite_bitmap(dst: &mut [u8], dst_w: u32, dst_h: u32, bmp: &RenderBitmap) {
77 match bmp {
78 RenderBitmap::Coverage {
79 width,
80 height,
81 coverage,
82 x,
83 y,
84 color,
85 } => composite_coverage(
86 dst,
87 (dst_w, dst_h),
88 (coverage, *width, *height),
89 (*x, *y),
90 *color,
91 ),
92 RenderBitmap::Rgba {
93 width,
94 height,
95 pixels,
96 x,
97 y,
98 } => composite_rgba(dst, (dst_w, dst_h), (pixels, *width, *height), (*x, *y)),
99 }
100}
101
102fn composite_rgba(dst: &mut [u8], dst_dim: (u32, u32), src: (&[u8], u32, u32), pos: (i32, i32)) {
104 let (dst_w, dst_h) = dst_dim;
105 let (pixels, sw, sh) = src;
106 let (x, y) = pos;
107 let (tw, th) = (sw as i32, sh as i32);
108 let (dw, dh) = (dst_w as i32, dst_h as i32);
109 let ty0 = (-y).max(0);
110 let ty1 = th.min(dh - y);
111 let tx0 = (-x).max(0);
112 let tx1 = tw.min(dw - x);
113 if ty1 <= ty0 || tx1 <= tx0 {
114 return;
115 }
116 for ty in ty0..ty1 {
117 let mut si = ((ty * tw + tx0) as usize) * 4;
118 let mut di = ((y + ty) * dw + x + tx0) as usize * 4;
119 for _ in tx0..tx1 {
120 let sa = u16::from(pixels[si + 3]);
121 if sa != 0 {
122 let inv = 255 - sa;
123 dst[di] = (u16::from(pixels[si]) + mul255(u16::from(dst[di]), inv)) as u8;
124 dst[di + 1] =
125 (u16::from(pixels[si + 1]) + mul255(u16::from(dst[di + 1]), inv)) as u8;
126 dst[di + 2] =
127 (u16::from(pixels[si + 2]) + mul255(u16::from(dst[di + 2]), inv)) as u8;
128 dst[di + 3] =
129 (u16::from(pixels[si + 3]) + mul255(u16::from(dst[di + 3]), inv)) as u8;
130 }
131 si += 4;
132 di += 4;
133 }
134 }
135}