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:
parent
b9add8e3d4
commit
bc4373c3ff
@ -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) {
|
||||||
|
@ -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(())
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user