Add shape Tai Tham vowels test
parent
f4560390d7
commit
6addccdeeb
|
|
@ -390,8 +390,8 @@ pub const Shaper = struct {
|
|||
y: f64 = 0,
|
||||
|
||||
// For debugging positions, turn this on:
|
||||
start_index: usize = 0,
|
||||
end_index: usize = 0,
|
||||
//start_index: usize = 0,
|
||||
//end_index: usize = 0,
|
||||
} = .{};
|
||||
|
||||
// Clear our cell buf and make sure we have enough room for the whole
|
||||
|
|
@ -450,53 +450,56 @@ pub const Shaper = struct {
|
|||
.y = run_offset.y,
|
||||
|
||||
// For debugging positions, turn this on:
|
||||
.start_index = index,
|
||||
.end_index = index,
|
||||
//.start_index = index,
|
||||
//.end_index = index,
|
||||
};
|
||||
} else {
|
||||
if (index < cell_offset.start_index) {
|
||||
cell_offset.start_index = index;
|
||||
}
|
||||
if (index > cell_offset.end_index) {
|
||||
cell_offset.end_index = index;
|
||||
}
|
||||
|
||||
// For debugging positions, turn this on:
|
||||
//} else {
|
||||
// if (index < cell_offset.start_index) {
|
||||
// cell_offset.start_index = index;
|
||||
// }
|
||||
// if (index > cell_offset.end_index) {
|
||||
// cell_offset.end_index = index;
|
||||
// }
|
||||
}
|
||||
|
||||
const x_offset = position.x - cell_offset.x;
|
||||
const y_offset = position.y - cell_offset.y;
|
||||
|
||||
const advance_x_offset = run_offset.x - cell_offset.x;
|
||||
const advance_y_offset = run_offset.y - cell_offset.y;
|
||||
const x_offset_diff = x_offset - advance_x_offset;
|
||||
const y_offset_diff = y_offset - advance_y_offset;
|
||||
// Ford debugging positions, turn this on:
|
||||
//const advance_x_offset = run_offset.x - cell_offset.x;
|
||||
//const advance_y_offset = run_offset.y - cell_offset.y;
|
||||
//const x_offset_diff = x_offset - advance_x_offset;
|
||||
//const y_offset_diff = y_offset - advance_y_offset;
|
||||
|
||||
if (@abs(x_offset_diff) > 0.0001 or @abs(y_offset_diff) > 0.0001) {
|
||||
var allocating = std.Io.Writer.Allocating.init(alloc);
|
||||
const writer = &allocating.writer;
|
||||
const codepoints = state.codepoints.items[cell_offset.start_index .. cell_offset.end_index + 1];
|
||||
for (codepoints) |cp| {
|
||||
if (cp.codepoint == 0) continue; // Skip surrogate pair padding
|
||||
try writer.print("\\u{{{x}}}", .{cp.codepoint});
|
||||
}
|
||||
try writer.writeAll(" → ");
|
||||
for (codepoints) |cp| {
|
||||
if (cp.codepoint == 0) continue; // Skip surrogate pair padding
|
||||
try writer.print("{u}", .{@as(u21, @intCast(cp.codepoint))});
|
||||
}
|
||||
const formatted_cps = try allocating.toOwnedSlice();
|
||||
//if (@abs(x_offset_diff) > 0.0001 or @abs(y_offset_diff) > 0.0001) {
|
||||
// var allocating = std.Io.Writer.Allocating.init(alloc);
|
||||
// const writer = &allocating.writer;
|
||||
// const codepoints = state.codepoints.items[cell_offset.start_index .. cell_offset.end_index + 1];
|
||||
// for (codepoints) |cp| {
|
||||
// if (cp.codepoint == 0) continue; // Skip surrogate pair padding
|
||||
// try writer.print("\\u{{{x}}}", .{cp.codepoint});
|
||||
// }
|
||||
// try writer.writeAll(" → ");
|
||||
// for (codepoints) |cp| {
|
||||
// if (cp.codepoint == 0) continue; // Skip surrogate pair padding
|
||||
// try writer.print("{u}", .{@as(u21, @intCast(cp.codepoint))});
|
||||
// }
|
||||
// const formatted_cps = try allocating.toOwnedSlice();
|
||||
|
||||
log.warn("position differs from advance: cluster={d} pos=({d:.2},{d:.2}) adv=({d:.2},{d:.2}) diff=({d:.2},{d:.2}) current cp={x}, cps={s}", .{
|
||||
cluster,
|
||||
x_offset,
|
||||
y_offset,
|
||||
advance_x_offset,
|
||||
advance_y_offset,
|
||||
x_offset_diff,
|
||||
y_offset_diff,
|
||||
state.codepoints.items[index].codepoint,
|
||||
formatted_cps,
|
||||
});
|
||||
}
|
||||
// log.warn("position differs from advance: cluster={d} pos=({d:.2},{d:.2}) adv=({d:.2},{d:.2}) diff=({d:.2},{d:.2}) current cp={x}, cps={s}", .{
|
||||
// cluster,
|
||||
// x_offset,
|
||||
// y_offset,
|
||||
// advance_x_offset,
|
||||
// advance_y_offset,
|
||||
// x_offset_diff,
|
||||
// y_offset_diff,
|
||||
// state.codepoints.items[index].codepoint,
|
||||
// formatted_cps,
|
||||
// });
|
||||
//}
|
||||
|
||||
self.cell_buf.appendAssumeCapacity(.{
|
||||
.x = @intCast(cluster),
|
||||
|
|
@ -1332,7 +1335,7 @@ test "shape with empty cells in between" {
|
|||
}
|
||||
}
|
||||
|
||||
test "shape Chinese characters" {
|
||||
test "shape Combining characters" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
|
|
@ -1350,6 +1353,9 @@ test "shape Chinese characters" {
|
|||
var t = try terminal.Terminal.init(alloc, .{ .cols = 30, .rows = 3 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// Enable grapheme clustering
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
var s = t.vtStream();
|
||||
defer s.deinit();
|
||||
try s.nextSlice(buf[0..buf_idx]);
|
||||
|
|
@ -1397,6 +1403,9 @@ test "shape Devanagari string" {
|
|||
var t = try terminal.Terminal.init(alloc, .{ .cols = 30, .rows = 3 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// Disable grapheme clustering
|
||||
t.modes.set(.grapheme_cluster, false);
|
||||
|
||||
var s = t.vtStream();
|
||||
defer s.deinit();
|
||||
try s.nextSlice("अपार्टमेंट");
|
||||
|
|
@ -1429,6 +1438,62 @@ test "shape Devanagari string" {
|
|||
try testing.expect(try it.next(alloc) == null);
|
||||
}
|
||||
|
||||
test "shape Tai Tham vowels (position differs from advance)" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
// We need a font that supports Tai Tham for this to work, if we can't find
|
||||
// Noto Sans Tai Tham, which is a system font on macOS, we just skip the
|
||||
// test.
|
||||
var testdata = testShaperWithDiscoveredFont(
|
||||
alloc,
|
||||
"Noto Sans Tai Tham",
|
||||
) catch return error.SkipZigTest;
|
||||
defer testdata.deinit();
|
||||
|
||||
var buf: [32]u8 = undefined;
|
||||
var buf_idx: usize = 0;
|
||||
buf_idx += try std.unicode.utf8Encode(0x1a2F, buf[buf_idx..]); // ᨯ
|
||||
buf_idx += try std.unicode.utf8Encode(0x1a70, buf[buf_idx..]); // ᩰ
|
||||
|
||||
// Make a screen with some data
|
||||
var t = try terminal.Terminal.init(alloc, .{ .cols = 30, .rows = 3 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// Enable grapheme clustering
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
var s = t.vtStream();
|
||||
defer s.deinit();
|
||||
try s.nextSlice(buf[0..buf_idx]);
|
||||
|
||||
var state: terminal.RenderState = .empty;
|
||||
defer state.deinit(alloc);
|
||||
try state.update(alloc, &t);
|
||||
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(.{
|
||||
.grid = testdata.grid,
|
||||
.cells = state.row_data.get(0).cells.slice(),
|
||||
});
|
||||
var count: usize = 0;
|
||||
while (try it.next(alloc)) |run| {
|
||||
count += 1;
|
||||
|
||||
const cells = try shaper.shape(run);
|
||||
const cell_width = run.grid.metrics.cell_width;
|
||||
try testing.expectEqual(@as(usize, 2), cells.len);
|
||||
try testing.expectEqual(@as(u16, 0), cells[0].x);
|
||||
try testing.expectEqual(@as(u16, 0), cells[1].x);
|
||||
|
||||
// The first glyph renders in the next cell
|
||||
try testing.expectEqual(@as(i16, @intCast(cell_width)), cells[0].x_offset);
|
||||
try testing.expectEqual(@as(i16, 0), cells[1].x_offset);
|
||||
}
|
||||
try testing.expectEqual(@as(usize, 1), count);
|
||||
}
|
||||
|
||||
test "shape box glyphs" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
|
|
|||
|
|
@ -8893,7 +8893,7 @@ test "Terminal: insertBlanks shift graphemes" {
|
|||
var t = try init(alloc, .{ .rows = 5, .cols = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// Disable grapheme clustering
|
||||
// Enable grapheme clustering
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
try t.printString("A");
|
||||
|
|
|
|||
Loading…
Reference in New Issue