Fix off-by-one error & adjust overline pos in cell height mod

pull/8022/head
Daniel Wennberg 2025-07-21 21:23:02 -07:00
parent 820879d2ef
commit 53b029284d
1 changed files with 38 additions and 19 deletions

View File

@ -235,17 +235,26 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void {
// centered in the cell.
if (comptime tag == .cell_height) {
// We split the difference in half because we want to
// center the baseline in the cell.
// center the baseline in the cell. We round the shift
// down to the nearest full pixel shift, such that if
// the diff is odd, there's one more pixel added/removed
// on top than on the bottom.
if (new > original) {
const diff = (new - original) / 2;
self.cell_baseline +|= diff;
self.underline_position +|= diff;
self.strikethrough_position +|= diff;
const diff = new - original;
const diff_bottom = diff / 2;
const diff_top = diff - diff_bottom;
self.cell_baseline +|= diff_bottom;
self.underline_position +|= diff_top;
self.strikethrough_position +|= diff_top;
self.overline_position +|= @as(i32, @intCast(diff_top));
} else {
const diff = (original - new) / 2;
self.cell_baseline -|= diff;
self.underline_position -|= diff;
self.strikethrough_position -|= diff;
const diff = original - new;
const diff_bottom = diff / 2;
const diff_top = diff - diff_bottom;
self.cell_baseline -|= diff_bottom;
self.underline_position -|= diff_top;
self.strikethrough_position -|= diff_top;
self.overline_position -|= @as(i32, @intCast(diff_top));
}
}
},
@ -463,19 +472,24 @@ test "Metrics: adjust cell height smaller" {
var set: ModifierSet = .{};
defer set.deinit(alloc);
try set.put(alloc, .cell_height, .{ .percent = 0.5 });
// We choose numbers such that the subtracted number of pixels is odd,
// as that's the case that could most easily have off-by-one errors.
// Here we're removing 25 pixels: 12 on the bottom, 13 on top.
try set.put(alloc, .cell_height, .{ .percent = 0.75 });
var m: Metrics = init();
m.cell_baseline = 50;
m.underline_position = 55;
m.strikethrough_position = 30;
m.overline_position = 0;
m.cell_height = 100;
m.cursor_height = 100;
m.apply(set);
try testing.expectEqual(@as(u32, 50), m.cell_height);
try testing.expectEqual(@as(u32, 25), m.cell_baseline);
try testing.expectEqual(@as(u32, 30), m.underline_position);
try testing.expectEqual(@as(u32, 5), m.strikethrough_position);
try testing.expectEqual(@as(u32, 75), m.cell_height);
try testing.expectEqual(@as(u32, 38), m.cell_baseline);
try testing.expectEqual(@as(u32, 42), m.underline_position);
try testing.expectEqual(@as(u32, 17), m.strikethrough_position);
try testing.expectEqual(@as(i32, -13), m.overline_position);
// Cursor height is separate from cell height and does not follow it.
try testing.expectEqual(@as(u32, 100), m.cursor_height);
}
@ -486,19 +500,24 @@ test "Metrics: adjust cell height larger" {
var set: ModifierSet = .{};
defer set.deinit(alloc);
try set.put(alloc, .cell_height, .{ .percent = 2 });
// We choose numbers such that the added number of pixels is odd,
// as that's the case that could most easily have off-by-one errors.
// Here we're adding 75 pixels: 37 on the bottom, 38 on top.
try set.put(alloc, .cell_height, .{ .percent = 1.75 });
var m: Metrics = init();
m.cell_baseline = 50;
m.underline_position = 55;
m.strikethrough_position = 30;
m.overline_position = 0;
m.cell_height = 100;
m.cursor_height = 100;
m.apply(set);
try testing.expectEqual(@as(u32, 200), m.cell_height);
try testing.expectEqual(@as(u32, 100), m.cell_baseline);
try testing.expectEqual(@as(u32, 105), m.underline_position);
try testing.expectEqual(@as(u32, 80), m.strikethrough_position);
try testing.expectEqual(@as(u32, 175), m.cell_height);
try testing.expectEqual(@as(u32, 87), m.cell_baseline);
try testing.expectEqual(@as(u32, 93), m.underline_position);
try testing.expectEqual(@as(u32, 68), m.strikethrough_position);
try testing.expectEqual(@as(i32, 38), m.overline_position);
// Cursor height is separate from cell height and does not follow it.
try testing.expectEqual(@as(u32, 100), m.cursor_height);
}