From 543556bdbe3a2161f3e7701096c9f47a48c54d70 Mon Sep 17 00:00:00 2001 From: Jon Valdes Date: Sat, 1 Feb 2020 21:51:19 +0100 Subject: [PATCH 1/3] Different implementation of scroll_region, which avoids allocations and temporary copies of scrolled data --- src/editor/mod.rs | 53 ++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 3504eba..7cc0513 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -204,48 +204,35 @@ impl Editor { } fn scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64, rows: i64, cols: i64) { - let (top, bot) = if rows > 0 { - (top as i64 + rows, bot as i64) - } else if rows < 0 { - (top as i64, bot as i64 + rows) + let (mut y, end_y, step_y) = if rows > 0 { + (top as i64 + rows, bot as i64, 1) } else { - (top as i64, bot as i64) + (bot as i64 + rows - 1, top as i64 - 1, -1) }; - let (left, right) = if cols > 0 { - (left as i64 + cols, right as i64) - } else if rows < 0 { - (left as i64, right as i64 + cols) + let (start_x, end_x, step_x) = if cols > 0 { + (left as i64 + cols, right as i64, 1) } else { - (left as i64, right as i64) + (right as i64 + cols - 1, left as i64 - 1, -1) }; - let mut region = Vec::new(); - for y in top..bot { - let row = &self.grid[y as usize]; - let mut copied_section = Vec::new(); - for x in left..right { - copied_section.push(row[x as usize].clone()); - } - region.push(copied_section); - } - - let new_top = top as i64 - rows; - let new_left = left as i64 - cols; - - for (y, row_section) in region.into_iter().enumerate() { - for (x, cell) in row_section.into_iter().enumerate() { - let y = new_top + y as i64; - if y >= 0 && y < self.grid.len() as i64 { - let row = &mut self.grid[y as usize]; - let dirty_row = &mut self.dirty[y as usize]; - let x = new_left + x as i64; - if x >= 0 && x < row.len() as i64 { - row[x as usize] = cell; - dirty_row[x as usize] = true; + while y != end_y { + let dest_y = y - rows; + if dest_y >= 0 && dest_y < self.size.1 as i64 { + let mut x = start_x; + while x != end_x { + let dest_x = x - cols; + if dest_x >= 0 && dest_x < self.size.0 as i64 { + let cell = std::mem::replace(&mut self.grid[y as usize][x as usize], None); + self.grid[dest_y as usize][dest_x as usize] = cell; + self.dirty[dest_y as usize][dest_x as usize] = true; + self.dirty[y as usize][x as usize] = true; } + x += step_x; } } + + y += step_y; } } From 2d7239c0e2cc08cb3102763958356f027bbae525 Mon Sep 17 00:00:00 2001 From: Jon Valdes Date: Sun, 2 Feb 2020 11:21:10 +0100 Subject: [PATCH 2/3] Do not clear scrolled-off area, destructure width and height --- src/editor/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 7cc0513..0f5a7e0 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -216,17 +216,19 @@ impl Editor { (right as i64 + cols - 1, left as i64 - 1, -1) }; + let grid_width = self.size.0; + let grid_height = self.size.1; + while y != end_y { let dest_y = y - rows; - if dest_y >= 0 && dest_y < self.size.1 as i64 { + if dest_y >= 0 && dest_y < grid_height as i64 { let mut x = start_x; while x != end_x { let dest_x = x - cols; - if dest_x >= 0 && dest_x < self.size.0 as i64 { - let cell = std::mem::replace(&mut self.grid[y as usize][x as usize], None); + if dest_x >= 0 && dest_x < grid_width as i64 { + let cell = self.grid[y as usize][x as usize].clone(); self.grid[dest_y as usize][dest_x as usize] = cell; self.dirty[dest_y as usize][dest_x as usize] = true; - self.dirty[y as usize][x as usize] = true; } x += step_x; } From 2a14d26f1e0ac70dc2843751627a84104a0d8a81 Mon Sep 17 00:00:00 2001 From: Jon Valdes Date: Sun, 2 Feb 2020 18:10:40 +0100 Subject: [PATCH 3/3] Using iterators and for loops instead of explicit while loops --- src/editor/mod.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 0f5a7e0..9ded483 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -204,37 +204,35 @@ impl Editor { } fn scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64, rows: i64, cols: i64) { - let (mut y, end_y, step_y) = if rows > 0 { - (top as i64 + rows, bot as i64, 1) - } else { - (bot as i64 + rows - 1, top as i64 - 1, -1) - }; - let (start_x, end_x, step_x) = if cols > 0 { - (left as i64 + cols, right as i64, 1) + let y_iter : Box> = if rows > 0 { + Box::new((top as i64 + rows).. bot as i64) } else { - (right as i64 + cols - 1, left as i64 - 1, -1) + Box::new((top as i64 .. (bot as i64 + rows)).rev()) }; let grid_width = self.size.0; let grid_height = self.size.1; - while y != end_y { + for y in y_iter { let dest_y = y - rows; if dest_y >= 0 && dest_y < grid_height as i64 { - let mut x = start_x; - while x != end_x { + + let x_iter : Box> = if cols > 0 { + Box::new((left as i64 + cols) .. right as i64) + } else { + Box::new((left as i64 .. (right as i64 + cols)).rev()) + }; + + for x in x_iter { let dest_x = x - cols; if dest_x >= 0 && dest_x < grid_width as i64 { let cell = self.grid[y as usize][x as usize].clone(); self.grid[dest_y as usize][dest_x as usize] = cell; self.dirty[dest_y as usize][dest_x as usize] = true; } - x += step_x; } } - - y += step_y; } }