From bf2794f90fff5fd3c37047048022bdeb677f88db Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Mon, 23 Sep 2024 18:31:39 -0600 Subject: [PATCH] renderer: draw underlines below text to improve legibility --- src/renderer/Metal.zig | 75 +++++++++++++++++---------------- src/renderer/OpenGL.zig | 91 +++++++++++++++++++++-------------------- 2 files changed, 86 insertions(+), 80 deletions(-) diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index bb2a27f44..1790711c8 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -2523,6 +2523,45 @@ fn updateCell( } } + // If the cell has an underline, draw it before the character glyph, + // so that it layers underneath instead of overtop, since that can + // make text difficult to read. + if (underline != .none) { + const sprite: font.Sprite = switch (underline) { + .none => unreachable, + .single => .underline, + .double => .underline_double, + .dotted => .underline_dotted, + .dashed => .underline_dashed, + .curly => .underline_curly, + }; + + const render = try self.font_grid.renderGlyph( + self.alloc, + font.sprite_index, + @intFromEnum(sprite), + .{ + .cell_width = if (cell.wide == .wide) 2 else 1, + .grid_metrics = self.grid_metrics, + }, + ); + + const color = style.underlineColor(palette) orelse colors.fg; + + try self.cells.add(self.alloc, .underline, .{ + .mode = .fg, + .grid_pos = .{ @intCast(coord.x), @intCast(coord.y) }, + .constraint_width = cell.gridWidth(), + .color = .{ color.r, color.g, color.b, alpha }, + .glyph_pos = .{ render.glyph.atlas_x, render.glyph.atlas_y }, + .glyph_size = .{ render.glyph.width, render.glyph.height }, + .bearings = .{ + @intCast(render.glyph.offset_x), + @intCast(render.glyph.offset_y), + }, + }); + } + // If the shaper cell has a glyph, draw it. if (shaper_cell.glyph_index) |glyph_index| glyph: { // Render @@ -2566,42 +2605,6 @@ fn updateCell( }); } - if (underline != .none) { - const sprite: font.Sprite = switch (underline) { - .none => unreachable, - .single => .underline, - .double => .underline_double, - .dotted => .underline_dotted, - .dashed => .underline_dashed, - .curly => .underline_curly, - }; - - const render = try self.font_grid.renderGlyph( - self.alloc, - font.sprite_index, - @intFromEnum(sprite), - .{ - .cell_width = if (cell.wide == .wide) 2 else 1, - .grid_metrics = self.grid_metrics, - }, - ); - - const color = style.underlineColor(palette) orelse colors.fg; - - try self.cells.add(self.alloc, .underline, .{ - .mode = .fg, - .grid_pos = .{ @intCast(coord.x), @intCast(coord.y) }, - .constraint_width = cell.gridWidth(), - .color = .{ color.r, color.g, color.b, alpha }, - .glyph_pos = .{ render.glyph.atlas_x, render.glyph.atlas_y }, - .glyph_size = .{ render.glyph.width, render.glyph.height }, - .bearings = .{ - @intCast(render.glyph.offset_x), - @intCast(render.glyph.offset_y), - }, - }); - } - if (style.flags.strikethrough) { const render = try self.font_grid.renderGlyph( self.alloc, diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index a8f7c385c..082f330c5 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -1761,6 +1761,53 @@ fn updateCell( @intFromFloat(@max(0, @min(255, @round(self.config.background_opacity * 255)))), }; + // If the cell has an underline, draw it before the character glyph, + // so that it layers underneath instead of overtop, since that can + // make text difficult to read. + if (underline != .none) { + const sprite: font.Sprite = switch (underline) { + .none => unreachable, + .single => .underline, + .double => .underline_double, + .dotted => .underline_dotted, + .dashed => .underline_dashed, + .curly => .underline_curly, + }; + + const render = try self.font_grid.renderGlyph( + self.alloc, + font.sprite_index, + @intFromEnum(sprite), + .{ + .cell_width = if (cell.wide == .wide) 2 else 1, + .grid_metrics = self.grid_metrics, + }, + ); + + const color = style.underlineColor(palette) orelse colors.fg; + + try self.cells.append(self.alloc, .{ + .mode = .fg, + .grid_col = @intCast(x), + .grid_row = @intCast(y), + .grid_width = cell.gridWidth(), + .glyph_x = render.glyph.atlas_x, + .glyph_y = render.glyph.atlas_y, + .glyph_width = render.glyph.width, + .glyph_height = render.glyph.height, + .glyph_offset_x = render.glyph.offset_x, + .glyph_offset_y = render.glyph.offset_y, + .r = color.r, + .g = color.g, + .b = color.b, + .a = alpha, + .bg_r = bg[0], + .bg_g = bg[1], + .bg_b = bg[2], + .bg_a = bg[3], + }); + } + // If the cell has a character, draw it if (cell.hasText()) fg: { // Render @@ -1807,50 +1854,6 @@ fn updateCell( }); } - if (underline != .none) { - const sprite: font.Sprite = switch (underline) { - .none => unreachable, - .single => .underline, - .double => .underline_double, - .dotted => .underline_dotted, - .dashed => .underline_dashed, - .curly => .underline_curly, - }; - - const render = try self.font_grid.renderGlyph( - self.alloc, - font.sprite_index, - @intFromEnum(sprite), - .{ - .cell_width = if (cell.wide == .wide) 2 else 1, - .grid_metrics = self.grid_metrics, - }, - ); - - const color = style.underlineColor(palette) orelse colors.fg; - - try self.cells.append(self.alloc, .{ - .mode = .fg, - .grid_col = @intCast(x), - .grid_row = @intCast(y), - .grid_width = cell.gridWidth(), - .glyph_x = render.glyph.atlas_x, - .glyph_y = render.glyph.atlas_y, - .glyph_width = render.glyph.width, - .glyph_height = render.glyph.height, - .glyph_offset_x = render.glyph.offset_x, - .glyph_offset_y = render.glyph.offset_y, - .r = color.r, - .g = color.g, - .b = color.b, - .a = alpha, - .bg_r = bg[0], - .bg_g = bg[1], - .bg_b = bg[2], - .bg_a = bg[3], - }); - } - if (style.flags.strikethrough) { const render = try self.font_grid.renderGlyph( self.alloc,