From 4b4ebe84d2cfbb8b0ddf7b678c5fe4cff53e5089 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 13 Mar 2021 13:15:48 +0530 Subject: refactor to use pixmap over Vec --- src/app.rs | 120 ++++++++++++++++++++++++------------------------------------ src/main.rs | 1 + src/undo.rs | 4 +- 3 files changed, 51 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/app.rs b/src/app.rs index 84d884f..c0d3018 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,9 @@ -use crate::undo::{ModifyRecord, OpKind, Operation, UndoStack}; +use crate::{ + bitmap::{MapPoint, Pixmap}, + undo::{ModifyRecord, OpKind, Operation, UndoStack}, +}; + +use std::convert::{From, TryFrom}; use sdl2::{ event::Event, @@ -15,9 +20,7 @@ use crate::consts::{BLACK, GRID_COLOR, WHITE}; pub struct AppState<'ctx> { start: Point, - width: u32, - height: u32, - data: Vec, + pixmap: Pixmap, zoom: u8, brush_size: u8, grid: Grid, @@ -49,11 +52,19 @@ impl<'ctx> AppState<'ctx> { self.start += direction.into(); } + fn width(&self) -> u32 { + self.pixmap.width + } + + fn height(&self) -> u32 { + self.pixmap.height + } + fn bounds(&self) -> (Point, Point) { let x_min = self.start.x(); let y_min = self.start.y(); - let x_max = self.start.x() + (self.width * self.zoom as u32) as i32; - let y_max = self.start.y() + (self.height * self.zoom as u32) as i32; + let x_max = self.start.x() + (self.width() * self.zoom as u32) as i32; + let y_max = self.start.y() + (self.height() * self.zoom as u32) as i32; return ( Point::new(x_min, y_min), Point::new(x_max as i32, y_max as i32), @@ -83,34 +94,6 @@ impl<'ctx> AppState<'ctx> { p.x() < maxi.x() && p.y() < maxi.y() && p.x() >= mini.x() && p.y() >= mini.y() } - fn within_grid>(&self, p: P) -> bool { - let p = p.into(); - let (x, y) = (p.x(), p.y()); - x >= 0 && x < self.width as i32 && y >= 0 && y < self.height as i32 - } - - fn set_at>(&mut self, p: P, val: bool) -> Result { - let p: Point = p.into(); - if let Some((x, y)) = self.idx_at_coord(p) { - let old_val = self.data[(y * self.width + x) as usize]; - self.data[(y * self.width + x) as usize] = val; - return Ok(ModifyRecord::new((x as i32, y as i32), old_val, val)); - } - return Err(()); - } - - fn set_with_absolute>(&mut self, p: P, val: bool) -> Result { - let p: Point = p.into(); - let (x, y) = (p.x(), p.y()); - if self.within_grid(p) { - let idx = y as u32 * self.width + x as u32; - let old_val = self.data[idx as usize]; - self.data[idx as usize] = val; - return Ok(ModifyRecord::new((x as i32, y as i32), old_val, val)); - } - return Err(()); - } - fn toggle_grid(&mut self) { self.grid.enabled = !self.grid.enabled; } @@ -122,7 +105,14 @@ impl<'ctx> AppState<'ctx> { ) -> Result, ()> { let radius = self.brush_size; if radius == 1 { - return Ok(self.set_at(center, val).map(|x| vec![x])?); + let center_point: Point = center.into(); + return Ok(if let Some(pt) = self.idx_at_coord(center_point) { + let old_val = self.pixmap.set(pt, val); + Ok(ModifyRecord::new(pt, old_val, val)) + } else { + Err(()) + } + .map(|x| vec![x])?); } else { if let Some(center_on_grid) = self.idx_at_coord(center) { // center_on_grid is now a coordinate on the drawing grid @@ -158,16 +148,10 @@ impl<'ctx> AppState<'ctx> { } } } - dbg!(&circle); - for (x, y) in circle { - if self.within_grid((x as i32, y as i32)) { - let idx = y as u32 * self.width + x as u32; - old_vals.push(ModifyRecord::new( - (x as i32, y as i32), - self.data[idx as usize], - val, - )); - self.data[idx as usize] = val; + for circumference_pt in circle { + if let Ok(mp) = MapPoint::try_from(circumference_pt) { + let old_val = self.pixmap.set(mp, val); + old_vals.push(ModifyRecord::new((mp.x, mp.y), old_val, val)); } } return Ok(old_vals); @@ -176,27 +160,20 @@ impl<'ctx> AppState<'ctx> { return Err(()); } - fn draw_line>(&mut self, to: P) { - let to = to.into(); - let from = self.last_point.unwrap_or(to.into()); - } - - fn apply_operation(&mut self, op: Operation, op_kind: OpKind) -> Result<(), ()> { + fn apply_operation(&mut self, op: Operation, op_kind: OpKind) { for ModifyRecord { point, old_val, val, } in op.into_iter() { - self.set_with_absolute( - point, + if self.pixmap.is_inside(point) { match op_kind { - OpKind::Undo => old_val, - OpKind::Redo => val, - }, - )?; + OpKind::Undo => self.pixmap.set(point, old_val), + OpKind::Redo => self.pixmap.set(point, val), + }; + } } - Ok(()) } fn zoom_in(&mut self, p: (i32, i32)) { @@ -237,17 +214,18 @@ impl<'ctx> AppState<'ctx> { fn draw_grid(&mut self) { let cs = self.zoom as u32; + let (width, height) = (self.width(), self.height()); let canvas = &mut self.canvas; canvas.set_draw_color(self.grid.color); - for i in 0..=self.width { + for i in 0..=width { let x = (i * cs) as i32; - let y = (self.height * cs) as i32; + let y = (height * cs) as i32; let start = self.start + Point::new(x, 0); let end = self.start + Point::new(x, y); canvas.draw_line(start, end).unwrap(); } - for j in 0..=self.height { - let x = (self.width * cs) as i32; + for j in 0..=height { + let x = (width * cs) as i32; let y = (j * cs) as i32; let start = self.start + Point::new(0, y); let end = self.start + Point::new(x, y); @@ -257,20 +235,22 @@ impl<'ctx> AppState<'ctx> { fn draw(&mut self) { let cs = self.zoom as u32; + let (width, height) = (self.width(), self.height()); + let start = self.start; if self.grid.enabled { self.draw_grid(); } let canvas = &mut self.canvas; - for (idx, val) in self.data.iter().enumerate() { + for (idx, val) in self.pixmap.data.iter().enumerate() { if *val { let idx = idx as i32; - let (x, y) = (idx % self.width as i32, idx / self.height as i32); + let (x, y) = (idx % width as i32, idx / height as i32); canvas.set_draw_color(WHITE); canvas .fill_rect(Rect::new( // start drawing 1 pixel after the grid line - x * cs as i32 + self.start.x() + 1, - y * cs as i32 + self.start.y() + 1, + x * cs as i32 + start.x() + 1, + y * cs as i32 + start.y() + 1, // stop drawing 1 pixel before the grid line cs - 1, cs - 1, @@ -312,14 +292,12 @@ impl<'ctx> AppState<'ctx> { .map_err(|e| e.to_string()) .unwrap(); - let data = vec![false; (width * height) as usize]; + let pixmap = Pixmap::new_with(width, height, false); Self { start: Point::new(60, 60), - width, - height, - data, zoom: 5, brush_size: 1, + pixmap, grid: Grid::new(), canvas, context, @@ -425,14 +403,12 @@ impl<'ctx> AppState<'ctx> { } // end of operation Event::MouseButtonUp { .. } => self.modify(|e| { - dbg!(&e.current_operation.len()); let op = e .current_operation .drain(..) .filter(|v| !v.old_val == v.val) .collect::>(); e.undo_stack.push(op); - dbg!(&e.undo_stack); }), Event::Quit { .. } => { break 'running; diff --git a/src/main.rs b/src/main.rs index bf89508..cb39648 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod app; +mod bitmap; mod consts; mod undo; diff --git a/src/undo.rs b/src/undo.rs index 2249fe7..b590312 100644 --- a/src/undo.rs +++ b/src/undo.rs @@ -1,12 +1,12 @@ #[derive(Copy, Clone, Debug)] pub struct ModifyRecord { - pub point: (i32, i32), + pub point: (u32, u32), pub old_val: bool, pub val: bool, } impl ModifyRecord { - pub fn new(point: (i32, i32), old_val: bool, val: bool) -> Self { + pub fn new(point: (u32, u32), old_val: bool, val: bool) -> Self { ModifyRecord { point, old_val, -- cgit v1.2.3