aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-04-04 11:12:36 +0100
committerAkshay <[email protected]>2021-04-04 14:07:09 +0100
commit931d256d62a1a20c8ba8a8b6726fb1d7167f1d68 (patch)
tree54026c8b3be8fc1c40caff868ceed98ac7cfcc90
parentc4354e2d8d51cc9fc12dce9ad2d5736e400a8de4 (diff)
speed up pixmap drawing!
-rw-r--r--src/app.rs73
-rw-r--r--src/utils.rs33
2 files changed, 79 insertions, 27 deletions
diff --git a/src/app.rs b/src/app.rs
index 243b196..56fcac7 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -507,55 +507,74 @@ impl<'ctx> AppState<'ctx> {
507 } 507 }
508 } 508 }
509 509
510 fn draw_symmetry(&mut self) { 510 fn draw_line_to_grid(&mut self, line: u32, axis: Axis, color: Color) {
511 let (winsize_x, winsize_y) = self.canvas.window().size(); 511 let (winsize_x, winsize_y) = self.canvas.window().size();
512 let cs = self.zoom as u32; 512 let cs = self.zoom as u32;
513 let Symmetry { x: sym_x, y: sym_y } = self.symmetry; 513 let offset = (line * cs) + (cs / 2);
514 if let Some(line) = sym_x { 514 self.canvas.set_draw_color(color);
515 self.canvas.set_draw_color(CYAN); 515 match axis {
516 let line_coord = (line * cs) as i32 + self.start.y() + (cs / 2) as i32; 516 Axis::X => {
517 self.canvas 517 let line_coord = offset as i32 + self.start.y();
518 .draw_line((0, line_coord), (winsize_x as i32, line_coord)) 518 self.canvas
519 .unwrap(); 519 .draw_line((0, line_coord), (winsize_x as i32, line_coord))
520 .unwrap();
521 }
522 Axis::Y => {
523 let line_coord = offset as i32 + self.start.x();
524 self.canvas
525 .draw_line((line_coord, 0), (line_coord, winsize_y as i32))
526 .unwrap();
527 }
520 } 528 }
521 if let Some(line) = sym_y { 529 }
522 self.canvas.set_draw_color(CYAN); 530
523 let line_coord = (line * cs) as i32 + self.start.x() + (cs / 2) as i32; 531 fn draw_symmetry(&mut self) {
524 self.canvas 532 let Symmetry { x, y } = self.symmetry;
525 .draw_line((line_coord, 0), (line_coord, winsize_y as i32)) 533 x.and_then(|line| {
526 .unwrap(); 534 self.draw_line_to_grid(line, Axis::X, CYAN);
535 Some(())
536 });
537 y.and_then(|line| {
538 self.draw_line_to_grid(line, Axis::Y, CYAN);
539 Some(())
540 });
541 }
542
543 fn draw_guides(&mut self) {
544 // do this without clone
545 for (Guide { offset, axis }, enabled) in self.guides.clone() {
546 if enabled {
547 self.draw_line_to_grid(offset, axis, PINK);
548 }
527 } 549 }
528 } 550 }
529 551
530 fn draw(&mut self) { 552 fn draw(&mut self) {
531 let cs = self.zoom as u32; 553 let cs = self.zoom as u32;
532 let (width, height) = (self.width(), self.height()); 554 let (width, _) = (self.width(), self.height());
533 let start = self.start; 555 let start = self.start;
534 let grid_enabled = self.grid.enabled; 556 let grid_enabled = self.grid.enabled;
535 self.canvas.set_draw_color(WHITE); 557 self.canvas.set_draw_color(WHITE);
536 for x in 0..width { 558 for (line_nr, scan) in self.pixmap.data[..].chunks(width as usize).enumerate() {
537 for y in 0..height { 559 let mut pass = 0usize;
538 if self.pixmap.get(MapPoint { x, y }) { 560 for (color, length) in utils::compress(scan) {
561 if color {
539 self.canvas 562 self.canvas
540 .fill_rect(Rect::new( 563 .fill_rect(Rect::new(
541 (x * cs) as i32 + start.x(), 564 (pass as u32 * cs) as i32 + start.x(),
542 (y * cs) as i32 + start.y(), 565 (line_nr as u32 * cs) as i32 + start.y(),
543 cs, 566 cs * length as u32,
544 cs, 567 cs,
545 )) 568 ))
546 .unwrap(); 569 .unwrap();
547 } 570 }
571 pass += length;
548 } 572 }
549 } 573 }
550 // for (idx, val) in self.pixmap.data.iter().enumerate() {
551 // if *val {
552 // let idx = idx as i32;
553 // let (x, y) = (idx % width as i32, idx / height as i32);
554 // }
555 // }
556 if grid_enabled { 574 if grid_enabled {
557 self.draw_grid(); 575 self.draw_grid();
558 } 576 }
577 self.draw_guides();
559 self.draw_symmetry(); 578 self.draw_symmetry();
560 self.draw_statusline(); 579 self.draw_statusline();
561 self.draw_command_box(); 580 self.draw_command_box();
diff --git a/src/utils.rs b/src/utils.rs
index bee5782..ab446f4 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -108,3 +108,36 @@ pub fn load_file<P: AsRef<Path>>(path: P) -> Result<Image, io::Error> {
108 image.read_to_end(&mut buf)?; 108 image.read_to_end(&mut buf)?;
109 Ok(Image::decode(&mut (Cursor::new(buf))).unwrap()) // TODO: obi error 109 Ok(Image::decode(&mut (Cursor::new(buf))).unwrap()) // TODO: obi error
110} 110}
111
112pub fn compress<T: PartialEq + Clone>(scanline: &[T]) -> Vec<(T, usize)> {
113 let mut runs = vec![];
114 if scanline.is_empty() {
115 return runs;
116 }
117 let mut idx = 0;
118 loop {
119 let first = &scanline[idx];
120 let run_length = scanline[idx..]
121 .iter()
122 .take_while(|&item| item == first)
123 .count();
124
125 runs.push((first.clone(), run_length));
126
127 idx += run_length;
128 if idx > scanline.len() - 1 {
129 break;
130 }
131 }
132 runs
133}
134
135#[cfg(test)]
136mod tests {
137 use super::compress;
138 #[test]
139 fn compression() {
140 let sl = [1, 1, 1, 2, 2, 2];
141 assert_eq!(compress(&sl), vec![(1, 3), (2, 3)]);
142 }
143}