initial underline support, can be improved

This commit is contained in:
Mitchell Hashimoto
2022-06-28 14:21:57 -07:00
parent 427fcc94e2
commit f53efa633a
6 changed files with 93 additions and 41 deletions

View File

@ -1,5 +1,7 @@
Bugs: Bugs:
* Underline should use freetype underline thickness hint
Performance: Performance:
* libuv allocates on every read, we should use a read buffer pool * libuv allocates on every read, we should use a read buffer pool
@ -19,8 +21,6 @@ Major Features:
* Line wrap * Line wrap
* Selection, highlighting * Selection, highlighting
* Copy (paste is done) * Copy (paste is done)
* Bold
* Underline
* Strikethrough * Strikethrough
* Emoji * Emoji
* Ligatures * Ligatures

View File

@ -28,6 +28,7 @@ const uint MODE_FG = 2u;
const uint MODE_CURSOR_RECT = 3u; const uint MODE_CURSOR_RECT = 3u;
const uint MODE_CURSOR_RECT_HOLLOW = 4u; const uint MODE_CURSOR_RECT_HOLLOW = 4u;
const uint MODE_CURSOR_BAR = 5u; const uint MODE_CURSOR_BAR = 5u;
const uint MODE_UNDERLINE = 6u;
void main() { void main() {
switch (mode) { switch (mode) {
@ -83,5 +84,9 @@ void main() {
case MODE_CURSOR_BAR: case MODE_CURSOR_BAR:
out_FragColor = color; out_FragColor = color;
break; break;
case MODE_UNDERLINE:
out_FragColor = color;
break;
} }
} }

View File

@ -9,6 +9,7 @@ const uint MODE_FG = 2u;
const uint MODE_CURSOR_RECT = 3u; const uint MODE_CURSOR_RECT = 3u;
const uint MODE_CURSOR_RECT_HOLLOW = 4u; const uint MODE_CURSOR_RECT_HOLLOW = 4u;
const uint MODE_CURSOR_BAR = 5u; const uint MODE_CURSOR_BAR = 5u;
const uint MODE_UNDERLINE = 6u;
// The grid coordinates (x, y) where x < columns and y < rows // The grid coordinates (x, y) where x < columns and y < rows
layout (location = 0) in vec2 grid_coord; layout (location = 0) in vec2 grid_coord;
@ -158,5 +159,23 @@ void main() {
gl_Position = projection * vec4(cell_pos, 0.0, 1.0); gl_Position = projection * vec4(cell_pos, 0.0, 1.0);
color = bg_color_in / 255.0; color = bg_color_in / 255.0;
break; break;
case MODE_UNDERLINE:
// Make the underline a smaller version of our cell
// TODO: use real font underline thickness
vec2 underline_size = vec2(cell_size.x, cell_size.y*0.05);
// Position our underline so that it is midway between the glyph
// baseline and the bottom of the cell.
vec2 underline_offset = vec2(cell_size.x, cell_size.y - (glyph_baseline / 2));
// Go to the bottom of the cell, take away the size of the
// underline, and that is our position. We also float it slightly
// above the bottom.
cell_pos = cell_pos + underline_offset - underline_size * position;
gl_Position = projection * vec4(cell_pos, 0.0, 1.0);
color = fg_color_in / 255.0;
break;
} }
} }

View File

@ -271,9 +271,9 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
try self.cells.ensureTotalCapacity( try self.cells.ensureTotalCapacity(
self.alloc, self.alloc,
// * 2 for background modes and cursor // * 3 for background modes and cursor and underlines
// + 1 for cursor // + 1 for cursor
(term.screen.rows * term.screen.cols * 2) + 1, (term.screen.rows * term.screen.cols * 3) + 1,
); );
// Build each cell // Build each cell
@ -308,9 +308,10 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
}); });
} }
// If the cell is empty then we draw nothing in the box. const fg = cell.fg orelse self.foreground;
if (cell.empty()) continue;
// If the cell is empty then we draw nothing in the box.
if (!cell.empty()) {
// Determine our glyph styling // Determine our glyph styling
const style: font.Style = if (cell.attrs.bold == 1) const style: font.Style = if (cell.attrs.bold == 1)
.bold .bold
@ -326,7 +327,6 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
break :glyph try self.font_atlas.addGlyph(self.alloc, cell.char, style); break :glyph try self.font_atlas.addGlyph(self.alloc, cell.char, style);
}; };
const fg = cell.fg orelse self.foreground;
self.cells.appendAssumeCapacity(.{ self.cells.appendAssumeCapacity(.{
.mode = 2, .mode = 2,
.grid_col = @intCast(u16, x), .grid_col = @intCast(u16, x),
@ -347,6 +347,29 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.bg_a = 0, .bg_a = 0,
}); });
} }
if (cell.attrs.underline == 1) {
self.cells.appendAssumeCapacity(.{
.mode = 6, // underline
.grid_col = @intCast(u16, x),
.grid_row = @intCast(u16, y),
.glyph_x = 0,
.glyph_y = 0,
.glyph_width = 0,
.glyph_height = 0,
.glyph_offset_x = 0,
.glyph_offset_y = 0,
.fg_r = fg.r,
.fg_g = fg.g,
.fg_b = fg.b,
.fg_a = 255,
.bg_r = 0,
.bg_g = 0,
.bg_b = 0,
.bg_a = 0,
});
}
}
} }
// Draw the cursor // Draw the cursor

View File

@ -24,6 +24,7 @@ pub const Cell = struct {
/// TODO: pack it /// TODO: pack it
attrs: struct { attrs: struct {
bold: u1 = 0, bold: u1 = 0,
underline: u1 = 0,
inverse: u1 = 0, inverse: u1 = 0,
} = .{}, } = .{},

View File

@ -154,6 +154,10 @@ pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
self.cursor.pen.attrs.bold = 1; self.cursor.pen.attrs.bold = 1;
}, },
.underline => {
self.cursor.pen.attrs.underline = 1;
},
.inverse => { .inverse => {
self.cursor.pen.attrs.inverse = 1; self.cursor.pen.attrs.inverse = 1;
}, },