Add Backend::print_at_rep and make Printer::print_hline use it. (#326)

* Add Backend::print_at_rep and make Printer::print_hline use it.

This avoids a string allocation in `print_hline` and makes it faster, presumably for all backends.
This speeds up the rendering of the background in StackView.

* Fix a bug in how Printer::print_hline computes the repetition count.
This commit is contained in:
Chris Vest 2019-03-12 23:03:00 +01:00 committed by Alexandre Bury
parent 4b5a7867e3
commit ea7b5dbae2
7 changed files with 64 additions and 5 deletions

View File

@ -17,6 +17,7 @@ use crate::backend;
use crate::event::{Event, Key, MouseButton, MouseEvent};
use crate::theme::{BaseColor, Color, ColorPair, Effect};
use crate::vec::Vec2;
use unicode_width::UnicodeWidthStr;
enum ColorRole {
Foreground,

View File

@ -373,6 +373,17 @@ impl backend::Backend for Backend {
fn print_at(&self, pos: Vec2, text: &str) {
ncurses::mvaddstr(pos.y as i32, pos.x as i32, text);
}
fn print_at_rep(&self, pos: Vec2, repetitions: usize, text: &str) {
if repetitions > 0 {
ncurses::mvaddstr(pos.y as i32, pos.x as i32, text);
let mut dupes_left = repetitions - 1;
while dupes_left > 0 {
ncurses::addstr(text);
dupes_left -= 1;
}
}
}
}
/// Returns the Key enum corresponding to the given ncurses event.

View File

@ -417,6 +417,17 @@ impl backend::Backend for Backend {
self.window.mvaddstr(pos.y as i32, pos.x as i32, text);
}
fn print_at_rep(&self, pos: Vec2, repetitions: usize, text: &str) {
if repetitions > 0 {
self.window.mvaddstr(pos.y as i32, pos.x as i32, text);
let mut dupes_left = repetitions - 1;
while dupes_left > 0 {
self.window.addstr(text);
dupes_left -= 1;
}
}
}
fn poll_event(&mut self) -> Option<Event> {
self.parse_next()
}

View File

@ -38,6 +38,8 @@ impl backend::Backend for Backend {
fn print_at(&self, _: Vec2, _: &str) {}
fn print_at_rep(&self, _pos: Vec2, _repetitions: usize, _text: &str) {}
fn clear(&self, _: theme::Color) {}
// This sets the Colours and returns the previous colours

View File

@ -10,6 +10,7 @@
use crate::event::Event;
use crate::theme;
use crate::vec::Vec2;
use unicode_width::UnicodeWidthStr;
#[cfg(unix)]
mod resize;
@ -64,6 +65,24 @@ pub trait Backend {
/// Main method used for printing
fn print_at(&self, pos: Vec2, text: &str);
/// First positions the cursor, similar to `print_at`, and then prints the given number of
/// `repetitions` of `text`.
fn print_at_rep(&self, pos: Vec2, repetitions: usize, text: &str) {
if repetitions > 0 {
self.print_at(pos, text);
let width = text.width();
let mut pos = pos;
let mut dupes_left = repetitions - 1;
while dupes_left > 0 {
pos = pos.saturating_add((width, 0));
self.print_at(pos, text);
dupes_left -= 1;
}
}
}
/// Clears the screen with the given color.
fn clear(&self, color: theme::Color);

View File

@ -268,6 +268,24 @@ impl backend::Backend for Backend {
.unwrap();
}
fn print_at_rep(&self, pos: Vec2, repetitions: usize, text: &str) {
if repetitions > 0 {
let mut out = self.terminal.borrow_mut();
write!(
out,
"{}{}",
termion::cursor::Goto(1 + pos.x as u16, 1 + pos.y as u16),
text
).unwrap();
let mut dupes_left = repetitions - 1;
while dupes_left > 0 {
write!(out, "{}", text).unwrap();
dupes_left -= 1;
}
}
}
fn poll_event(&mut self) -> Option<Event> {
let event = select! {
recv(self.input_receiver) -> event => event.ok(),

View File

@ -255,13 +255,10 @@ impl<'a, 'b> Printer<'a, 'b> {
let start = start - self.content_offset;
// Don't write too much if we're close to the end
let width = min(width, (self.output_size.x - start.x) / c.width());
// Could we avoid allocating?
let text: String = ::std::iter::repeat(c).take(width).collect();
let repetitions = min(width, self.output_size.x - start.x) / c.width();
let start = start + self.offset;
self.backend.print_at(start, &text);
self.backend.print_at_rep(start, repetitions, c);
}
/// Call the given closure with a colored printer,