From b04c0e6e97765aeb888479c5e0bc27d54de60659 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 10 Nov 2019 04:51:22 -0500 Subject: optimize cursor movement a bit --- src/row.rs | 171 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 49 deletions(-) (limited to 'src/row.rs') diff --git a/src/row.rs b/src/row.rs index 8008212..f7d4485 100644 --- a/src/row.rs +++ b/src/row.rs @@ -15,6 +15,10 @@ impl Row { } } + fn cols(&self) -> u16 { + self.cells.len().try_into().unwrap() + } + pub fn clear(&mut self, bgcolor: crate::attrs::Color) { for cell in &mut self.cells { cell.clear(bgcolor); @@ -99,12 +103,16 @@ impl Row { contents: &mut Vec, start: u16, width: u16, + row: u16, + wrapping: bool, + pos: crate::grid::Pos, attrs: crate::attrs::Attrs, - ) -> (crate::attrs::Attrs, Option) { + ) -> (crate::grid::Pos, crate::attrs::Attrs) { let mut prev_was_wide = false; + let mut prev_pos = pos; let mut prev_attrs = attrs; - let mut cols = None; + let mut new_pos = crate::grid::Pos { row, col: start }; for cell in self .cells() .skip(start as usize) @@ -115,52 +123,92 @@ impl Row { continue; } - let attrs = cell.attrs(); - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } + prev_was_wide = cell.is_wide(); - if cell.has_contents() { - // using write! here is significantly slower, for some reason - // write!(contents, "{}", cell.contents()).unwrap(); - contents.extend(cell.contents().as_bytes()); - } else if cell.bgcolor() == crate::attrs::Color::Default { - write!(contents, "{}", crate::term::MoveRight::default()) - .unwrap(); + let has_contents = cell.has_contents(); + if !has_contents && cell.bgcolor() == crate::attrs::Color::Default + { + new_pos.col += 1; } else { - write!( - contents, - "{}{}", - crate::term::EraseChar::default(), - crate::term::MoveRight::default() - ) - .unwrap(); - } + if new_pos != prev_pos { + if new_pos.row == prev_pos.row + 1 { + if !wrapping + || prev_pos.col != self.cols() + || new_pos.col != 0 + { + write!( + contents, + "{}{}", + crate::term::CRLF::default(), + crate::term::MoveRight::new(new_pos.col) + ) + .unwrap(); + } + } else if prev_pos.row == new_pos.row { + write!( + contents, + "{}", + crate::term::MoveRight::new( + new_pos.col - prev_pos.col + ) + ) + .unwrap(); + } else { + write!( + contents, + "{}", + crate::term::MoveTo::new(new_pos) + ) + .unwrap(); + } + prev_pos = new_pos; + } - prev_was_wide = cell.is_wide(); - cols = - Some(cols.unwrap_or(0) + if prev_was_wide { 2 } else { 1 }); + let attrs = cell.attrs(); + if &prev_attrs != attrs { + attrs.write_escape_code_diff(contents, &prev_attrs); + prev_attrs = *attrs; + } + + if has_contents { + // using write! here is significantly slower, for some + // reason + // write!(contents, "{}", cell.contents()).unwrap(); + contents.extend(cell.contents().as_bytes()); + let width = if prev_was_wide { 2 } else { 1 }; + prev_pos.col += width; + new_pos.col += width; + } else { + write!( + contents, + "{}", + crate::term::EraseChar::default(), + ) + .unwrap(); + new_pos.col += 1; + } + } } - (prev_attrs, cols) + (prev_pos, prev_attrs) } - pub fn write_contents_diff Fn(&'a mut Vec)>( + pub fn write_contents_diff( &self, contents: &mut Vec, prev: &Self, - initial_pos: F, start: u16, width: u16, + row: u16, + wrapping: bool, + pos: crate::grid::Pos, attrs: crate::attrs::Attrs, - ) -> (crate::attrs::Attrs, Option) { + ) -> (crate::grid::Pos, crate::attrs::Attrs) { let mut prev_was_wide = false; + let mut prev_pos = pos; let mut prev_attrs = attrs; - let mut skip = 0; - let mut cols = None; - let mut initial_pos = Some(initial_pos); + let mut new_pos = crate::grid::Pos { row, col: start }; for (cell, prev_cell) in self .cells() .zip(prev.cells()) @@ -172,18 +220,45 @@ impl Row { continue; } + prev_was_wide = cell.is_wide(); + if cell == prev_cell { - prev_was_wide = cell.is_wide(); - skip += if prev_was_wide { 2 } else { 1 }; + new_pos.col += if prev_was_wide { 2 } else { 1 }; } else { - if let Some(f) = initial_pos.take() { - f(contents) - } - if skip > 0 { - write!(contents, "{}", crate::term::MoveRight::new(skip)) + if new_pos != prev_pos { + if new_pos.row == prev_pos.row + 1 { + if !wrapping + || prev_pos.col != self.cols() + || new_pos.col != 0 + { + write!( + contents, + "{}{}", + crate::term::CRLF::default(), + crate::term::MoveRight::new(new_pos.col) + ) + .unwrap(); + } + } else if prev_pos.row == new_pos.row + && prev_pos.col < new_pos.col + { + write!( + contents, + "{}", + crate::term::MoveRight::new( + new_pos.col - prev_pos.col + ) + ) .unwrap(); - cols = Some(cols.unwrap_or(0) + skip); - skip = 0; + } else { + write!( + contents, + "{}", + crate::term::MoveTo::new(new_pos) + ) + .unwrap(); + } + prev_pos = new_pos; } let attrs = cell.attrs(); @@ -197,24 +272,22 @@ impl Row { // reason // write!(contents, "{}", cell.contents()).unwrap(); contents.extend(cell.contents().as_bytes()); + let width = if prev_was_wide { 2 } else { 1 }; + prev_pos.col += width; + new_pos.col += width; } else { write!( contents, - "{}{}", + "{}", crate::term::EraseChar::default(), - crate::term::MoveRight::default() ) .unwrap(); + new_pos.col += 1; } - - prev_was_wide = cell.is_wide(); - cols = Some( - cols.unwrap_or(0) + if prev_was_wide { 2 } else { 1 }, - ); } } - (prev_attrs, cols) + (prev_pos, prev_attrs) } fn content_width(&self, start: u16, formatting: bool) -> u16 { -- cgit v1.2.3-54-g00ecf