use crate::BitMapBackend;
use plotters_backend::DrawingBackend;
#[inline(always)]
pub(super) fn blend(prev: &mut u8, new: u8, a: u64) {
if new > *prev {
*prev += (u64::from(new - *prev) * a / 256) as u8
} else {
*prev -= (u64::from(*prev - new) * a / 256) as u8
}
}
pub trait PixelFormat: Sized {
const PIXEL_SIZE: usize;
const EFFECTIVE_PIXEL_SIZE: usize;
fn byte_at(r: u8, g: u8, b: u8, a: u64, idx: usize) -> u8;
fn decode_pixel(data: &[u8]) -> (u8, u8, u8, u64);
fn blend_rect_fast(
target: &mut BitMapBackend<'_, Self>,
upper_left: (i32, i32),
bottom_right: (i32, i32),
r: u8,
g: u8,
b: u8,
a: f64,
);
fn fill_vertical_line_fast(
target: &mut BitMapBackend<'_, Self>,
x: i32,
ys: (i32, i32),
r: u8,
g: u8,
b: u8,
) {
let (w, h) = target.get_size();
let w = w as i32;
let h = h as i32;
if x < 0 || x >= w {
return;
}
let dst = target.get_raw_pixel_buffer();
let (mut y0, mut y1) = ys;
if y0 > y1 {
std::mem::swap(&mut y0, &mut y1);
}
y0 = y0.max(0);
y1 = y1.min(h - 1);
for y in y0..=y1 {
for idx in 0..Self::EFFECTIVE_PIXEL_SIZE {
dst[(y * w + x) as usize * Self::PIXEL_SIZE + idx] = Self::byte_at(r, g, b, 0, idx);
}
}
}
fn fill_rect_fast(
target: &mut BitMapBackend<'_, Self>,
upper_left: (i32, i32),
bottom_right: (i32, i32),
r: u8,
g: u8,
b: u8,
);
#[inline(always)]
fn draw_pixel(
target: &mut BitMapBackend<'_, Self>,
point: (i32, i32),
(r, g, b): (u8, u8, u8),
alpha: f64,
) {
let (x, y) = (point.0 as usize, point.1 as usize);
let (w, _) = target.get_size();
let buf = target.get_raw_pixel_buffer();
let w = w as usize;
let base = (y * w + x) * Self::PIXEL_SIZE;
if base < buf.len() {
unsafe {
if alpha >= 1.0 - 1.0 / 256.0 {
for idx in 0..Self::EFFECTIVE_PIXEL_SIZE {
*buf.get_unchecked_mut(base + idx) = Self::byte_at(r, g, b, 0, idx);
}
} else {
if alpha <= 0.0 {
return;
}
let alpha = (alpha * 256.0).floor() as u64;
for idx in 0..Self::EFFECTIVE_PIXEL_SIZE {
blend(
buf.get_unchecked_mut(base + idx),
Self::byte_at(r, g, b, 0, idx),
alpha,
);
}
}
}
}
}
fn can_be_saved() -> bool {
false
}
}