use crate::{shape, Color, Result};
pub struct Canvas {
height: usize,
width: usize,
h_minus_1: usize,
w_minus_1: usize,
}
impl Canvas {
pub fn new(width: usize, height: usize) -> Result<Canvas> {
Ok(Canvas {
width: width,
height: height,
w_minus_1: width - 1,
h_minus_1: height - 1,
})
}
pub fn draw(&mut self, shape: &dyn shape::Shape, color: &Color, buffer: &mut [u8]) {
if shape.is_filled() {
shape.draw_filled(self, color, buffer)
} else {
shape.draw(self, color, buffer)
}
}
pub fn clear(&mut self, color: &Color, buffer: &mut [u8]) {
for i in 0..self.width {
for j in 0..self.height {
self.draw_point_internal(i, j, color, buffer);
}
}
}
#[inline]
pub fn get_color<'a>(&self, x: i32, y: i32, buffer: &'a mut [u8]) -> &'a [u8] {
let si = (x as usize + y as usize * self.width) * 4;
return &(buffer[si..si + 4]);
}
#[inline(always)]
pub(crate) fn draw_point(&mut self, x: i32, y: i32, color: &Color, buffer: &mut [u8]) {
self.draw_point_internal(x as usize, y as usize, color, buffer)
}
#[inline(always)]
fn draw_point_internal(&mut self, x: usize, y: usize, color: &Color, buffer: &mut [u8]) {
if x > self.w_minus_1 || y > self.h_minus_1 {
return;
}
let si = (x + y * self.width) * 4;
buffer[si] = color.r;
buffer[si + 1] = color.g;
buffer[si + 2] = color.b;
buffer[si + 3] = color.a;
}
}