showbits/showbits-common/src/view.rs

89 lines
2.3 KiB
Rust

use image::RgbaImage;
use palette::{Srgba, blend::Compose};
use crate::{Rect, Vec2, color};
pub struct View<'a> {
area: Rect,
buffer: &'a mut RgbaImage,
}
impl<'a> View<'a> {
pub fn new(buffer: &'a mut RgbaImage) -> Self {
let size = Vec2::from_u32(buffer.width(), buffer.height());
let area = Rect::from_nw(Vec2::ZERO, size);
Self { area, buffer }
}
pub fn dup(&mut self) -> View<'_> {
View {
area: self.area,
buffer: self.buffer,
}
}
pub fn zoom(mut self, area: Rect) -> Self {
self.area = area + self.area.corner_nw();
self
}
pub fn size(&self) -> Vec2 {
self.area.size()
}
pub fn area(&self) -> Rect {
Rect::from_nw(Vec2::ZERO, self.size())
}
fn pos_to_buffer_pos(&self, pos: Vec2) -> Vec2 {
pos + self.area.corner_nw()
}
pub fn get(&self, pos: Vec2) -> Option<Srgba> {
let (x, y) = self.pos_to_buffer_pos(pos).to_u32_checked()?;
let pixel = self.buffer.get_pixel_checked(x, y)?;
Some(color::from_image_color(*pixel))
}
pub fn set(&mut self, pos: Vec2, color: Srgba) {
let Some((x, y)) = self.pos_to_buffer_pos(pos).to_u32_checked() else {
return;
};
let Some(pixel) = self.buffer.get_pixel_mut_checked(x, y) else {
return;
};
let below = color::from_image_color(*pixel);
*pixel = color::to_image_color(color.atop(below));
}
pub fn replace(&mut self, pos: Vec2, color: Srgba) {
let Some((x, y)) = self.pos_to_buffer_pos(pos).to_u32_checked() else {
return;
};
let Some(pixel) = self.buffer.get_pixel_mut_checked(x, y) else {
return;
};
*pixel = color::to_image_color(color);
}
// More complicated drawing primitives
pub fn rect(&mut self, area: Rect, color: Srgba) {
for pos in area.points() {
self.set(pos, color);
}
}
pub fn image(&mut self, image: &RgbaImage) {
for y in 0..image.height() {
for x in 0..image.width() {
let color = color::from_image_color(*image.get_pixel(x, y));
self.set(Vec2::from_u32(x, y), color);
}
}
}
}