From 931d256d62a1a20c8ba8a8b6726fb1d7167f1d68 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 4 Apr 2021 15:42:36 +0530 Subject: speed up pixmap drawing! --- src/app.rs | 73 ++++++++++++++++++++++++++++++++++++++---------------------- src/utils.rs | 33 +++++++++++++++++++++++++++ 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> { } } - fn draw_symmetry(&mut self) { + fn draw_line_to_grid(&mut self, line: u32, axis: Axis, color: Color) { let (winsize_x, winsize_y) = self.canvas.window().size(); let cs = self.zoom as u32; - let Symmetry { x: sym_x, y: sym_y } = self.symmetry; - if let Some(line) = sym_x { - self.canvas.set_draw_color(CYAN); - let line_coord = (line * cs) as i32 + self.start.y() + (cs / 2) as i32; - self.canvas - .draw_line((0, line_coord), (winsize_x as i32, line_coord)) - .unwrap(); + let offset = (line * cs) + (cs / 2); + self.canvas.set_draw_color(color); + match axis { + Axis::X => { + let line_coord = offset as i32 + self.start.y(); + self.canvas + .draw_line((0, line_coord), (winsize_x as i32, line_coord)) + .unwrap(); + } + Axis::Y => { + let line_coord = offset as i32 + self.start.x(); + self.canvas + .draw_line((line_coord, 0), (line_coord, winsize_y as i32)) + .unwrap(); + } } - if let Some(line) = sym_y { - self.canvas.set_draw_color(CYAN); - let line_coord = (line * cs) as i32 + self.start.x() + (cs / 2) as i32; - self.canvas - .draw_line((line_coord, 0), (line_coord, winsize_y as i32)) - .unwrap(); + } + + fn draw_symmetry(&mut self) { + let Symmetry { x, y } = self.symmetry; + x.and_then(|line| { + self.draw_line_to_grid(line, Axis::X, CYAN); + Some(()) + }); + y.and_then(|line| { + self.draw_line_to_grid(line, Axis::Y, CYAN); + Some(()) + }); + } + + fn draw_guides(&mut self) { + // do this without clone + for (Guide { offset, axis }, enabled) in self.guides.clone() { + if enabled { + self.draw_line_to_grid(offset, axis, PINK); + } } } fn draw(&mut self) { let cs = self.zoom as u32; - let (width, height) = (self.width(), self.height()); + let (width, _) = (self.width(), self.height()); let start = self.start; let grid_enabled = self.grid.enabled; self.canvas.set_draw_color(WHITE); - for x in 0..width { - for y in 0..height { - if self.pixmap.get(MapPoint { x, y }) { + for (line_nr, scan) in self.pixmap.data[..].chunks(width as usize).enumerate() { + let mut pass = 0usize; + for (color, length) in utils::compress(scan) { + if color { self.canvas .fill_rect(Rect::new( - (x * cs) as i32 + start.x(), - (y * cs) as i32 + start.y(), - cs, + (pass as u32 * cs) as i32 + start.x(), + (line_nr as u32 * cs) as i32 + start.y(), + cs * length as u32, cs, )) .unwrap(); } + pass += length; } } - // for (idx, val) in self.pixmap.data.iter().enumerate() { - // if *val { - // let idx = idx as i32; - // let (x, y) = (idx % width as i32, idx / height as i32); - // } - // } if grid_enabled { self.draw_grid(); } + self.draw_guides(); self.draw_symmetry(); self.draw_statusline(); 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>(path: P) -> Result { image.read_to_end(&mut buf)?; Ok(Image::decode(&mut (Cursor::new(buf))).unwrap()) // TODO: obi error } + +pub fn compress(scanline: &[T]) -> Vec<(T, usize)> { + let mut runs = vec![]; + if scanline.is_empty() { + return runs; + } + let mut idx = 0; + loop { + let first = &scanline[idx]; + let run_length = scanline[idx..] + .iter() + .take_while(|&item| item == first) + .count(); + + runs.push((first.clone(), run_length)); + + idx += run_length; + if idx > scanline.len() - 1 { + break; + } + } + runs +} + +#[cfg(test)] +mod tests { + use super::compress; + #[test] + fn compression() { + let sl = [1, 1, 1, 2, 2, 2]; + assert_eq!(compress(&sl), vec![(1, 3), (2, 3)]); + } +} -- cgit v1.2.3