aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-04-02 08:06:30 +0100
committerAkshay <[email protected]>2021-04-02 08:06:30 +0100
commit2b89b786a97b788ef8063b2777c6bc65a207033f (patch)
tree917d9de86f2a958052b8f3323b7b66562057b77b
parent11eb57ceb22636fafbb1f1c1a49dda3956e6f7e4 (diff)
fix rare index error, more functional flood fill algo
-rw-r--r--src/app.rs41
-rw-r--r--src/bitmap.rs39
2 files changed, 46 insertions, 34 deletions
diff --git a/src/app.rs b/src/app.rs
index 84869a3..725a45a 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -176,8 +176,10 @@ impl<'ctx> AppState<'ctx> {
176 .chain(sym_circle) 176 .chain(sym_circle)
177 .filter(|&pt| dither::bayer(dither_level, pt)) 177 .filter(|&pt| dither::bayer(dither_level, pt))
178 { 178 {
179 let old_val = self.pixmap.set(point, val); 179 if self.pixmap.contains(point) {
180 modify_record.push(PaintRecord::new(point, old_val, val)); 180 let old_val = self.pixmap.set(point, val);
181 modify_record.push(PaintRecord::new(point, old_val, val));
182 }
181 } 183 }
182 Ok(modify_record) 184 Ok(modify_record)
183 } 185 }
@@ -203,8 +205,10 @@ impl<'ctx> AppState<'ctx> {
203 .into_iter() 205 .into_iter()
204 .filter(|&pt| dither::bayer(dither_level, pt)) 206 .filter(|&pt| dither::bayer(dither_level, pt))
205 { 207 {
206 let old_val = self.pixmap.set(c, val); 208 if self.pixmap.contains(c) {
207 line_modify_record.push(PaintRecord::new(c, old_val, val)); 209 let old_val = self.pixmap.set(c, val);
210 line_modify_record.push(PaintRecord::new(c, old_val, val));
211 }
208 } 212 }
209 } 213 }
210 Ok(line_modify_record) 214 Ok(line_modify_record)
@@ -353,9 +357,11 @@ impl<'ctx> AppState<'ctx> {
353 container.place(&mut padding_box, HorAlign::Right, VertAlign::Center); 357 container.place(&mut padding_box, HorAlign::Right, VertAlign::Center);
354 padding_box.place(&mut primary, HorAlign::Center, VertAlign::Center); 358 padding_box.place(&mut primary, HorAlign::Center, VertAlign::Center);
355 359
356 self.canvas.set_draw_color(if !self.active_color { WHITE } else { BLACK }); 360 self.canvas
361 .set_draw_color(if !self.active_color { WHITE } else { BLACK });
357 self.canvas.fill_rect(primary.area()).unwrap(); 362 self.canvas.fill_rect(primary.area()).unwrap();
358 self.canvas.set_draw_color(if self.active_color { WHITE } else { BLACK }); 363 self.canvas
364 .set_draw_color(if self.active_color { WHITE } else { BLACK });
359 365
360 let brush_box = (0..8) 366 let brush_box = (0..8)
361 .map(|x| (0..8).map(|y| (x, y).into()).collect::<Vec<MapPoint>>()) 367 .map(|x| (0..8).map(|y| (x, y).into()).collect::<Vec<MapPoint>>())
@@ -364,9 +370,11 @@ impl<'ctx> AppState<'ctx> {
364 .collect::<Vec<_>>(); 370 .collect::<Vec<_>>();
365 371
366 for pt in brush_box { 372 for pt in brush_box {
367 let canvas_pt = Point::from(primary.start) 373 let canvas_pt =
368 + Point::from((pt.x as i32 * 2, pt.y as i32 * 2)); 374 Point::from(primary.start) + Point::from((pt.x as i32 * 2, pt.y as i32 * 2));
369 self.canvas.fill_rect(rect!(canvas_pt.x(), canvas_pt.y(), 2, 2)).unwrap(); 375 self.canvas
376 .fill_rect(rect!(canvas_pt.x(), canvas_pt.y(), 2, 2))
377 .unwrap();
370 } 378 }
371 379
372 let mouse_coords = if let Some((x, y)) = self.idx_at_coord(self.mouse) { 380 let mouse_coords = if let Some((x, y)) = self.idx_at_coord(self.mouse) {
@@ -735,20 +743,19 @@ impl<'ctx> AppState<'ctx> {
735 Brush::Fill => { 743 Brush::Fill => {
736 if let Some(c) = contact { 744 if let Some(c) = contact {
737 let target = self.pixmap.get(c); 745 let target = self.pixmap.get(c);
738 let mut operation = vec![]; 746 let replacement = self.active_color;
739 self.pixmap.flood_fill( 747 let operation =
740 c, 748 self.pixmap.flood_fill(c, target, replacement);
741 target, 749 for o in operation.iter() {
742 self.active_color, 750 self.pixmap.set(o.clone(), replacement);
743 &mut operation, 751 }
744 );
745 self.current_operation.extend( 752 self.current_operation.extend(
746 operation 753 operation
747 .into_iter() 754 .into_iter()
748 .map(|point| PaintRecord { 755 .map(|point| PaintRecord {
749 point, 756 point,
750 old: target, 757 old: target,
751 new: self.active_color, 758 new: replacement,
752 }) 759 })
753 .collect::<Vec<PaintRecord>>(), 760 .collect::<Vec<PaintRecord>>(),
754 ) 761 )
diff --git a/src/bitmap.rs b/src/bitmap.rs
index dc66d73..6aa6b12 100644
--- a/src/bitmap.rs
+++ b/src/bitmap.rs
@@ -1,4 +1,5 @@
1use std::{ 1use std::{
2 collections::HashSet,
2 convert::{From, Into, TryFrom}, 3 convert::{From, Into, TryFrom},
3 ops::{Add, Sub}, 4 ops::{Add, Sub},
4}; 5};
@@ -10,7 +11,7 @@ pub struct Pixmap<T> {
10 pub data: Vec<T>, 11 pub data: Vec<T>,
11} 12}
12 13
13#[derive(Copy, Clone, Debug)] 14#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
14pub struct MapPoint { 15pub struct MapPoint {
15 pub x: u32, 16 pub x: u32,
16 pub y: u32, 17 pub y: u32,
@@ -249,22 +250,26 @@ where
249 .collect() 250 .collect()
250 } 251 }
251 252
252 pub fn flood_fill( 253 pub fn flood_fill(&mut self, start: MapPoint, target: T, replacement: T) -> Vec<MapPoint> {
253 &mut self, 254 let mut queue = vec![start];
254 start: MapPoint, 255 let mut area = HashSet::new();
255 target: T, 256 loop {
256 replacement: T, 257 if queue.is_empty() {
257 pts: &mut Vec<MapPoint>, 258 break area.drain().collect();
258 ) { 259 } else {
259 if !self.contains(start) || self.get(start) != target || self.get(start) == replacement { 260 let last = queue.pop().unwrap();
260 return; 261 area.insert(last);
261 } else { 262 for (x, y) in [(1, 0), (0, 1), (-1, 0), (0, -1)].iter() {
262 pts.push(start); 263 let dir = MapPoint::try_from((last.x as i64 + x, last.y as i64 + y));
263 self.set(start, replacement); 264 if let Ok(pt) = dir {
264 for (x, y) in [(1, 0), (0, 1), (-1, 0), (0, -1)].iter() { 265 if self.contains(pt)
265 let dir = MapPoint::try_from((start.x as i64 - x, start.y as i64 + y)); 266 && self.get(pt) == target
266 if let Ok(pt) = dir { 267 && self.get(pt) != replacement
267 self.flood_fill(pt, target, replacement, pts); 268 && !area.contains(&pt)
269 {
270 queue.push(pt);
271 }
272 }
268 } 273 }
269 } 274 }
270 } 275 }