1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-28 09:12:19 +03:00

implement underlines in the new renderer

This commit is contained in:
Wez Furlong 2019-10-25 23:40:30 -07:00
parent b9add8e3d4
commit bc4373c3ff
3 changed files with 111 additions and 42 deletions

View File

@ -4,6 +4,7 @@ in vec2 o_tex;
in vec4 o_fg_color; in vec4 o_fg_color;
in vec4 o_bg_color; in vec4 o_bg_color;
in float o_has_color; in float o_has_color;
in vec2 o_underline;
uniform mat4 projection; uniform mat4 projection;
uniform bool bg_and_line_layer; uniform bool bg_and_line_layer;
@ -11,9 +12,40 @@ uniform sampler2D glyph_tex;
out vec4 color; out vec4 color;
float multiply_one(float src, float dst, float inv_dst_alpha, float inv_src_alpha) {
return (src * dst) + (src * (inv_dst_alpha)) + (dst * (inv_src_alpha));
}
// Alpha-regulated multiply to colorize the glyph bitmap.
// The texture data is pre-multiplied by the alpha, so we need to divide
// by the alpha after multiplying to avoid having the colors be too dark.
vec4 multiply(vec4 src, vec4 dst) {
float inv_src_alpha = 1.0 - src.a;
float inv_dst_alpha = 1.0 - dst.a;
return vec4(
multiply_one(src.r, dst.r, inv_dst_alpha, inv_src_alpha) / dst.a,
multiply_one(src.g, dst.g, inv_dst_alpha, inv_src_alpha) / dst.a,
multiply_one(src.b, dst.b, inv_dst_alpha, inv_src_alpha) / dst.a,
dst.a);
}
void main() { void main() {
if (bg_and_line_layer) { if (bg_and_line_layer) {
color = o_bg_color; color = o_bg_color;
// Sample the underline glyph texture for this location.
// Note that the texture is whitespace in the case where this is
// no underline or strikethrough.
// We tint the underline glyph with the foreground color
vec4 under_color = multiply(o_fg_color, texture(glyph_tex, o_underline));
if (under_color.a != 0.0) {
// if the line glyph isn't transparent in this position then
// we take this pixel color, otherwise we'll leave the color
// at the background color.
color = under_color;
}
} else { } else {
color = texture(glyph_tex, o_tex); color = texture(glyph_tex, o_tex);
if (o_has_color == 0.0) { if (o_has_color == 0.0) {

View File

@ -195,13 +195,18 @@ struct Vertex {
position: (f32, f32), position: (f32, f32),
// bearing offset within the cell // bearing offset within the cell
adjust: (f32, f32), adjust: (f32, f32),
// glyph texture
tex: (f32, f32), tex: (f32, f32),
// underline texture
underline: (f32, f32),
bg_color: (f32, f32, f32, f32), bg_color: (f32, f32, f32, f32),
fg_color: (f32, f32, f32, f32), fg_color: (f32, f32, f32, f32),
// "bool can't be an in in the vertex shader" // "bool can't be an in in the vertex shader"
has_color: f32, has_color: f32,
} }
::window::glium::implement_vertex!(Vertex, position, adjust, tex, bg_color, fg_color, has_color); ::window::glium::implement_vertex!(
Vertex, position, adjust, tex, underline, bg_color, fg_color, has_color
);
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct RenderMetrics { struct RenderMetrics {
@ -384,6 +389,31 @@ impl<T: Texture2d> UtilSprites<T> {
double_and_strike, double_and_strike,
}) })
} }
/// Figure out what we're going to draw for the underline.
/// If the current cell is part of the current URL highlight
/// then we want to show the underline.
pub fn select_sprite(
&self,
is_highlited_hyperlink: bool,
is_strike_through: bool,
underline: Underline,
) -> &Sprite<T> {
match (is_highlited_hyperlink, is_strike_through, underline) {
(true, false, Underline::None) => &self.single_underline,
(true, false, Underline::Single) => &self.double_underline,
(true, false, Underline::Double) => &self.single_underline,
(true, true, Underline::None) => &self.strike_through,
(true, true, Underline::Single) => &self.single_and_strike,
(true, true, Underline::Double) => &self.double_and_strike,
(false, false, Underline::None) => &self.white_space,
(false, false, Underline::Single) => &self.single_underline,
(false, false, Underline::Double) => &self.double_underline,
(false, true, Underline::None) => &self.strike_through,
(false, true, Underline::Single) => &self.single_and_strike,
(false, true, Underline::Double) => &self.double_and_strike,
}
}
} }
struct OpenGLRenderState { struct OpenGLRenderState {
@ -1400,31 +1430,12 @@ impl TermWindow {
+ self.render_metrics.descender) + self.render_metrics.descender)
- (glyph.y_offset + glyph.bearing_y)) as f32; - (glyph.y_offset + glyph.bearing_y)) as f32;
/*
// underline and strikethrough // underline and strikethrough
// Figure out what we're going to draw for the underline. let underline = gl_state.util_sprites.select_sprite(
// If the current cell is part of the current URL highlight
// then we want to show the underline.
#[cfg_attr(feature = "cargo-clippy", allow(clippy::match_same_arms))]
let underline: f32 = match (
is_highlited_hyperlink, is_highlited_hyperlink,
attrs.strikethrough(), attrs.strikethrough(),
attrs.underline(), attrs.underline(),
) { );
(true, false, Underline::None) => U_ONE,
(true, false, Underline::Single) => U_TWO,
(true, false, Underline::Double) => U_ONE,
(true, true, Underline::None) => U_STRIKE_ONE,
(true, true, Underline::Single) => U_STRIKE_TWO,
(true, true, Underline::Double) => U_STRIKE_ONE,
(false, false, Underline::None) => U_NONE,
(false, false, Underline::Single) => U_ONE,
(false, false, Underline::Double) => U_TWO,
(false, true, Underline::None) => U_STRIKE,
(false, true, Underline::Single) => U_STRIKE_ONE,
(false, true, Underline::Double) => U_STRIKE_TWO,
};
*/
// Iterate each cell that comprises this glyph. There is usually // Iterate each cell that comprises this glyph. There is usually
// a single cell per glyph but combining characters, ligatures // a single cell per glyph but combining characters, ligatures
@ -1467,13 +1478,6 @@ impl TermWindow {
vert[V_BOT_LEFT].bg_color = bg_color; vert[V_BOT_LEFT].bg_color = bg_color;
vert[V_BOT_RIGHT].bg_color = bg_color; vert[V_BOT_RIGHT].bg_color = bg_color;
/*
vert[V_TOP_LEFT].underline = underline;
vert[V_TOP_RIGHT].underline = underline;
vert[V_BOT_LEFT].underline = underline;
vert[V_BOT_RIGHT].underline = underline;
*/
let texture = glyph let texture = glyph
.texture .texture
.as_ref() .as_ref()
@ -1489,6 +1493,7 @@ impl TermWindow {
let pixel_rect = slice.pixel_rect(texture); let pixel_rect = slice.pixel_rect(texture);
let texture_rect = texture.texture.to_texture_coords(pixel_rect); let texture_rect = texture.texture.to_texture_coords(pixel_rect);
let underline_tex_rect = underline.texture_coords();
let left = if glyph_idx == 0 { left } else { 0.0 }; let left = if glyph_idx == 0 { left } else { 0.0 };
/* /*
@ -1500,15 +1505,23 @@ impl TermWindow {
- self.render_metrics.cell_size.width as f32; - self.render_metrics.cell_size.width as f32;
vert[V_TOP_LEFT].tex = (texture_rect.min_x(), texture_rect.min_y()); vert[V_TOP_LEFT].tex = (texture_rect.min_x(), texture_rect.min_y());
vert[V_TOP_LEFT].underline =
(underline_tex_rect.min_x(), underline_tex_rect.min_y());
vert[V_TOP_LEFT].adjust = (left, top); vert[V_TOP_LEFT].adjust = (left, top);
vert[V_TOP_RIGHT].tex = (texture_rect.max_x(), texture_rect.min_y()); vert[V_TOP_RIGHT].tex = (texture_rect.max_x(), texture_rect.min_y());
vert[V_TOP_RIGHT].underline =
(underline_tex_rect.max_x(), underline_tex_rect.min_y());
vert[V_TOP_RIGHT].adjust = (right, top); //(left, top); vert[V_TOP_RIGHT].adjust = (right, top); //(left, top);
vert[V_BOT_LEFT].tex = (texture_rect.min_x(), texture_rect.max_y()); vert[V_BOT_LEFT].tex = (texture_rect.min_x(), texture_rect.max_y());
vert[V_BOT_LEFT].underline =
(underline_tex_rect.min_x(), underline_tex_rect.max_y());
vert[V_BOT_LEFT].adjust = (left, bottom); //(left, top); vert[V_BOT_LEFT].adjust = (left, bottom); //(left, top);
vert[V_BOT_RIGHT].tex = (texture_rect.max_x(), texture_rect.max_y()); vert[V_BOT_RIGHT].tex = (texture_rect.max_x(), texture_rect.max_y());
vert[V_BOT_RIGHT].underline =
(underline_tex_rect.max_x(), underline_tex_rect.max_y());
vert[V_BOT_RIGHT].adjust = (right, bottom); //(left, top); vert[V_BOT_RIGHT].adjust = (right, bottom); //(left, top);
let has_color = if glyph.has_color { 1.0 } else { 0.0 }; let has_color = if glyph.has_color { 1.0 } else { 0.0 };
@ -1527,9 +1540,11 @@ impl TermWindow {
// the right pane with its prior contents instead of showing the // the right pane with its prior contents instead of showing the
// cleared lines from the shell in the main screen. // cleared lines from the shell in the main screen.
let white_space = gl_state.util_sprites.white_space.texture_coords();
for cell_idx in last_cell_idx + 1..num_cols { for cell_idx in last_cell_idx + 1..num_cols {
let vert_idx = cell_idx * VERTICES_PER_CELL; let vert_idx = cell_idx * VERTICES_PER_CELL;
let vert_slice = &mut vertices[vert_idx..vert_idx + 4]; let vert = &mut vertices[vert_idx..vert_idx + 4];
// Even though we don't have a cell for these, they still // Even though we don't have a cell for these, they still
// hold the cursor or the selection so we need to compute // hold the cursor or the selection so we need to compute
@ -1544,18 +1559,36 @@ impl TermWindow {
palette, palette,
); );
for vert in vert_slice.iter_mut() { let bg_color = bg_color.to_tuple_rgba();
vert.bg_color = bg_color.to_tuple_rgba(); let fg_color = glyph_color.to_tuple_rgba();
vert.fg_color = glyph_color.to_tuple_rgba();
/* vert[V_TOP_LEFT].tex = (white_space.min_x(), white_space.min_y());
// vert.underline = U_NONE; vert[V_TOP_LEFT].underline = vert[V_TOP_LEFT].tex;
// Note: these 0 coords refer to the blank pixel vert[V_TOP_LEFT].adjust = (0., 0.);
// in the bottom left of the underline texture! vert[V_TOP_LEFT].has_color = 0.0;
vert.tex = (0.0, 0.0); vert[V_TOP_LEFT].bg_color = bg_color;
vert.adjust = Default::default(); vert[V_TOP_LEFT].fg_color = fg_color;
vert.has_color = 0.0;
*/ vert[V_TOP_RIGHT].tex = (white_space.max_x(), white_space.min_y());
} vert[V_TOP_RIGHT].underline = vert[V_TOP_RIGHT].tex;
vert[V_TOP_RIGHT].adjust = (0., 0.);
vert[V_TOP_RIGHT].has_color = 0.0;
vert[V_TOP_RIGHT].bg_color = bg_color;
vert[V_TOP_RIGHT].fg_color = fg_color;
vert[V_BOT_LEFT].tex = (white_space.min_x(), white_space.max_y());
vert[V_BOT_LEFT].underline = vert[V_BOT_LEFT].tex;
vert[V_BOT_LEFT].adjust = (0., 0.);
vert[V_BOT_LEFT].has_color = 0.0;
vert[V_BOT_LEFT].bg_color = bg_color;
vert[V_BOT_LEFT].fg_color = fg_color;
vert[V_BOT_RIGHT].tex = (white_space.max_x(), white_space.max_y());
vert[V_BOT_RIGHT].underline = vert[V_BOT_RIGHT].tex;
vert[V_BOT_RIGHT].adjust = (0., 0.);
vert[V_BOT_RIGHT].has_color = 0.0;
vert[V_BOT_RIGHT].bg_color = bg_color;
vert[V_BOT_RIGHT].fg_color = fg_color;
} }
Ok(()) Ok(())

View File

@ -2,6 +2,7 @@ precision mediump float;
in vec2 position; in vec2 position;
in vec2 adjust; in vec2 adjust;
in vec2 tex; in vec2 tex;
in vec2 underline;
in vec4 bg_color; in vec4 bg_color;
in vec4 fg_color; in vec4 fg_color;
in float has_color; in float has_color;
@ -13,12 +14,15 @@ out vec2 o_tex;
out vec4 o_fg_color; out vec4 o_fg_color;
out vec4 o_bg_color; out vec4 o_bg_color;
out float o_has_color; out float o_has_color;
out vec2 o_underline;
void main() { void main() {
o_tex = tex; o_tex = tex;
o_has_color = has_color; o_has_color = has_color;
o_fg_color = fg_color; o_fg_color = fg_color;
o_bg_color = bg_color; o_bg_color = bg_color;
o_underline = underline;
if (bg_and_line_layer) { if (bg_and_line_layer) {
// Want to fill the whole cell when painting backgrounds // Want to fill the whole cell when painting backgrounds
gl_Position = projection * vec4(position, 0.0, 1.0); gl_Position = projection * vec4(position, 0.0, 1.0);