diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2022-12-09 09:21:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-09 09:21:28 +0300 |
commit | 6566dd3defa9f080dabb295740dc1dac06e3b8fb (patch) | |
tree | baf1879dac3a39fda83f80ffe465bfc61596e0a9 /alacritty/src/display/damage.rs | |
parent | 79860622a7beb8bbff0602e56977be6018f3aa39 (diff) | |
download | r-alacritty-6566dd3defa9f080dabb295740dc1dac06e3b8fb.tar.gz r-alacritty-6566dd3defa9f080dabb295740dc1dac06e3b8fb.tar.bz2 r-alacritty-6566dd3defa9f080dabb295740dc1dac06e3b8fb.zip |
Fix damage computation on boundaries
Given that the Rect started to use signed integers saturating_sub
became irrelevant and no clamp to zero were performed. This commit
uses max instead to fix it.
Diffstat (limited to 'alacritty/src/display/damage.rs')
-rw-r--r-- | alacritty/src/display/damage.rs | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs index 380a2f63..82230dff 100644 --- a/alacritty/src/display/damage.rs +++ b/alacritty/src/display/damage.rs @@ -30,14 +30,13 @@ impl<'a> RenderDamageIterator<'a> { // Make sure to damage near cells to include wide chars. #[inline] - fn overdamage(&self, mut rect: Rect) -> Rect { - let size_info = &self.size_info; - rect.x = rect.x.saturating_sub(size_info.cell_width() as i32); + fn overdamage(size_info: &SizeInfo<u32>, mut rect: Rect) -> Rect { + rect.x = (rect.x - size_info.cell_width() as i32).max(0); rect.width = cmp::min( size_info.width() as i32 - rect.x, rect.width + 2 * size_info.cell_width() as i32, ); - rect.y = rect.y.saturating_sub(size_info.cell_height() as i32 / 2); + rect.y = (rect.y - size_info.cell_height() as i32 / 2).max(0); rect.height = cmp::min( size_info.height() as i32 - rect.y, rect.height + size_info.cell_height() as i32, @@ -52,11 +51,12 @@ impl<'a> Iterator for RenderDamageIterator<'a> { fn next(&mut self) -> Option<Rect> { let line = self.damaged_lines.next()?; - let mut total_damage_rect = self.overdamage(self.rect_for_line(line)); + let size_info = &self.size_info; + let mut total_damage_rect = Self::overdamage(size_info, self.rect_for_line(line)); // Merge rectangles which overlap with each other. while let Some(line) = self.damaged_lines.peek().copied() { - let next_rect = self.overdamage(self.rect_for_line(line)); + let next_rect = Self::overdamage(size_info, self.rect_for_line(line)); if !rects_overlap(total_damage_rect, next_rect) { break; } @@ -92,3 +92,52 @@ fn merge_rects(lhs: Rect, rhs: Rect) -> Rect { let y_bottom = cmp::min(lhs.y, rhs.y); Rect::new(left_x, y_bottom, right_x - left_x, y_top - y_bottom) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn damage_rect_math() { + let rect_side = 10; + let cell_size = 4; + let bound = 100; + + let size_info: SizeInfo<u32> = SizeInfo::new( + bound as f32, + bound as f32, + cell_size as f32, + cell_size as f32, + 2., + 2., + true, + ) + .into(); + + // Test min clamping. + let rect = Rect::new(0, 0, rect_side, rect_side); + let rect = RenderDamageIterator::overdamage(&size_info, rect); + assert_eq!(Rect::new(0, 0, rect_side + 2 * cell_size, 10 + cell_size), rect); + + // Test max clamping. + let rect = Rect::new(bound, bound, rect_side, rect_side); + let rect = RenderDamageIterator::overdamage(&size_info, rect); + assert_eq!( + Rect::new(bound - cell_size, bound - cell_size / 2, cell_size, cell_size / 2), + rect + ); + + // Test no clamping. + let rect = Rect::new(bound / 2, bound / 2, rect_side, rect_side); + let rect = RenderDamageIterator::overdamage(&size_info, rect); + assert_eq!( + Rect::new( + bound / 2 - cell_size, + bound / 2 - cell_size / 2, + rect_side + 2 * cell_size, + rect_side + cell_size + ), + rect + ); + } +} |