Move buffer copy to its own function, it's more readable

This commit is contained in:
2023-11-05 08:23:31 +01:00
parent 1199dd7613
commit b81ec4ae4f

View File

@ -124,20 +124,24 @@ impl Component for Backlog {
value: PrerenderValue::Rendered(buf),
}) if *key == text_area.width => {
// We already rendered it, copy the buffer.
assert_eq!(buf.area().width, text_area.width);
for (y, line) in buf
.content()
.chunks(u16::min(buf.area().width, text_area.width) as usize)
.enumerate()
.skip(buf.area().height.saturating_sub(text_area.height) as usize)
{
for (x, cell) in line.into_iter().enumerate() {
*frame.buffer_mut().get_mut(
text_area.x + (x as u16),
text_area.y + text_area.height + (y as u16) - buf.area().height,
) = cell.clone();
}
}
assert_eq!(text_area.width, buf.area.width);
let top_padding = text_area.height.saturating_sub(buf.area.height);
let skip_top_lines = buf.area.height.saturating_sub(text_area.height);
copy_buffer(
buf,
Rect {
x: 0,
y: 0,
width: text_area.width,
height: buf.area.height - skip_top_lines,
},
frame.buffer_mut(),
Rect {
y: text_area.y + top_padding,
height: text_area.height - top_padding,
..text_area
},
);
buf.area().height
},
@ -145,28 +149,37 @@ impl Component for Backlog {
let widget = BottomAlignedParagraph::new(item.text);
let height = widget.render_overlap(text_area, frame.buffer_mut());
// Copy the drawn result to a buffer for caching
let mut buf = ratatui::buffer::Buffer::empty(Rect {
x: 0,
y: 0,
width: text_area.width,
height,
});
for y in 0..height {
// TODO: only copy the width actually drawn by the widget
for x in 0..text_area.width {
*buf.get_mut(x, y) = frame
.buffer_mut()
.get(text_area.x + x, text_area.y + text_area.height + y - height)
.clone()
}
// If the whole widget fits in the text_area, copy the drawn result to a buffer
// for caching
if height <= text_area.height {
let mut buf = ratatui::buffer::Buffer::empty(Rect {
x: 0,
y: 0,
width: text_area.width,
height,
});
let top_padding = text_area.height.saturating_sub(buf.area.height);
copy_buffer(
frame.buffer_mut(),
Rect {
y: text_area.y + top_padding,
height: text_area.height - top_padding,
..text_area
},
&mut buf,
Rect {
x: 0,
y: 0,
width: text_area.width, // TODO: only copy the width actually drawn by the widget
height: height,
},
);
*prerender = Some(PrerenderInner {
key: text_area.width,
value: PrerenderValue::Rendered(buf),
});
}
*prerender = Some(PrerenderInner {
key: text_area.width,
value: PrerenderValue::Rendered(buf),
});
height
},
};
@ -185,3 +198,44 @@ impl Component for Backlog {
Ok(())
}
}
fn copy_buffer(src: &Buffer, src_area: Rect, dst: &mut Buffer, dst_area: Rect) {
assert_eq!(src_area.width, dst_area.width, "width mismatch");
assert_eq!(src_area.height, dst_area.height, "height mismatch");
assert!(
src_area.x + src_area.width <= src.area.width,
"src width overflow"
);
assert!(
src_area.y + src_area.height <= src.area.height,
"src height overflow"
);
assert!(
dst_area.x + dst_area.width <= dst.area.width,
"dst width overflow"
);
assert!(
dst_area.y + dst_area.height <= dst.area.height,
"dst height overflow"
);
for (y, line) in src
.content()
.chunks(src.area.width as usize)
.skip(src_area.y as usize)
.take(dst_area.height as usize)
.enumerate()
{
for (x, cell) in line
.into_iter()
.skip(src_area.x as usize)
.take(src_area.width as usize)
.enumerate()
{
*dst.get_mut(dst_area.x + (x as u16), dst_area.y + (y as u16)) = src
.get(src_area.x + (x as u16), src_area.y + (y as u16))
.clone();
}
}
}