#[cfg(feature = "aa")]
use core::fmt::Debug;
#[cfg(feature = "aa")]
use embedded_graphics_core::draw_target::DrawTarget;
#[cfg(feature = "aa")]
use embedded_graphics_core::pixelcolor::{Rgb565, RgbColor};
#[cfg(feature = "aa")]
use embedded_graphics_core::prelude::Point;
#[cfg(feature = "aa")]
use crate::raster::aa::ReadPixel;
#[cfg(feature = "aa")]
#[inline(always)]
fn blend_q8(bg: Rgb565, fg: Rgb565, coverage_q8: u32) -> Rgb565 {
let inv = 256 - coverage_q8;
let r = (bg.r() as u32 * inv + fg.r() as u32 * coverage_q8) >> 8;
let g = (bg.g() as u32 * inv + fg.g() as u32 * coverage_q8) >> 8;
let b = (bg.b() as u32 * inv + fg.b() as u32 * coverage_q8) >> 8;
Rgb565::new(r as u8, g as u8, b as u8)
}
#[cfg(feature = "aa")]
#[inline(always)]
fn plot_aa<D>(fb: &mut D, x: i32, y: i32, color: Rgb565, coverage_q8: u32)
where
D: DrawTarget<Color = Rgb565> + ReadPixel,
<D as DrawTarget>::Error: Debug,
{
if coverage_q8 == 0 {
return;
}
let final_color = if coverage_q8 >= 256 {
color
} else {
let bg = fb.read_pixel(Point::new(x, y));
blend_q8(bg, color, coverage_q8)
};
fb.draw_iter([embedded_graphics_core::Pixel(Point::new(x, y), final_color)])
.unwrap();
}
#[cfg(feature = "aa")]
pub fn draw_line_aa<D>(x0: i32, y0: i32, x1: i32, y1: i32, color: Rgb565, fb: &mut D)
where
D: DrawTarget<Color = Rgb565> + ReadPixel,
<D as DrawTarget>::Error: Debug,
{
let dx = (x1 - x0).abs();
let dy = (y1 - y0).abs();
let steep = dy > dx;
let (x0, y0, x1, y1) = if steep {
(y0, x0, y1, x1)
} else {
(x0, y0, x1, y1)
};
let (x0, y0, x1, y1) = if x0 > x1 {
(x1, y1, x0, y0)
} else {
(x0, y0, x1, y1)
};
let dx = x1 - x0;
let dy = y1 - y0;
if dx == 0 {
let (px, py) = if steep { (y0, x0) } else { (x0, y0) };
plot_aa(fb, px, py, color, 256);
return;
}
let gradient: i32 = ((dy as i64) << 16) as i32 / dx;
let mut intery: i32 = y0 << 16;
for x in x0..=x1 {
let y_int = intery >> 16;
let frac_q16 = (intery & 0xFFFF) as u32;
let cov_top = 256 - (frac_q16 >> 8); let cov_bot = frac_q16 >> 8; if steep {
plot_aa(fb, y_int, x, color, cov_top);
plot_aa(fb, y_int + 1, x, color, cov_bot);
} else {
plot_aa(fb, x, y_int, color, cov_top);
plot_aa(fb, x, y_int + 1, color, cov_bot);
}
intery += gradient;
}
}