1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2025-02-24 16:06:43 -05:00

Shave a few cycles off Grid::scroll_up

This implementation avoids a few extra transformations by operating in
buffer-space. However, there is still a transformation from the logical
buffer-space to the underlying vector.
This commit is contained in:
Joe Wilm 2018-05-19 14:47:16 -07:00
parent f897c998e9
commit 63de0559dd
2 changed files with 36 additions and 7 deletions

View file

@ -334,7 +334,6 @@ impl<T: Copy + Clone> Grid<T> {
/// scroll_up moves lines at the bottom towards the top /// scroll_up moves lines at the bottom towards the top
/// ///
/// This is the performance-sensitive part of scrolling. /// This is the performance-sensitive part of scrolling.
#[inline]
pub fn scroll_up( pub fn scroll_up(
&mut self, &mut self,
region: &Range<index::Line>, region: &Range<index::Line>,
@ -356,17 +355,21 @@ impl<T: Copy + Clone> Grid<T> {
selection.rotate(*positions as isize); selection.rotate(*positions as isize);
} }
// Now, restore any lines outside the scroll region // // This next loop swaps "fixed" lines outside of a scroll region
for idx in (*region.end .. *self.num_lines()).rev() { // // back into place after the rotation. The work is done in buffer-
// First do the swap // // space rather than terminal-space to avoid redundant
self.raw.swap_lines(Line(idx), Line(idx) - positions); // // transformations.
let fixed_lines = *self.num_lines() - *region.end;
for i in 0..fixed_lines {
self.raw.swap(i, i + *positions);
} }
// Finally, reset recycled lines // Finally, reset recycled lines
// //
// Recycled lines are just above the end of the scrolling region. // Recycled lines are just above the end of the scrolling region.
for i in 0..*positions { for i in 0..*positions {
self.raw[region.end - i - 1].reset(&template); self.raw[i + fixed_lines].reset(&template);
} }
} else { } else {
// Subregion rotation // Subregion rotation

View file

@ -171,12 +171,25 @@ impl<T> Storage<T> {
self.len self.len
} }
/// Compute actual index in underlying storage given the requested index.
#[inline] #[inline]
pub fn raw_len(&self) -> usize {
self.inner.len()
}
/// Compute actual index in underlying storage given the requested index.
fn compute_index(&self, requested: usize) -> usize { fn compute_index(&self, requested: usize) -> usize {
(requested + self.zero) % self.inner.len() (requested + self.zero) % self.inner.len()
} }
#[inline]
pub fn line_offset(&self) -> usize {
self.inner.len() + self.zero + *self.visible_lines
}
pub fn compute_line_index(&self, a: Line) -> usize {
(self.line_offset() - *a) % self.inner.len()
}
pub fn swap_lines(&mut self, a: Line, b: Line) { pub fn swap_lines(&mut self, a: Line, b: Line) {
let offset = self.inner.len() + self.zero + *self.visible_lines; let offset = self.inner.len() + self.zero + *self.visible_lines;
let a = (offset - *a) % self.inner.len(); let a = (offset - *a) % self.inner.len();
@ -184,6 +197,19 @@ impl<T> Storage<T> {
self.inner.swap(a, b); self.inner.swap(a, b);
} }
/// Swap two lines in raw buffer
///
/// # Panics
///
/// `swap` will panic if either `a` or `b` are out-of-bounds of the
/// underlying storage.
pub fn swap(&mut self, a: usize, b: usize) {
let a = self.compute_index(a);
let b = self.compute_index(b);
self.inner.swap(a, b);
}
/// Iterator over *logical* entries in the storage /// Iterator over *logical* entries in the storage
/// ///
/// This *does not* iterate over hidden entries. /// This *does not* iterate over hidden entries.