a73x

430800c8

Improve glyph positioning

a73x   2026-04-08 11:58


diff --git a/src/font.zig b/src/font.zig
index ed0f60d..6be6a1f 100644
--- a/src/font.zig
+++ b/src/font.zig
@@ -138,6 +138,11 @@ pub const Face = struct {
        const metrics = self.face.*.size.*.metrics;
        return @intCast((metrics.ascender - metrics.descender) >> 6);
    }

    pub fn baseline(self: *Face) u32 {
        const metrics = self.face.*.size.*.metrics;
        return @intCast(metrics.ascender >> 6);
    }
};

pub const GlyphUV = struct {
diff --git a/src/main.zig b/src/main.zig
index 591cb85..1060bb3 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -56,6 +56,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {

    const cell_w = face.cellWidth();
    const cell_h = face.cellHeight();
    const baseline = face.baseline();

    // === grid size ===
    const initial_grid: GridSize = .{ .cols = 80, .rows = 24 };
@@ -218,6 +219,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
                    col_idx,
                    cell_w,
                    cell_h,
                    baseline,
                    glyph_uv,
                    bg_uv,
                    colors,
@@ -286,6 +288,7 @@ fn appendCellInstances(
    col_idx: u32,
    cell_w: u32,
    cell_h: u32,
    baseline: u32,
    glyph_uv: ?font.GlyphUV,
    bg_uv: font.GlyphUV,
    colors: vt.CellColors,
@@ -308,7 +311,7 @@ fn appendCellInstances(
        .glyph_size = .{ @floatFromInt(uv.width), @floatFromInt(uv.height) },
        .glyph_bearing = .{
            @floatFromInt(uv.bearing_x),
            @as(f32, @floatFromInt(cell_h)) - @as(f32, @floatFromInt(uv.bearing_y)),
            glyphTopOffset(baseline, uv.bearing_y),
        },
        .uv_rect = .{ uv.u0, uv.v0, uv.u1, uv.v1 },
        .fg = colors.fg,
@@ -316,6 +319,10 @@ fn appendCellInstances(
    });
}

fn glyphTopOffset(baseline: u32, bearing_y: i32) f32 {
    return @as(f32, @floatFromInt(baseline)) - @as(f32, @floatFromInt(bearing_y));
}

fn encodeKeyboardEvent(
    term: *const vt.Terminal,
    ev: wayland_client.KeyboardEvent,
@@ -416,6 +423,7 @@ fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
    // Cell size from font metrics
    const cell_w: f32 = @floatFromInt(face.cellWidth());
    const cell_h: f32 = @floatFromInt(face.cellHeight());
    const baseline = face.baseline();
    std.debug.print("cell size: {d}x{d}\n", .{ cell_w, cell_h });

    // One Instance: 'M' at cell position (40, 12) — near center of 80x24 grid
@@ -425,7 +433,7 @@ fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
            .glyph_size = .{ @floatFromInt(glyph_uv.width), @floatFromInt(glyph_uv.height) },
            .glyph_bearing = .{
                @floatFromInt(glyph_uv.bearing_x),
                @as(f32, @floatFromInt(face.cellHeight())) - @as(f32, @floatFromInt(glyph_uv.bearing_y)),
                glyphTopOffset(baseline, glyph_uv.bearing_y),
            },
            .uv_rect = .{ glyph_uv.u0, glyph_uv.v0, glyph_uv.u1, glyph_uv.v1 },
            .fg = .{ 1.0, 1.0, 1.0, 1.0 },
@@ -503,6 +511,7 @@ test "appendCellInstances emits a background quad for colored space" {
        3,
        8,
        16,
        12,
        null,
        bg_uv,
        .{
@@ -552,6 +561,7 @@ test "appendCellInstances emits background before glyph" {
        1,
        8,
        16,
        12,
        glyph_uv,
        bg_uv,
        .{
@@ -566,6 +576,11 @@ test "appendCellInstances emits background before glyph" {
    try std.testing.expectEqualDeep([2]f32{ 7.0, 11.0 }, instances.items[1].glyph_size);
    try std.testing.expectEqualDeep([4]f32{ 0.1, 0.2, 0.3, 1.0 }, instances.items[0].fg);
    try std.testing.expectEqualDeep([4]f32{ 0.9, 0.8, 0.7, 1.0 }, instances.items[1].fg);
    try std.testing.expectEqualDeep([2]f32{ 1.0, -1.0 }, instances.items[1].glyph_bearing);
}

test "glyphTopOffset uses baseline rather than cell height" {
    try std.testing.expectEqual(@as(f32, -3.0), glyphTopOffset(9, 12));
}

fn runRenderSmokeTest(alloc: std.mem.Allocator) !void {