From 9b4e362a338d90d8c0563f516cfe9819b9a5c9f0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 30 Apr 2024 10:07:02 -0700 Subject: [PATCH] font/coretext: shaping ligatures adds padding cells for replaced cells Fixes #1708 Harfbuzz does this automatically. Our tests for harfbuzz test this. We had a todo in CoreText to mimic this but wasn't sure if it was useful. Turns out, it is important (see bug!) --- src/font/res/GeistMono-Regular.ttf | Bin 0 -> 112160 bytes src/font/shaper/coretext.zig | 135 +++++++++++++++++++++++++---- src/font/test.zig | 1 + 3 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 src/font/res/GeistMono-Regular.ttf diff --git a/src/font/res/GeistMono-Regular.ttf b/src/font/res/GeistMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a909c5d618162902debdbc09463d905c7c54cd61 GIT binary patch literal 112160 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 literal 0 HcmV?d00001 diff --git a/src/font/shaper/coretext.zig b/src/font/shaper/coretext.zig index 831062208..76d0cdb9a 100644 --- a/src/font/shaper/coretext.zig +++ b/src/font/shaper/coretext.zig @@ -325,9 +325,20 @@ pub const Shaper = struct { // Our cluster is also our cell X position. If the cluster changes // then we need to reset our current cell offsets. const cluster = state.codepoints.items[index].cluster; - if (cell_offset.cluster != cluster) cell_offset = .{ - .cluster = cluster, - }; + if (cell_offset.cluster != cluster) { + assert(cell_offset.cluster < cluster); + + // If we have a gap between clusters then we need to + // add empty cells to the buffer. + for (cell_offset.cluster + 1..cluster) |x| { + self.cell_buf.appendAssumeCapacity(.{ + .x = @intCast(x), + .glyph_index = null, + }); + } + + cell_offset = .{ .cluster = cluster }; + } self.cell_buf.appendAssumeCapacity(.{ .x = @intCast(cluster), @@ -341,10 +352,6 @@ pub const Shaper = struct { cell_offset.x += advance.width; cell_offset.y += advance.height; - // TODO: harfbuzz shaper has handling for inserting blank - // cells for multi-cell ligatures. Do we need to port that? - // Example: try Monaspace "===" with a background color. - _ = pos; // const i = self.cell_buf.items.len - 1; // log.warn( @@ -355,6 +362,25 @@ pub const Shaper = struct { //log.warn("-------------------------------", .{}); } + // If our last cell doesn't match our last cluster then we have + // a left-replaced ligature that needs to have spaces appended + // so that cells retain their background colors. + if (self.cell_buf.items.len > 0) pad: { + const last_cell = self.cell_buf.items[self.cell_buf.items.len - 1]; + const last_cp = state.codepoints.items[state.codepoints.items.len - 1]; + if (last_cell.x == last_cp.cluster) break :pad; + assert(last_cell.x < last_cp.cluster); + + // We need to go back to the last matched cluster and add + // padding up to there. + for (last_cell.x + 1..last_cp.cluster + 1) |x| { + self.cell_buf.appendAssumeCapacity(.{ + .x = @intCast(x), + .glyph_index = null, + }); + } + } + return self.cell_buf.items; } @@ -388,13 +414,10 @@ pub const Shaper = struct { // If the UTF-16 codepoint is a pair then we need to insert // a dummy entry so that the CTRunGetStringIndices() function // maps correctly. - if (pair) { - try state.codepoints.append(self.shaper.alloc, .{ - .codepoint = 0, - .cluster = cluster, - }); - log.warn("run pair cp=0", .{}); - } + if (pair) try state.codepoints.append(self.shaper.alloc, .{ + .codepoint = 0, + .cluster = cluster, + }); } pub fn finalize(self: RunIteratorHook) !void { @@ -620,8 +643,9 @@ test "shape inconsolata ligs" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 2), cells.len); try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); } try testing.expectEqual(@as(usize, 1), count); } @@ -644,8 +668,10 @@ test "shape inconsolata ligs" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 3), cells.len); try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); } try testing.expectEqual(@as(usize, 1), count); } @@ -676,13 +702,82 @@ test "shape monaspace ligs" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 3), cells.len); try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); } try testing.expectEqual(@as(usize, 1), count); } } +// https://github.com/mitchellh/ghostty/issues/1708 +test "shape left-replaced lig in last run" { + const testing = std.testing; + const alloc = testing.allocator; + + var testdata = try testShaperWithFont(alloc, .geist_mono); + defer testdata.deinit(); + + { + var screen = try terminal.Screen.init(alloc, 5, 3, 0); + defer screen.deinit(); + try screen.testWriteString("!=="); + + var shaper = &testdata.shaper; + var it = shaper.runIterator( + testdata.grid, + &screen, + screen.pages.pin(.{ .screen = .{ .y = 0 } }).?, + null, + null, + ); + var count: usize = 0; + while (try it.next(alloc)) |run| { + count += 1; + + const cells = try shaper.shape(run); + try testing.expectEqual(@as(usize, 3), cells.len); + try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); + } + try testing.expectEqual(@as(usize, 1), count); + } +} + +// https://github.com/mitchellh/ghostty/issues/1708 +test "shape left-replaced lig in early run" { + const testing = std.testing; + const alloc = testing.allocator; + + var testdata = try testShaperWithFont(alloc, .geist_mono); + defer testdata.deinit(); + + { + var screen = try terminal.Screen.init(alloc, 5, 3, 0); + defer screen.deinit(); + try screen.testWriteString("!==X"); + + var shaper = &testdata.shaper; + var it = shaper.runIterator( + testdata.grid, + &screen, + screen.pages.pin(.{ .screen = .{ .y = 0 } }).?, + null, + null, + ); + + const run = (try it.next(alloc)).?; + const cells = try shaper.shape(run); + try testing.expectEqual(@as(usize, 4), cells.len); + try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); + try testing.expect(cells[3].glyph_index != null); + } +} + // https://github.com/mitchellh/ghostty/issues/1664 test "shape U+3C9 with JB Mono" { const testing = std.testing; @@ -782,8 +877,8 @@ test "shape emoji width long" { count += 1; const cells = try shaper.shape(run); - // screen.testWriteString isn't grapheme aware, otherwise this is two - try testing.expectEqual(@as(usize, 1), cells.len); + // screen.testWriteString isn't grapheme aware, otherwise this is one + try testing.expectEqual(@as(usize, 5), cells.len); } try testing.expectEqual(@as(usize, 1), count); } @@ -1401,6 +1496,7 @@ const TestShaper = struct { const TestFont = enum { inconsolata, + geist_mono, jetbrains_mono, monaspace_neon, nerd_font, @@ -1416,6 +1512,7 @@ fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper { const testEmojiText = @import("../test.zig").fontEmojiText; const testFont = switch (font_req) { .inconsolata => @import("../test.zig").fontRegular, + .geist_mono => @import("../test.zig").fontGeistMono, .jetbrains_mono => @import("../test.zig").fontJetBrainsMono, .monaspace_neon => @import("../test.zig").fontMonaspaceNeon, .nerd_font => @import("../test.zig").fontNerdFont, diff --git a/src/font/test.zig b/src/font/test.zig index 499a75158..253d067b4 100644 --- a/src/font/test.zig +++ b/src/font/test.zig @@ -16,6 +16,7 @@ pub const fontVariable = @embedFile("res/Lilex-VF.ttf"); pub const fontNerdFont = @embedFile("res/JetBrainsMonoNerdFont-Regular.ttf"); /// Specific font families below: +pub const fontGeistMono = @embedFile("res/GeistMono-Regular.ttf"); pub const fontJetBrainsMono = @embedFile("res/JetBrainsMonoNoNF-Regular.ttf"); /// Cozette is a unique font because it embeds some emoji characters