aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-03-13 07:45:48 +0000
committerAkshay <[email protected]>2021-03-13 07:45:48 +0000
commit4b4ebe84d2cfbb8b0ddf7b678c5fe4cff53e5089 (patch)
treec04174ca126041760a95075a7e3a33928b7b220b
parentf1d0fd346bd3607c89307ad801d1f12b582f661a (diff)
refactor to use pixmap over Vec<bool>
-rw-r--r--src/app.rs120
-rw-r--r--src/main.rs1
-rw-r--r--src/undo.rs4
3 files changed, 51 insertions, 74 deletions
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 @@
1use crate::undo::{ModifyRecord, OpKind, Operation, UndoStack}; 1use crate::{
2 bitmap::{MapPoint, Pixmap},
3 undo::{ModifyRecord, OpKind, Operation, UndoStack},
4};
5
6use std::convert::{From, TryFrom};
2 7
3use sdl2::{ 8use sdl2::{
4 event::Event, 9 event::Event,
@@ -15,9 +20,7 @@ use crate::consts::{BLACK, GRID_COLOR, WHITE};
15 20
16pub struct AppState<'ctx> { 21pub struct AppState<'ctx> {
17 start: Point, 22 start: Point,
18 width: u32, 23 pixmap: Pixmap<bool>,
19 height: u32,
20 data: Vec<bool>,
21 zoom: u8, 24 zoom: u8,
22 brush_size: u8, 25 brush_size: u8,
23 grid: Grid, 26 grid: Grid,
@@ -49,11 +52,19 @@ impl<'ctx> AppState<'ctx> {
49 self.start += direction.into(); 52 self.start += direction.into();
50 } 53 }
51 54
55 fn width(&self) -> u32 {
56 self.pixmap.width
57 }
58
59 fn height(&self) -> u32 {
60 self.pixmap.height
61 }
62
52 fn bounds(&self) -> (Point, Point) { 63 fn bounds(&self) -> (Point, Point) {
53 let x_min = self.start.x(); 64 let x_min = self.start.x();
54 let y_min = self.start.y(); 65 let y_min = self.start.y();
55 let x_max = self.start.x() + (self.width * self.zoom as u32) as i32; 66 let x_max = self.start.x() + (self.width() * self.zoom as u32) as i32;
56 let y_max = self.start.y() + (self.height * self.zoom as u32) as i32; 67 let y_max = self.start.y() + (self.height() * self.zoom as u32) as i32;
57 return ( 68 return (
58 Point::new(x_min, y_min), 69 Point::new(x_min, y_min),
59 Point::new(x_max as i32, y_max as i32), 70 Point::new(x_max as i32, y_max as i32),
@@ -83,34 +94,6 @@ impl<'ctx> AppState<'ctx> {
83 p.x() < maxi.x() && p.y() < maxi.y() && p.x() >= mini.x() && p.y() >= mini.y() 94 p.x() < maxi.x() && p.y() < maxi.y() && p.x() >= mini.x() && p.y() >= mini.y()
84 } 95 }
85 96
86 fn within_grid<P: Into<Point>>(&self, p: P) -> bool {
87 let p = p.into();
88 let (x, y) = (p.x(), p.y());
89 x >= 0 && x < self.width as i32 && y >= 0 && y < self.height as i32
90 }
91
92 fn set_at<P: Into<Point>>(&mut self, p: P, val: bool) -> Result<ModifyRecord, ()> {
93 let p: Point = p.into();
94 if let Some((x, y)) = self.idx_at_coord(p) {
95 let old_val = self.data[(y * self.width + x) as usize];
96 self.data[(y * self.width + x) as usize] = val;
97 return Ok(ModifyRecord::new((x as i32, y as i32), old_val, val));
98 }
99 return Err(());
100 }
101
102 fn set_with_absolute<P: Into<Point>>(&mut self, p: P, val: bool) -> Result<ModifyRecord, ()> {
103 let p: Point = p.into();
104 let (x, y) = (p.x(), p.y());
105 if self.within_grid(p) {
106 let idx = y as u32 * self.width + x as u32;
107 let old_val = self.data[idx as usize];
108 self.data[idx as usize] = val;
109 return Ok(ModifyRecord::new((x as i32, y as i32), old_val, val));
110 }
111 return Err(());
112 }
113
114 fn toggle_grid(&mut self) { 97 fn toggle_grid(&mut self) {
115 self.grid.enabled = !self.grid.enabled; 98 self.grid.enabled = !self.grid.enabled;
116 } 99 }
@@ -122,7 +105,14 @@ impl<'ctx> AppState<'ctx> {
122 ) -> Result<Vec<ModifyRecord>, ()> { 105 ) -> Result<Vec<ModifyRecord>, ()> {
123 let radius = self.brush_size; 106 let radius = self.brush_size;
124 if radius == 1 { 107 if radius == 1 {
125 return Ok(self.set_at(center, val).map(|x| vec![x])?); 108 let center_point: Point = center.into();
109 return Ok(if let Some(pt) = self.idx_at_coord(center_point) {
110 let old_val = self.pixmap.set(pt, val);
111 Ok(ModifyRecord::new(pt, old_val, val))
112 } else {
113 Err(())
114 }
115 .map(|x| vec![x])?);
126 } else { 116 } else {
127 if let Some(center_on_grid) = self.idx_at_coord(center) { 117 if let Some(center_on_grid) = self.idx_at_coord(center) {
128 // center_on_grid is now a coordinate on the drawing grid 118 // center_on_grid is now a coordinate on the drawing grid
@@ -158,16 +148,10 @@ impl<'ctx> AppState<'ctx> {
158 } 148 }
159 } 149 }
160 } 150 }
161 dbg!(&circle); 151 for circumference_pt in circle {
162 for (x, y) in circle { 152 if let Ok(mp) = MapPoint::try_from(circumference_pt) {
163 if self.within_grid((x as i32, y as i32)) { 153 let old_val = self.pixmap.set(mp, val);
164 let idx = y as u32 * self.width + x as u32; 154 old_vals.push(ModifyRecord::new((mp.x, mp.y), old_val, val));
165 old_vals.push(ModifyRecord::new(
166 (x as i32, y as i32),
167 self.data[idx as usize],
168 val,
169 ));
170 self.data[idx as usize] = val;
171 } 155 }
172 } 156 }
173 return Ok(old_vals); 157 return Ok(old_vals);
@@ -176,27 +160,20 @@ impl<'ctx> AppState<'ctx> {
176 return Err(()); 160 return Err(());
177 } 161 }
178 162
179 fn draw_line<P: Into<Point>>(&mut self, to: P) { 163 fn apply_operation(&mut self, op: Operation, op_kind: OpKind) {
180 let to = to.into();
181 let from = self.last_point.unwrap_or(to.into());
182 }
183
184 fn apply_operation(&mut self, op: Operation, op_kind: OpKind) -> Result<(), ()> {
185 for ModifyRecord { 164 for ModifyRecord {
186 point, 165 point,
187 old_val, 166 old_val,
188 val, 167 val,
189 } in op.into_iter() 168 } in op.into_iter()
190 { 169 {
191 self.set_with_absolute( 170 if self.pixmap.is_inside(point) {
192 point,
193 match op_kind { 171 match op_kind {
194 OpKind::Undo => old_val, 172 OpKind::Undo => self.pixmap.set(point, old_val),
195 OpKind::Redo => val, 173 OpKind::Redo => self.pixmap.set(point, val),
196 }, 174 };
197 )?; 175 }
198 } 176 }
199 Ok(())
200 } 177 }
201 178
202 fn zoom_in(&mut self, p: (i32, i32)) { 179 fn zoom_in(&mut self, p: (i32, i32)) {
@@ -237,17 +214,18 @@ impl<'ctx> AppState<'ctx> {
237 214
238 fn draw_grid(&mut self) { 215 fn draw_grid(&mut self) {
239 let cs = self.zoom as u32; 216 let cs = self.zoom as u32;
217 let (width, height) = (self.width(), self.height());
240 let canvas = &mut self.canvas; 218 let canvas = &mut self.canvas;
241 canvas.set_draw_color(self.grid.color); 219 canvas.set_draw_color(self.grid.color);
242 for i in 0..=self.width { 220 for i in 0..=width {
243 let x = (i * cs) as i32; 221 let x = (i * cs) as i32;
244 let y = (self.height * cs) as i32; 222 let y = (height * cs) as i32;
245 let start = self.start + Point::new(x, 0); 223 let start = self.start + Point::new(x, 0);
246 let end = self.start + Point::new(x, y); 224 let end = self.start + Point::new(x, y);
247 canvas.draw_line(start, end).unwrap(); 225 canvas.draw_line(start, end).unwrap();
248 } 226 }
249 for j in 0..=self.height { 227 for j in 0..=height {
250 let x = (self.width * cs) as i32; 228 let x = (width * cs) as i32;
251 let y = (j * cs) as i32; 229 let y = (j * cs) as i32;
252 let start = self.start + Point::new(0, y); 230 let start = self.start + Point::new(0, y);
253 let end = self.start + Point::new(x, y); 231 let end = self.start + Point::new(x, y);
@@ -257,20 +235,22 @@ impl<'ctx> AppState<'ctx> {
257 235
258 fn draw(&mut self) { 236 fn draw(&mut self) {
259 let cs = self.zoom as u32; 237 let cs = self.zoom as u32;
238 let (width, height) = (self.width(), self.height());
239 let start = self.start;
260 if self.grid.enabled { 240 if self.grid.enabled {
261 self.draw_grid(); 241 self.draw_grid();
262 } 242 }
263 let canvas = &mut self.canvas; 243 let canvas = &mut self.canvas;
264 for (idx, val) in self.data.iter().enumerate() { 244 for (idx, val) in self.pixmap.data.iter().enumerate() {
265 if *val { 245 if *val {
266 let idx = idx as i32; 246 let idx = idx as i32;
267 let (x, y) = (idx % self.width as i32, idx / self.height as i32); 247 let (x, y) = (idx % width as i32, idx / height as i32);
268 canvas.set_draw_color(WHITE); 248 canvas.set_draw_color(WHITE);
269 canvas 249 canvas
270 .fill_rect(Rect::new( 250 .fill_rect(Rect::new(
271 // start drawing 1 pixel after the grid line 251 // start drawing 1 pixel after the grid line
272 x * cs as i32 + self.start.x() + 1, 252 x * cs as i32 + start.x() + 1,
273 y * cs as i32 + self.start.y() + 1, 253 y * cs as i32 + start.y() + 1,
274 // stop drawing 1 pixel before the grid line 254 // stop drawing 1 pixel before the grid line
275 cs - 1, 255 cs - 1,
276 cs - 1, 256 cs - 1,
@@ -312,14 +292,12 @@ impl<'ctx> AppState<'ctx> {
312 .map_err(|e| e.to_string()) 292 .map_err(|e| e.to_string())
313 .unwrap(); 293 .unwrap();
314 294
315 let data = vec![false; (width * height) as usize]; 295 let pixmap = Pixmap::new_with(width, height, false);
316 Self { 296 Self {
317 start: Point::new(60, 60), 297 start: Point::new(60, 60),
318 width,
319 height,
320 data,
321 zoom: 5, 298 zoom: 5,
322 brush_size: 1, 299 brush_size: 1,
300 pixmap,
323 grid: Grid::new(), 301 grid: Grid::new(),
324 canvas, 302 canvas,
325 context, 303 context,
@@ -425,14 +403,12 @@ impl<'ctx> AppState<'ctx> {
425 } 403 }
426 // end of operation 404 // end of operation
427 Event::MouseButtonUp { .. } => self.modify(|e| { 405 Event::MouseButtonUp { .. } => self.modify(|e| {
428 dbg!(&e.current_operation.len());
429 let op = e 406 let op = e
430 .current_operation 407 .current_operation
431 .drain(..) 408 .drain(..)
432 .filter(|v| !v.old_val == v.val) 409 .filter(|v| !v.old_val == v.val)
433 .collect::<Vec<_>>(); 410 .collect::<Vec<_>>();
434 e.undo_stack.push(op); 411 e.undo_stack.push(op);
435 dbg!(&e.undo_stack);
436 }), 412 }),
437 Event::Quit { .. } => { 413 Event::Quit { .. } => {
438 break 'running; 414 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 @@
1mod app; 1mod app;
2mod bitmap;
2mod consts; 3mod consts;
3mod undo; 4mod undo;
4 5
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 @@
1#[derive(Copy, Clone, Debug)] 1#[derive(Copy, Clone, Debug)]
2pub struct ModifyRecord { 2pub struct ModifyRecord {
3 pub point: (i32, i32), 3 pub point: (u32, u32),
4 pub old_val: bool, 4 pub old_val: bool,
5 pub val: bool, 5 pub val: bool,
6} 6}
7 7
8impl ModifyRecord { 8impl ModifyRecord {
9 pub fn new(point: (i32, i32), old_val: bool, val: bool) -> Self { 9 pub fn new(point: (u32, u32), old_val: bool, val: bool) -> Self {
10 ModifyRecord { 10 ModifyRecord {
11 point, 11 point,
12 old_val, 12 old_val,