diff options
author | Akshay <[email protected]> | 2021-04-04 11:12:36 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2021-04-04 14:07:09 +0100 |
commit | 931d256d62a1a20c8ba8a8b6726fb1d7167f1d68 (patch) | |
tree | 54026c8b3be8fc1c40caff868ceed98ac7cfcc90 | |
parent | c4354e2d8d51cc9fc12dce9ad2d5736e400a8de4 (diff) |
speed up pixmap drawing!
-rw-r--r-- | src/app.rs | 73 | ||||
-rw-r--r-- | src/utils.rs | 33 |
2 files changed, 79 insertions, 27 deletions
@@ -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 | |||
112 | pub 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)] | ||
136 | mod 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 | } | ||