From 9d0b9b97b59546303c477b09ffff015ed483767c Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Tue, 13 May 2025 21:54:59 -0700 Subject: [PATCH] Use structs with Drawable trait instead of methods on shm_pool --- src/graphics/circle.rs | 39 +++++++++++++ src/graphics/drawable.rs | 31 ++++++++++ src/graphics/mod.rs | 2 + src/graphics/rectangle.rs | 115 +++++++++++--------------------------- src/wayland/wl_shm.rs | 9 ++- 5 files changed, 111 insertions(+), 85 deletions(-) create mode 100644 src/graphics/circle.rs create mode 100644 src/graphics/drawable.rs diff --git a/src/graphics/circle.rs b/src/graphics/circle.rs new file mode 100644 index 0000000..1affd27 --- /dev/null +++ b/src/graphics/circle.rs @@ -0,0 +1,39 @@ +use crate::wayland::shm::ShmPool; +use super::drawable::{Drawable, color_blend}; + +// x and y are center of circle +pub struct Circle { + x: usize, + y: usize, + radius: usize, + color: u32, +} + +impl Circle { + pub fn new(x: usize, y: usize, radius: usize, color: u32) -> Self { + Circle { x, y, radius, color } + } +} + +impl Drawable for Circle { + fn draw(&self, shm_pool: &mut ShmPool) { + for l_row in 1..self.radius { + let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); + let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt(); + let row: Vec = vec![self.color; 2*(inner_diff.floor() as usize)]; + shm_pool.write(&row, (self.y-l_row)*shm_pool.width + self.x - inner_diff.floor() as usize); + shm_pool.write(&row, (self.y+l_row-1)*shm_pool.width + self.x - inner_diff.floor() as usize); + for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) { + let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt(); + let offset = (self.y-l_row)*shm_pool.width + self.x - l_col; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y-l_row)*shm_pool.width + self.x + l_col-1; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+l_row-1)*shm_pool.width + self.x - l_col; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+l_row-1)*shm_pool.width + self.x + l_col-1; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + } + } + } +} diff --git a/src/graphics/drawable.rs b/src/graphics/drawable.rs new file mode 100644 index 0000000..7d495f8 --- /dev/null +++ b/src/graphics/drawable.rs @@ -0,0 +1,31 @@ +use crate::wayland::shm::ShmPool; + +pub fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 { + // TODO: Account for alpha channel + let r1 = (col1 & 0x00ff0000) >> 16; + let g1 = (col1 & 0x0000ff00) >> 8; + let b1 = col1 & 0x000000ff; + let r2 = (col2 & 0x00ff0000) >> 16; + let g2 = (col2 & 0x0000ff00) >> 8; + let b2 = col2 & 0x000000ff; + let r3 = if r1 < r2 { + r1 + ((r2 - r1) as f64 * diff) as u32 + } else { + r1 - ((r1 - r2) as f64 * diff) as u32 + }; + let g3 = if g1 < g2 { + g1 + ((g2 - g1) as f64 * diff) as u32 + } else { + g1 - ((g1 - g2) as f64 * diff) as u32 + }; + let b3 = if b1 < b2 { + b1 + ((b2 - b1) as f64 * diff) as u32 + } else { + b1 - ((b1 - b2) as f64 * diff) as u32 + }; + return 0xff000000 + (r3 << 16) + (g3 << 8) + b3; +} + +pub trait Drawable { + fn draw(&self, shm_pool: &mut ShmPool); +} diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index 5b2aff3..5f6292e 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -1,2 +1,4 @@ +pub mod drawable; pub mod rectangle; +pub mod circle; diff --git a/src/graphics/rectangle.rs b/src/graphics/rectangle.rs index f52504b..ca20fc2 100644 --- a/src/graphics/rectangle.rs +++ b/src/graphics/rectangle.rs @@ -1,94 +1,45 @@ -use std::usize; - use crate::wayland::shm::ShmPool; +use super::drawable::{Drawable, color_blend}; -fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 { - // TODO: Account for alpha channel - let r1 = (col1 & 0x00ff0000) >> 16; - let g1 = (col1 & 0x0000ff00) >> 8; - let b1 = col1 & 0x000000ff; - let r2 = (col2 & 0x00ff0000) >> 16; - let g2 = (col2 & 0x0000ff00) >> 8; - let b2 = col2 & 0x000000ff; - let r3 = if r1 < r2 { - r1 + ((r2 - r1) as f64 * diff) as u32 - } else { - r1 - ((r1 - r2) as f64 * diff) as u32 - }; - let g3 = if g1 < g2 { - g1 + ((g2 - g1) as f64 * diff) as u32 - } else { - g1 - ((g1 - g2) as f64 * diff) as u32 - }; - let b3 = if b1 < b2 { - b1 + ((b2 - b1) as f64 * diff) as u32 - } else { - b1 - ((b1 - b2) as f64 * diff) as u32 - }; - return 0xff000000 + (r3 << 16) + (g3 << 8) + b3; + +// x and y and topleft corner of rect +pub struct Rectangle { + x: usize, + y: usize, + width: usize, + height: usize, + radius: usize, + color: u32, } -// l_row means local row and g_row means global row -impl ShmPool { - - // x and y are topleft corner of rect - pub fn rectangle(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) { - for g_row in y..y+h { - self.write(&vec![color; w], g_row*self.width+x); - } +impl Rectangle { + pub fn new(x: usize, y: usize, width: usize, height: usize, radius: usize, color: u32) -> Self { + Rectangle {x, y, width, height, radius, color} } +} - // x and y and topleft corner of rect - pub fn rounded_rectangle( - &mut self, - x: usize, - y: usize, - w: usize, - h: usize, - radius: usize, - color: u32 - ) { - for l_row in 1..radius { - let inner_diff = (((radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); - let outer_diff = ((radius.pow(2) - l_row.pow(2)) as f64).sqrt(); - self.write(&vec![color; w - (2*(radius - inner_diff.floor() as usize-1))], (y+radius-l_row)*self.width + x + radius - inner_diff.floor() as usize-1); - self.write(&vec![color; w - (2*(radius - inner_diff.floor() as usize-1))], (y+h-radius+l_row)*self.width + x + radius - inner_diff.floor() as usize-1); +impl Drawable for Rectangle { + fn draw(&self, shm_pool: &mut ShmPool) { + for g_row in self.y+self.radius..self.y+self.height-self.radius+1 { + shm_pool.write(&vec![self.color; self.width], g_row*shm_pool.width+self.x); + } + for l_row in 1..self.radius { + let inner_diff = (((self.radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); + let outer_diff = ((self.radius.pow(2) - l_row.pow(2)) as f64).sqrt(); + shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1); + shm_pool.write(&vec![self.color; self.width - (2*(self.radius - inner_diff.floor() as usize-1))], (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - inner_diff.floor() as usize-1); for l_col in inner_diff.floor() as usize+1..outer_diff.ceil() as usize { let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt(); - let offset = (y+radius-l_row)*self.width + x + radius - l_col - 1; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y+radius-l_row)*self.width + x + w - radius + l_col; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y+h-radius+l_row)*self.width + x + radius - l_col - 1; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y+h-radius+l_row)*self.width + x + w - radius + l_col; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - } - } - for g_row in y+radius..y+h-radius+1 { - self.write(&vec![color; w], g_row*self.width+x); - } - } - - // x and y are center of circle - pub fn circle(&mut self, x: usize, y: usize, radius: usize, color: u32) { - for l_row in 1..radius { - let inner_diff = (((radius-1).pow(2) - l_row.pow(2)) as f64).sqrt(); - let outer_diff = ((radius.pow(2) - l_row.pow(2)) as f64).sqrt(); - let row: Vec = vec![color; 2*(inner_diff.floor() as usize)]; - self.write(&row, (y-l_row)*self.width + x - inner_diff.floor() as usize); - self.write(&row, (y+l_row-1)*self.width + x - inner_diff.floor() as usize); - for l_col in (inner_diff.floor() as usize+1)..(outer_diff.ceil() as usize) { - let distance = ((l_row.pow(2) + l_col.pow(2)) as f64).sqrt(); - let offset = (y-l_row)*self.width + x - l_col; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y-l_row)*self.width + x + l_col-1; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y+l_row-1)*self.width + x - l_col; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - let offset = (y+l_row-1)*self.width + x + l_col-1; - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.radius - l_col - 1; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+self.radius-l_row)*shm_pool.width + self.x + self.width - self.radius + l_col; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.radius - l_col - 1; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); + let offset = (self.y+self.height-self.radius+l_row)*shm_pool.width + self.x + self.width - self.radius + l_col; + shm_pool.write_pixel(color_blend(self.color, shm_pool.read_pixel(offset), distance.fract()), offset as isize); } } } } + diff --git a/src/wayland/wl_shm.rs b/src/wayland/wl_shm.rs index 122fc2a..1d6375b 100644 --- a/src/wayland/wl_shm.rs +++ b/src/wayland/wl_shm.rs @@ -1,5 +1,7 @@ use std::{error::Error, io::Write, os::unix::net::SocketAncillary, sync::atomic::Ordering, u8}; +use crate::graphics::drawable::Drawable; use crate::wayland::{shm, surface::UnsetErr, vec_utils::WlMessage, wl_client::WlClient}; +use crate::graphics::{rectangle::Rectangle, circle::Circle}; const STRIDE: usize = 4; @@ -15,9 +17,10 @@ impl WlClient { self.shmpool_id.store(current_id, Ordering::Relaxed); shm_pool.write(&vec![0xffff0000; width * height], 0); - shm_pool.rectangle(50, 50, 50, 50, 0xff00ff00); - shm_pool.circle(300, 300, 200, 0xff0000ff); - shm_pool.rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00); + let rect = Rectangle::new(100, 100, 200, 50, 25, 0xffffff); + rect.draw(&mut shm_pool); + let circle = Circle::new(250, 150, 20, 0xff00ffff); + circle.draw(&mut shm_pool); let object = self.shm_id.load(Ordering::Relaxed); if object == 0 {