From cbe54334caffe348ab3c88f61bfe206074708dd9 Mon Sep 17 00:00:00 2001 From: chlorospingus Date: Tue, 29 Apr 2025 03:30:33 -0700 Subject: [PATCH] Improve circle rendering and add antialiasing to rounded rect --- src/graphics/rectangle.rs | 57 ++++++++++++++++++++++++++------------- src/wayland/wl_shm.rs | 4 +-- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/graphics/rectangle.rs b/src/graphics/rectangle.rs index ab4c451..f52504b 100644 --- a/src/graphics/rectangle.rs +++ b/src/graphics/rectangle.rs @@ -1,3 +1,5 @@ +use std::usize; + use crate::wayland::shm::ShmPool; fn color_blend(col1: u32, col2: u32, diff: f64) -> u32 { @@ -46,29 +48,46 @@ impl ShmPool { radius: usize, color: u32 ) { - for l_row in 0..radius+1 { - let x_diff = radius - ((radius*radius - l_row*l_row) as f64).sqrt() as usize; - self.write(&vec![color; w - (2*x_diff)], (y+radius-l_row)*self.width + x + x_diff); - self.write(&vec![color; w - (2*x_diff)], (y+h-radius+l_row)*self.width + x + x_diff); + 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); + 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 { + for g_row in y+radius..y+h-radius+1 { self.write(&vec![color; w], g_row*self.width+x); } } - - pub fn shitty_circle(&mut self, x: usize, y: usize, radius: usize, color: u32) { - for g_row in y-radius..y+radius+1 { - for g_col in x-radius..x+radius+1 { - let l_row = y.abs_diff(g_row); - let l_col = y.abs_diff(g_col); - let distance = (((l_row*l_row)+(l_col*l_col)) as f64).sqrt(); - let offset = g_row*self.width + g_col; - if (distance.floor() as usize) < radius { - self.write_pixel(color, offset as isize); - } else if (distance.ceil() as usize) <= radius+1 { - dbg!(distance); - self.write_pixel(color_blend(color, self.read_pixel(offset), distance.fract()), offset as isize); - } + + // 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); } } } diff --git a/src/wayland/wl_shm.rs b/src/wayland/wl_shm.rs index bd3b7fc..ddd5a1f 100644 --- a/src/wayland/wl_shm.rs +++ b/src/wayland/wl_shm.rs @@ -14,8 +14,8 @@ impl WlClient { self.shm_pool = Some(shm::ShmPool::new(width, height, self.current_id)?); self.shm_pool.as_mut().unwrap().write(&vec![0xffff0000; width * height], 0); self.shm_pool.as_mut().unwrap().rectangle(50, 50, 50, 50, 0xff00ff00); - self.shm_pool.as_mut().unwrap().shitty_circle(200, 200, 20, 0xff0000ff); - self.shm_pool.as_mut().unwrap().rounded_rectangle(400, 200, 200, 100, 14, 0xffffff00); + self.shm_pool.as_mut().unwrap().circle(300, 300, 200, 0xff0000ff); + self.shm_pool.as_mut().unwrap().rounded_rectangle(450, 400, 60, 40, 16, 0xffffff00); let object = self.shm_id.ok_or(UnsetErr("shm_id".to_string()))?; const OPCODE: u16 = 0;