diff --git a/src/font/shape.zig b/src/font/shape.zig index e3634d68c..0d8a029bf 100644 --- a/src/font/shape.zig +++ b/src/font/shape.zig @@ -77,19 +77,7 @@ pub const RunOptions = struct { cells: std.MultiArrayList(terminal.RenderState.Cell).Slice = .empty, /// The x boundaries of the selection in this row. - selection2: ?[2]u16 = null, - - /// The terminal screen to shape. - screen: *const terminal.Screen, - - /// The row within the screen to shape. This row must exist within - /// screen; it is not validated. - row: terminal.Pin, - - /// The selection boundaries. This is used to break shaping on - /// selection boundaries. This can be disabled by setting this to - /// null. - selection: ?terminal.Selection = null, + selection: ?[2]u16 = null, /// The cursor position within this row. This is used to break shaping /// on cursor boundaries. This can be disabled by setting this to diff --git a/src/font/shaper/coretext.zig b/src/font/shaper/coretext.zig index 41fa88758..c1deec11d 100644 --- a/src/font/shaper/coretext.zig +++ b/src/font/shaper/coretext.zig @@ -644,8 +644,6 @@ test "run iterator" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |_| count += 1; @@ -669,8 +667,6 @@ test "run iterator" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |_| count += 1; @@ -695,8 +691,6 @@ test "run iterator" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |_| count += 1; @@ -722,8 +716,6 @@ test "run iterator" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |_| count += 1; @@ -776,8 +768,6 @@ test "run iterator: empty cells with background set" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); { const run = (try it.next(alloc)).?; @@ -818,8 +808,6 @@ test "shape" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -859,8 +847,6 @@ test "shape nerd fonts" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -893,8 +879,6 @@ test "shape inconsolata ligs" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -924,8 +908,6 @@ test "shape inconsolata ligs" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -963,8 +945,6 @@ test "shape monaspace ligs" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1003,8 +983,6 @@ test "shape left-replaced lig in last run" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1043,8 +1021,6 @@ test "shape left-replaced lig in early run" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); const run = (try it.next(alloc)).?; @@ -1080,8 +1056,6 @@ test "shape U+3C9 with JB Mono" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var run_count: usize = 0; @@ -1119,8 +1093,6 @@ test "shape emoji width" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1172,8 +1144,6 @@ test "shape emoji width long" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(1).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1214,8 +1184,6 @@ test "shape variation selector VS15" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1255,8 +1223,6 @@ test "shape variation selector VS16" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1293,8 +1259,6 @@ test "shape with empty cells in between" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1337,8 +1301,6 @@ test "shape Chinese characters" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1386,8 +1348,6 @@ test "shape Devanagari string" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); const run = try it.next(alloc); @@ -1436,8 +1396,6 @@ test "shape box glyphs" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1478,9 +1436,7 @@ test "shape selection boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, - .selection2 = .{ 0, @intCast(t.cols - 1) }, + .selection = .{ 0, @intCast(t.cols - 1) }, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1497,9 +1453,7 @@ test "shape selection boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, - .selection2 = .{ 2, @intCast(t.cols - 1) }, + .selection = .{ 2, @intCast(t.cols - 1) }, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1516,9 +1470,7 @@ test "shape selection boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, - .selection2 = .{ 0, 3 }, + .selection = .{ 0, 3 }, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1535,9 +1487,7 @@ test "shape selection boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, - .selection2 = .{ 1, 3 }, + .selection = .{ 1, 3 }, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1554,9 +1504,7 @@ test "shape selection boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, - .selection2 = .{ 1, 1 }, + .selection = .{ 1, 1 }, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1593,8 +1541,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1612,8 +1558,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, .cursor_x = 0, }); var count: usize = 0; @@ -1630,8 +1574,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1650,8 +1592,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, .cursor_x = 1, }); var count: usize = 0; @@ -1668,8 +1608,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1687,8 +1625,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, .cursor_x = 9, }); var count: usize = 0; @@ -1705,8 +1641,6 @@ test "shape cursor boundary" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1744,8 +1678,6 @@ test "shape cursor boundary and colored emoji" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1762,8 +1694,6 @@ test "shape cursor boundary and colored emoji" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, .cursor_x = 0, }); var count: usize = 0; @@ -1779,8 +1709,6 @@ test "shape cursor boundary and colored emoji" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1795,8 +1723,6 @@ test "shape cursor boundary and colored emoji" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, .cursor_x = 1, }); var count: usize = 0; @@ -1812,8 +1738,6 @@ test "shape cursor boundary and colored emoji" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1848,8 +1772,6 @@ test "shape cell attribute change" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1878,8 +1800,6 @@ test "shape cell attribute change" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1911,8 +1831,6 @@ test "shape cell attribute change" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1944,8 +1862,6 @@ test "shape cell attribute change" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -1975,8 +1891,6 @@ test "shape cell attribute change" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); var count: usize = 0; while (try it.next(alloc)) |run| { @@ -2020,8 +1934,6 @@ test "shape high plane sprite font codepoint" { var it = shaper.runIterator(.{ .grid = testdata.grid, .cells = state.row_data.get(0).cells.slice(), - .screen = undefined, - .row = undefined, }); // We should get one run const run = (try it.next(alloc)).?; diff --git a/src/font/shaper/run.zig b/src/font/shaper/run.zig index a0080d1fc..85c5c410b 100644 --- a/src/font/shaper/run.zig +++ b/src/font/shaper/run.zig @@ -45,273 +45,6 @@ pub const RunIterator = struct { i: usize = 0, pub fn next(self: *RunIterator, alloc: Allocator) !?TextRun { - if (self.opts.cells.len > 0) return try self.next2(alloc); - - const cells = self.opts.row.cells(.all); - - // Trim the right side of a row that might be empty - const max: usize = max: { - for (0..cells.len) |i| { - const rev_i = cells.len - i - 1; - if (!cells[rev_i].isEmpty()) break :max rev_i + 1; - } - - break :max 0; - }; - - // Invisible cells don't have any glyphs rendered, - // so we explicitly skip them in the shaping process. - while (self.i < max and - self.opts.row.style(&cells[self.i]).flags.invisible) - { - self.i += 1; - } - - // We're over at the max - if (self.i >= max) return null; - - // Track the font for our current run - var current_font: font.Collection.Index = .{}; - - // Allow the hook to prepare - try self.hooks.prepare(); - - // Initialize our hash for this run. - var hasher = Hasher.init(0); - - // Let's get our style that we'll expect for the run. - const style = self.opts.row.style(&cells[self.i]); - - // Go through cell by cell and accumulate while we build our run. - var j: usize = self.i; - while (j < max) : (j += 1) { - // Use relative cluster positions (offset from run start) to make - // the shaping cache position-independent. This ensures that runs - // with identical content but different starting positions in the - // row produce the same hash, enabling cache reuse. - const cluster = j - self.i; - const cell = &cells[j]; - - // If we have a selection and we're at a boundary point, then - // we break the run here. - if (self.opts.selection) |unordered_sel| { - if (j > self.i) { - const sel = unordered_sel.ordered(self.opts.screen, .forward); - const start_x = sel.start().x; - const end_x = sel.end().x; - - if (start_x > 0 and - j == start_x) break; - - if (end_x > 0 and - j == end_x + 1) break; - } - } - - // If we're a spacer, then we ignore it - switch (cell.wide) { - .narrow, .wide => {}, - .spacer_head, .spacer_tail => continue, - } - - // If our cell attributes are changing, then we split the run. - // This prevents a single glyph for ">=" to be rendered with - // one color when the two components have different styling. - if (j > self.i) style: { - const prev_cell = cells[j - 1]; - - // If the prev cell and this cell are both plain - // codepoints then we check if they are commonly "bad" - // ligatures and spit the run if they are. - if (prev_cell.content_tag == .codepoint and - cell.content_tag == .codepoint) - { - const prev_cp = prev_cell.codepoint(); - switch (prev_cp) { - // fl, fi - 'f' => { - const cp = cell.codepoint(); - if (cp == 'l' or cp == 'i') break; - }, - - // st - 's' => { - const cp = cell.codepoint(); - if (cp == 't') break; - }, - - else => {}, - } - } - - // If the style is exactly the change then fast path out. - if (prev_cell.style_id == cell.style_id) break :style; - - // The style is different. We allow differing background - // styles but any other change results in a new run. - const c1 = comparableStyle(style); - const c2 = comparableStyle(self.opts.row.style(&cells[j])); - if (!c1.eql(c2)) break; - } - - // Text runs break when font styles change so we need to get - // the proper style. - const font_style: font.Style = style: { - if (style.flags.bold) { - if (style.flags.italic) break :style .bold_italic; - break :style .bold; - } - - if (style.flags.italic) break :style .italic; - break :style .regular; - }; - - // Determine the presentation format for this glyph. - const presentation: ?font.Presentation = if (cell.hasGrapheme()) p: { - // We only check the FIRST codepoint because I believe the - // presentation format must be directly adjacent to the codepoint. - const cps = self.opts.row.grapheme(cell) orelse break :p null; - assert(cps.len > 0); - if (cps[0] == 0xFE0E) break :p .text; - if (cps[0] == 0xFE0F) break :p .emoji; - break :p null; - } else emoji: { - // If we're not a grapheme, our individual char could be - // an emoji so we want to check if we expect emoji presentation. - // The font grid indexForCodepoint we use below will do this - // automatically. - break :emoji null; - }; - - // If our cursor is on this line then we break the run around the - // cursor. This means that any row with a cursor has at least - // three breaks: before, exactly the cursor, and after. - // - // We do not break a cell that is exactly the grapheme. If there - // are cells following that contain joiners, we allow those to - // break. This creates an effect where hovering over an emoji - // such as a skin-tone emoji is fine, but hovering over the - // joiners will show the joiners allowing you to modify the - // emoji. - if (!cell.hasGrapheme()) { - if (self.opts.cursor_x) |cursor_x| { - // Exactly: self.i is the cursor and we iterated once. This - // means that we started exactly at the cursor and did at - // exactly one iteration. Why exactly one? Because we may - // start at our cursor but do many if our cursor is exactly - // on an emoji. - if (self.i == cursor_x and j == self.i + 1) break; - - // Before: up to and not including the cursor. This means - // that we started before the cursor (self.i < cursor_x) - // and j is now at the cursor meaning we haven't yet processed - // the cursor. - if (self.i < cursor_x and j == cursor_x) { - assert(j > 0); - break; - } - - // After: after the cursor. We don't need to do anything - // special, we just let the run complete. - } - } - - // We need to find a font that supports this character. If - // there are additional zero-width codepoints (to form a single - // grapheme, i.e. combining characters), we need to find a font - // that supports all of them. - const font_info: struct { - idx: font.Collection.Index, - fallback: ?u32 = null, - } = font_info: { - // If we find a font that supports this entire grapheme - // then we use that. - if (try self.indexForCell( - alloc, - cell, - font_style, - presentation, - )) |idx| break :font_info .{ .idx = idx }; - - // Otherwise we need a fallback character. Prefer the - // official replacement character. - if (try self.opts.grid.getIndex( - alloc, - 0xFFFD, // replacement char - font_style, - presentation, - )) |idx| break :font_info .{ .idx = idx, .fallback = 0xFFFD }; - - // Fallback to space - if (try self.opts.grid.getIndex( - alloc, - ' ', - font_style, - presentation, - )) |idx| break :font_info .{ .idx = idx, .fallback = ' ' }; - - // We can't render at all. This is a bug, we should always - // have a font that can render a space. - unreachable; - }; - - //log.warn("char={x} info={}", .{ cell.char, font_info }); - if (j == self.i) current_font = font_info.idx; - - // If our fonts are not equal, then we're done with our run. - if (font_info.idx != current_font) break; - - // If we're a fallback character, add that and continue; we - // don't want to add the entire grapheme. - if (font_info.fallback) |cp| { - try self.addCodepoint(&hasher, cp, @intCast(cluster)); - continue; - } - - // If we're a Kitty unicode placeholder then we add a blank. - if (cell.codepoint() == terminal.kitty.graphics.unicode.placeholder) { - try self.addCodepoint(&hasher, ' ', @intCast(cluster)); - continue; - } - - // Add all the codepoints for our grapheme - try self.addCodepoint( - &hasher, - if (cell.codepoint() == 0) ' ' else cell.codepoint(), - @intCast(cluster), - ); - if (cell.hasGrapheme()) { - const cps = self.opts.row.grapheme(cell).?; - for (cps) |cp| { - // Do not send presentation modifiers - if (cp == 0xFE0E or cp == 0xFE0F) continue; - try self.addCodepoint(&hasher, cp, @intCast(cluster)); - } - } - } - - // Finalize our buffer - try self.hooks.finalize(); - - // Add our length to the hash as an additional mechanism to avoid collisions - autoHash(&hasher, j - self.i); - - // Add our font index - autoHash(&hasher, current_font); - - // Move our cursor. Must defer since we use self.i below. - defer self.i = j; - - return TextRun{ - .hash = hasher.final(), - .offset = @intCast(self.i), - .cells = @intCast(j - self.i), - .grid = self.opts.grid, - .font_index = current_font, - }; - } - - pub fn next2(self: *RunIterator, alloc: Allocator) !?TextRun { const slice = &self.opts.cells; const cells: []const terminal.page.Cell = slice.items(.raw); const graphemes: []const []const u21 = slice.items(.grapheme); @@ -360,7 +93,7 @@ pub const RunIterator = struct { // If we have a selection and we're at a boundary point, then // we break the run here. - if (self.opts.selection2) |bounds| { + if (self.opts.selection) |bounds| { if (j > self.i) { if (bounds[0] > 0 and j == bounds[0]) break; if (bounds[1] > 0 and j == bounds[1] + 1) break; @@ -485,7 +218,7 @@ pub const RunIterator = struct { } = font_info: { // If we find a font that supports this entire grapheme // then we use that. - if (try self.indexForCell2( + if (try self.indexForCell( alloc, cell, graphemes[j], @@ -583,82 +316,6 @@ pub const RunIterator = struct { /// We look for fonts that support each individual codepoint and then /// find the common font amongst all candidates. fn indexForCell( - self: *RunIterator, - alloc: Allocator, - cell: *const terminal.Cell, - style: font.Style, - presentation: ?font.Presentation, - ) !?font.Collection.Index { - if (cell.isEmpty() or - cell.codepoint() == 0 or - cell.codepoint() == terminal.kitty.graphics.unicode.placeholder) - { - return try self.opts.grid.getIndex( - alloc, - ' ', - style, - presentation, - ); - } - - // Get the font index for the primary codepoint. - const primary_cp: u32 = cell.codepoint(); - const primary = try self.opts.grid.getIndex( - alloc, - primary_cp, - style, - presentation, - ) orelse return null; - - // Easy, and common: we aren't a multi-codepoint grapheme, so - // we just return whatever index for the cell codepoint. - if (!cell.hasGrapheme()) return primary; - - // If this is a grapheme, we need to find a font that supports - // all of the codepoints in the grapheme. - const cps = self.opts.row.grapheme(cell) orelse return primary; - var candidates: std.ArrayList(font.Collection.Index) = try .initCapacity(alloc, cps.len + 1); - defer candidates.deinit(alloc); - candidates.appendAssumeCapacity(primary); - - for (cps) |cp| { - // Ignore Emoji ZWJs - if (cp == 0xFE0E or cp == 0xFE0F or cp == 0x200D) continue; - - // Find a font that supports this codepoint. If none support this - // then the whole grapheme can't be rendered so we return null. - // - // We explicitly do not require the additional grapheme components - // to support the base presentation, since it is common for emoji - // fonts to support the base emoji with emoji presentation but not - // certain ZWJ-combined characters like the male and female signs. - const idx = try self.opts.grid.getIndex( - alloc, - cp, - style, - null, - ) orelse return null; - candidates.appendAssumeCapacity(idx); - } - - // We need to find a candidate that has ALL of our codepoints - for (candidates.items) |idx| { - if (!self.opts.grid.hasCodepoint(idx, primary_cp, presentation)) continue; - for (cps) |cp| { - // Ignore Emoji ZWJs - if (cp == 0xFE0E or cp == 0xFE0F or cp == 0x200D) continue; - if (!self.opts.grid.hasCodepoint(idx, cp, null)) break; - } else { - // If the while completed, then we have a candidate that - // supports all of our codepoints. - return idx; - } - } - - return null; - } - - fn indexForCell2( self: *RunIterator, alloc: Allocator, cell: *const terminal.Cell, diff --git a/src/renderer/generic.zig b/src/renderer/generic.zig index bc7dc0321..719b0c327 100644 --- a/src/renderer/generic.zig +++ b/src/renderer/generic.zig @@ -2414,7 +2414,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type { var run_iter_opts: font.shape.RunOptions = .{ .grid = self.font_grid, .cells = cells_slice, - .selection2 = if (selection) |s| s else null, + .selection = if (selection) |s| s else null, // We want to do font shaping as long as the cursor is // visible on this viewport. @@ -2423,11 +2423,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type { if (vp.y != y) break :cursor_x null; break :cursor_x vp.x; }, - - // Old stuff - .screen = undefined, - .row = undefined, - .selection = null, }; run_iter_opts.applyBreakConfig(self.config.font_shaping_break); var run_iter = self.font_shaper.runIterator(run_iter_opts);