1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

Add text color, improve resize render performance

This commit is contained in:
Wez Furlong 2018-01-21 17:14:56 -08:00
parent 306414baa9
commit 31f35554a4
2 changed files with 51 additions and 11 deletions

View File

@ -187,6 +187,15 @@ impl Font {
Ok(&mut self.fonts[idx]) Ok(&mut self.fonts[idx])
} }
pub fn has_color(&mut self, idx: usize) -> Result<bool, Error> {
let font = self.get_font(idx)?;
unsafe {
Ok(
((*font.face.face).face_flags & ftwrap::FT_FACE_FLAG_COLOR as i64) != 0,
)
}
}
pub fn get_metrics(&mut self) -> Result<(f64, f64), Error> { pub fn get_metrics(&mut self) -> Result<(f64, f64), Error> {
let font = self.get_font(0)?; let font = self.get_font(0)?;
Ok((font.cell_height, font.cell_width)) Ok((font.cell_height, font.cell_width))

View File

@ -39,6 +39,7 @@ struct TerminalWindow<'a> {
cairo_context: cairo::Context, cairo_context: cairo::Context,
window_surface: cairo::Surface, window_surface: cairo::Surface,
buffer_surface: cairo::ImageSurface, buffer_surface: cairo::ImageSurface,
need_paint: bool,
} }
impl<'a> TerminalWindow<'a> { impl<'a> TerminalWindow<'a> {
@ -107,6 +108,7 @@ impl<'a> TerminalWindow<'a> {
cairo_context, cairo_context,
buffer_surface, buffer_surface,
window_surface, window_surface,
need_paint: true,
}) })
} }
@ -147,6 +149,7 @@ impl<'a> TerminalWindow<'a> {
self.window_surface.set_size(width as i32, height as i32); self.window_surface.set_size(width as i32, height as i32);
self.width = width; self.width = width;
self.height = height; self.height = height;
self.need_paint = true;
Ok(true) Ok(true)
} else { } else {
debug!("ignoring extra resize"); debug!("ignoring extra resize");
@ -178,19 +181,19 @@ impl<'a> TerminalWindow<'a> {
fn paint(&mut self) -> Result<(), Error> { fn paint(&mut self) -> Result<(), Error> {
debug!("paint"); debug!("paint");
self.need_paint = false;
let ctx = cairo::Context::new(&self.buffer_surface); let ctx = cairo::Context::new(&self.buffer_surface);
let message = "x_advance != foo->bar(); ❤ 😍🤢"; let message = "x_advance != foo->bar(); ❤ 😍🤢";
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0); ctx.set_source_rgb(0.0, 0.0, 0.0);
ctx.paint(); ctx.paint();
ctx.set_source_rgba(0.8, 0.8, 0.8, 1.0);
let mut x = 0.0; let mut x = 0.0;
let mut y = self.cell_height.ceil(); let mut y = self.cell_height.ceil();
let glyph_info = self.font.shape(0, message)?; let glyph_info = self.font.shape(0, message)?;
for info in glyph_info { for info in glyph_info {
let has_color = self.font.has_color(info.font_idx)?;
let ft_glyph = self.font.load_glyph(info.font_idx, info.glyph_pos)?; let ft_glyph = self.font.load_glyph(info.font_idx, info.glyph_pos)?;
let scale = if (info.x_advance / info.num_cells as f64).floor() > self.cell_width { let scale = if (info.x_advance / info.num_cells as f64).floor() > self.cell_width {
@ -284,8 +287,6 @@ impl<'a> TerminalWindow<'a> {
let bearing_x = ft_glyph.bitmap_left as f64; let bearing_x = ft_glyph.bitmap_left as f64;
let bearing_y = ft_glyph.bitmap_top as f64; let bearing_y = ft_glyph.bitmap_top as f64;
// TODO: colorize!
debug!( debug!(
"x,y: {},{} bearing:{},{} off={},{} adv={},{} scale={}", "x,y: {},{} bearing:{},{} off={},{} adv={},{} scale={}",
x, x,
@ -300,6 +301,7 @@ impl<'a> TerminalWindow<'a> {
); );
ctx.translate(x, y); ctx.translate(x, y);
ctx.scale(scale, scale); ctx.scale(scale, scale);
ctx.set_source_surface( ctx.set_source_surface(
&cairo_surface, &cairo_surface,
// Destination for the paint operation // Destination for the paint operation
@ -307,6 +309,26 @@ impl<'a> TerminalWindow<'a> {
-(info.y_offset + bearing_y), -(info.y_offset + bearing_y),
); );
ctx.paint(); ctx.paint();
if !has_color {
// Apply text color.
// TODO: we only do this for non-colored fonts, but
// we could apply it to those also if the current
// cell color is not the default foreground attribute.
ctx.save();
ctx.rectangle(
info.x_offset + bearing_x,
-(info.y_offset + bearing_y),
cairo_surface.get_width() as f64,
cairo_surface.get_height() as f64,
);
ctx.clip();
ctx.set_source_rgb(0.7, 0.7, 0.7);
ctx.set_operator(cairo::Operator::Multiply);
ctx.paint();
ctx.restore();
}
ctx.identity_matrix(); ctx.identity_matrix();
} }
@ -338,13 +360,24 @@ fn run() -> Result<(), Error> {
let (conn, screen_num) = xcb::Connection::connect(None)?; let (conn, screen_num) = xcb::Connection::connect(None)?;
println!("Connected screen {}", screen_num); println!("Connected screen {}", screen_num);
let mut window = TerminalWindow::new(&conn, screen_num, 300, 300)?; let mut window = TerminalWindow::new(&conn, screen_num, 1024, 300)?;
window.paint()?;
window.show(); window.show();
conn.flush(); conn.flush();
loop { loop {
let event = conn.wait_for_event(); // If we need to re-render the display, try to defer that until after we've
// consumed the input queue
let event = if window.need_paint {
match conn.poll_for_queued_event() {
None => {
window.paint();
continue;
}
Some(event) => Some(event),
}
} else {
conn.wait_for_event()
};
match event { match event {
None => break, None => break,
Some(event) => { Some(event) => {
@ -361,9 +394,7 @@ fn run() -> Result<(), Error> {
} }
xcb::CONFIGURE_NOTIFY => { xcb::CONFIGURE_NOTIFY => {
let cfg: &xcb::ConfigureNotifyEvent = unsafe { xcb::cast_event(&event) }; let cfg: &xcb::ConfigureNotifyEvent = unsafe { xcb::cast_event(&event) };
if window.resize_surfaces(cfg.width(), cfg.height())? { window.resize_surfaces(cfg.width(), cfg.height())?;
window.paint()?;
}
} }
xcb::KEY_PRESS => { xcb::KEY_PRESS => {
let key_press: &xcb::KeyPressEvent = unsafe { xcb::cast_event(&event) }; let key_press: &xcb::KeyPressEvent = unsafe { xcb::cast_event(&event) };