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:
parent
306414baa9
commit
31f35554a4
@ -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))
|
||||||
|
53
src/main.rs
53
src/main.rs
@ -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) };
|
||||||
|
Loading…
Reference in New Issue
Block a user