mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -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:
parent
d49d45f4b1
commit
284bed686a
2 changed files with 36 additions and 7 deletions
|
@ -334,7 +334,6 @@ impl<T: Copy + Clone> Grid<T> {
|
|||
/// scroll_up moves lines at the bottom towards the top
|
||||
///
|
||||
/// This is the performance-sensitive part of scrolling.
|
||||
#[inline]
|
||||
pub fn scroll_up(
|
||||
&mut self,
|
||||
region: &Range<index::Line>,
|
||||
|
@ -356,17 +355,21 @@ impl<T: Copy + Clone> Grid<T> {
|
|||
selection.rotate(*positions as isize);
|
||||
}
|
||||
|
||||
// Now, restore any lines outside the scroll region
|
||||
for idx in (*region.end .. *self.num_lines()).rev() {
|
||||
// First do the swap
|
||||
self.raw.swap_lines(Line(idx), Line(idx) - positions);
|
||||
// // This next loop swaps "fixed" lines outside of a scroll region
|
||||
// // back into place after the rotation. The work is done in buffer-
|
||||
// // space rather than terminal-space to avoid redundant
|
||||
// // 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
|
||||
//
|
||||
// Recycled lines are just above the end of the scrolling region.
|
||||
for i in 0..*positions {
|
||||
self.raw[region.end - i - 1].reset(&template);
|
||||
self.raw[i + fixed_lines].reset(&template);
|
||||
}
|
||||
} else {
|
||||
// Subregion rotation
|
||||
|
|
|
@ -171,12 +171,25 @@ impl<T> Storage<T> {
|
|||
self.len
|
||||
}
|
||||
|
||||
/// Compute actual index in underlying storage given the requested index.
|
||||
#[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 {
|
||||
(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) {
|
||||
let offset = self.inner.len() + self.zero + *self.visible_lines;
|
||||
let a = (offset - *a) % self.inner.len();
|
||||
|
@ -184,6 +197,19 @@ impl<T> Storage<T> {
|
|||
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
|
||||
///
|
||||
/// This *does not* iterate over hidden entries.
|
||||
|
|
Loading…
Reference in a new issue