use super::blend::{blend_row, mul255};
use super::{CoverageTile, RenderBitmap};
fn composite_coverage(
dst: &mut [u8],
dst_dim: (u32, u32),
src: (&[u8], u32, u32),
pos: (i32, i32),
color: [u8; 4],
) {
let pa = u16::from(color[3]);
if pa == 0 {
return;
}
let pr = mul255(u16::from(color[0]), pa);
let pg = mul255(u16::from(color[1]), pa);
let pb = mul255(u16::from(color[2]), pa);
let (dst_w, dst_h) = dst_dim;
let (cov, cov_w, cov_h) = src;
let (x, y) = pos;
let (tw, th) = (cov_w as i32, cov_h as i32);
let (dw, dh) = (dst_w as i32, dst_h as i32);
let ty0 = (-y).max(0);
let ty1 = th.min(dh - y);
let tx0 = (-x).max(0);
let tx1 = tw.min(dw - x);
if ty1 <= ty0 || tx1 <= tx0 {
return;
}
let run = (tx1 - tx0) as usize;
for ty in ty0..ty1 {
let tile_base = (ty * tw + tx0) as usize;
let cov_row = &cov[tile_base..tile_base + run];
let dst_start = ((y + ty) * dw + x + tx0) as usize * 4;
blend_row(dst, dst_start, cov_row, pr, pg, pb, pa);
}
}
pub fn composite(
dst: &mut [u8],
dst_w: u32,
dst_h: u32,
tile: &CoverageTile,
x: i32,
y: i32,
color: [u8; 4],
) {
composite_coverage(
dst,
(dst_w, dst_h),
(&tile.data, tile.width, tile.height),
(x, y),
color,
);
}
pub fn composite_bitmap(dst: &mut [u8], dst_w: u32, dst_h: u32, bmp: &RenderBitmap) {
match bmp {
RenderBitmap::Coverage {
width,
height,
coverage,
x,
y,
color,
} => composite_coverage(
dst,
(dst_w, dst_h),
(coverage, *width, *height),
(*x, *y),
*color,
),
RenderBitmap::Rgba {
width,
height,
pixels,
x,
y,
} => composite_rgba(dst, (dst_w, dst_h), (pixels, *width, *height), (*x, *y)),
}
}
fn composite_rgba(dst: &mut [u8], dst_dim: (u32, u32), src: (&[u8], u32, u32), pos: (i32, i32)) {
let (dst_w, dst_h) = dst_dim;
let (pixels, sw, sh) = src;
let (x, y) = pos;
let (tw, th) = (sw as i32, sh as i32);
let (dw, dh) = (dst_w as i32, dst_h as i32);
let ty0 = (-y).max(0);
let ty1 = th.min(dh - y);
let tx0 = (-x).max(0);
let tx1 = tw.min(dw - x);
if ty1 <= ty0 || tx1 <= tx0 {
return;
}
for ty in ty0..ty1 {
let mut si = ((ty * tw + tx0) as usize) * 4;
let mut di = ((y + ty) * dw + x + tx0) as usize * 4;
for _ in tx0..tx1 {
let sa = u16::from(pixels[si + 3]);
if sa != 0 {
let inv = 255 - sa;
dst[di] = (u16::from(pixels[si]) + mul255(u16::from(dst[di]), inv)) as u8;
dst[di + 1] =
(u16::from(pixels[si + 1]) + mul255(u16::from(dst[di + 1]), inv)) as u8;
dst[di + 2] =
(u16::from(pixels[si + 2]) + mul255(u16::from(dst[di + 2]), inv)) as u8;
dst[di + 3] =
(u16::from(pixels[si + 3]) + mul255(u16::from(dst[di + 3]), inv)) as u8;
}
si += 4;
di += 4;
}
}
}