diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 1790711c8..0fda9cbe4 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -2274,6 +2274,10 @@ fn rebuildCells( }; for (shaper_cells) |shaper_cell| { + // The shaper can emit null glyphs representing the right half + // of wide characters, we don't need to do anything with them. + if (shaper_cell.glyph_index == null) continue; + const coord: terminal.Coordinate = .{ .x = shaper_cell.x, .y = y, @@ -2541,7 +2545,7 @@ fn updateCell( font.sprite_index, @intFromEnum(sprite), .{ - .cell_width = if (cell.wide == .wide) 2 else 1, + .cell_width = 1, .grid_metrics = self.grid_metrics, }, ); @@ -2551,7 +2555,7 @@ fn updateCell( try self.cells.add(self.alloc, .underline, .{ .mode = .fg, .grid_pos = .{ @intCast(coord.x), @intCast(coord.y) }, - .constraint_width = cell.gridWidth(), + .constraint_width = 1, .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 }, @@ -2560,6 +2564,21 @@ fn updateCell( @intCast(render.glyph.offset_y), }, }); + // If it's a wide cell we need to underline the right half as well. + if (cell.gridWidth() > 1 and coord.x < self.cells.size.columns - 1) { + try self.cells.add(self.alloc, .underline, .{ + .mode = .fg, + .grid_pos = .{ @intCast(coord.x + 1), @intCast(coord.y) }, + .constraint_width = 1, + .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. @@ -2611,7 +2630,7 @@ fn updateCell( font.sprite_index, @intFromEnum(font.Sprite.strikethrough), .{ - .cell_width = if (cell.wide == .wide) 2 else 1, + .cell_width = 1, .grid_metrics = self.grid_metrics, }, ); @@ -2619,7 +2638,7 @@ fn updateCell( try self.cells.add(self.alloc, .strikethrough, .{ .mode = .fg, .grid_pos = .{ @intCast(coord.x), @intCast(coord.y) }, - .constraint_width = cell.gridWidth(), + .constraint_width = 1, .color = .{ colors.fg.r, colors.fg.g, colors.fg.b, alpha }, .glyph_pos = .{ render.glyph.atlas_x, render.glyph.atlas_y }, .glyph_size = .{ render.glyph.width, render.glyph.height }, @@ -2628,6 +2647,21 @@ fn updateCell( @intCast(render.glyph.offset_y), }, }); + // If it's a wide cell we need to strike through the right half as well. + if (cell.gridWidth() > 1 and coord.x < self.cells.size.columns - 1) { + try self.cells.add(self.alloc, .strikethrough, .{ + .mode = .fg, + .grid_pos = .{ @intCast(coord.x + 1), @intCast(coord.y) }, + .constraint_width = 1, + .color = .{ colors.fg.r, colors.fg.g, colors.fg.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), + }, + }); + } } return true; diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 760721af3..7ea3f6ec8 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -1338,6 +1338,10 @@ pub fn rebuildCells( }; for (shaper_cells) |shaper_cell| { + // The shaper can emit null glyphs representing the right half + // of wide characters, we don't need to do anything with them. + if (shaper_cell.glyph_index == null) continue; + // If this cell falls within our preedit range then we skip it. // We do this so we don't have conflicting data on the same // cell. @@ -1779,7 +1783,7 @@ fn updateCell( font.sprite_index, @intFromEnum(sprite), .{ - .cell_width = if (cell.wide == .wide) 2 else 1, + .cell_width = 1, .grid_metrics = self.grid_metrics, }, ); @@ -1790,7 +1794,7 @@ fn updateCell( .mode = .fg, .grid_col = @intCast(x), .grid_row = @intCast(y), - .grid_width = cell.gridWidth(), + .grid_width = 1, .glyph_x = render.glyph.atlas_x, .glyph_y = render.glyph.atlas_y, .glyph_width = render.glyph.width, @@ -1806,6 +1810,29 @@ fn updateCell( .bg_b = bg[2], .bg_a = bg[3], }); + // If it's a wide cell we need to underline the right half as well. + if (cell.gridWidth() > 1 and x < self.grid_size.columns - 1) { + try self.cells.append(self.alloc, .{ + .mode = .fg, + .grid_col = @intCast(x + 1), + .grid_row = @intCast(y), + .grid_width = 1, + .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 shaper cell has a glyph, draw it. @@ -1866,7 +1893,7 @@ fn updateCell( font.sprite_index, @intFromEnum(font.Sprite.strikethrough), .{ - .cell_width = if (cell.wide == .wide) 2 else 1, + .cell_width = 1, .grid_metrics = self.grid_metrics, }, ); @@ -1875,7 +1902,7 @@ fn updateCell( .mode = .fg, .grid_col = @intCast(x), .grid_row = @intCast(y), - .grid_width = cell.gridWidth(), + .grid_width = 1, .glyph_x = render.glyph.atlas_x, .glyph_y = render.glyph.atlas_y, .glyph_width = render.glyph.width, @@ -1891,6 +1918,29 @@ fn updateCell( .bg_b = bg[2], .bg_a = bg[3], }); + // If it's a wide cell we need to strike through the right half as well. + if (cell.gridWidth() > 1 and x < self.grid_size.columns - 1) { + try self.cells.append(self.alloc, .{ + .mode = .fg, + .grid_col = @intCast(x + 1), + .grid_row = @intCast(y), + .grid_width = 1, + .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 = colors.fg.r, + .g = colors.fg.g, + .b = colors.fg.b, + .a = alpha, + .bg_r = bg[0], + .bg_g = bg[1], + .bg_b = bg[2], + .bg_a = bg[3], + }); + } } return true;