test(shaper/coretext): test non-monotonic CoreText output

pull/9609/head
Qwerasd 2025-11-14 17:39:03 -07:00
parent 712cc9e55c
commit 985e1a3cea
1 changed files with 92 additions and 0 deletions

View File

@ -1202,6 +1202,51 @@ test "shape Chinese characters" {
try testing.expectEqual(@as(usize, 1), count);
}
// This test exists because the string it uses causes CoreText to output a
// non-monotonic run, which we need to handle by sorting the resulting buffer.
test "shape Devanagari string" {
const testing = std.testing;
const alloc = testing.allocator;
// We need a font that supports devanagari for this to work, if we can't
// find Arial Unicode MS, which is a system font on macOS, we just skip
// the test.
var testdata = testShaperWithDiscoveredFont(
alloc,
"Arial Unicode MS",
) catch return error.SkipZigTest;
defer testdata.deinit();
// Make a screen with some data
var screen = try terminal.Screen.init(alloc, .{ .cols = 30, .rows = 3, .max_scrollback = 0 });
defer screen.deinit();
try screen.testWriteString("अपार्टमेंट");
// Get our run iterator
var shaper = &testdata.shaper;
var it = shaper.runIterator(.{
.grid = testdata.grid,
.screen = &screen,
.row = screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
});
const run = try it.next(alloc);
try testing.expect(run != null);
const cells = try shaper.shape(run.?);
try testing.expectEqual(@as(usize, 8), cells.len);
try testing.expectEqual(@as(u16, 0), cells[0].x);
try testing.expectEqual(@as(u16, 1), cells[1].x);
try testing.expectEqual(@as(u16, 2), cells[2].x);
try testing.expectEqual(@as(u16, 3), cells[3].x);
try testing.expectEqual(@as(u16, 4), cells[4].x);
try testing.expectEqual(@as(u16, 5), cells[5].x);
try testing.expectEqual(@as(u16, 5), cells[6].x);
try testing.expectEqual(@as(u16, 6), cells[7].x);
try testing.expect(try it.next(alloc) == null);
}
test "shape box glyphs" {
const testing = std.testing;
const alloc = testing.allocator;
@ -1890,3 +1935,50 @@ fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
.lib = lib,
};
}
/// Return a fully initialized shaper by discovering a named font on the system.
fn testShaperWithDiscoveredFont(alloc: Allocator, font_req: [:0]const u8) !TestShaper {
var lib = try Library.init(alloc);
errdefer lib.deinit();
var c = Collection.init();
c.load_options = .{ .library = lib };
// Discover and add our font to the collection.
{
var disco = font.Discover.init();
defer disco.deinit();
var disco_it = try disco.discover(alloc, .{
.family = font_req,
.size = 12,
.monospace = false,
});
defer disco_it.deinit();
var face: font.DeferredFace = (try disco_it.next()).?;
errdefer face.deinit();
_ = try c.add(
alloc,
try face.load(lib, .{ .size = .{ .points = 12 } }),
.{
.style = .regular,
.fallback = false,
.size_adjustment = .none,
},
);
}
const grid_ptr = try alloc.create(SharedGrid);
errdefer alloc.destroy(grid_ptr);
grid_ptr.* = try .init(alloc, .{ .collection = c });
errdefer grid_ptr.*.deinit(alloc);
var shaper = try Shaper.init(alloc, .{});
errdefer shaper.deinit();
return TestShaper{
.alloc = alloc,
.shaper = shaper,
.grid = grid_ptr,
.lib = lib,
};
}