a73x

ae38f777

Render actual cell colors

a73x   2026-04-08 11:53


diff --git a/src/main.zig b/src/main.zig
index abb172e..02f4d78 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -198,13 +198,15 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
        const term_rows = term.render_state.row_data.items(.cells);
        var row_idx: u32 = 0;
        while (row_idx < term_rows.len) : (row_idx += 1) {
            const raw_cells = term_rows[row_idx].items(.raw);
            const row_cells = term_rows[row_idx];
            const raw_cells = row_cells.items(.raw);
            var col_idx: u32 = 0;
            while (col_idx < raw_cells.len) : (col_idx += 1) {
                const cp = raw_cells[col_idx].codepoint();
                if (cp == 0 or cp == ' ') continue;

                const uv = atlas.getOrInsert(&face, @intCast(cp)) catch continue;
                const colors = term.cellColors(row_cells.get(col_idx));

                try instances.append(alloc, .{
                    .cell_pos = .{ @floatFromInt(col_idx), @floatFromInt(row_idx) },
@@ -216,8 +218,8 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
                        @as(f32, @floatFromInt(cell_h)) - @as(f32, @floatFromInt(uv.bearing_y)),
                    },
                    .uv_rect = .{ uv.u0, uv.v0, uv.u1, uv.v1 },
                    .fg = .{ 0.9, 0.9, 0.9, 1.0 },
                    .bg = .{ 0.08, 0.08, 0.08, 1.0 },
                    .fg = colors.fg,
                    .bg = colors.bg,
                });
            }
        }
diff --git a/src/vt.zig b/src/vt.zig
index 71c55bf..cf18589 100644
--- a/src/vt.zig
+++ b/src/vt.zig
@@ -53,6 +53,10 @@ const ghostty_vt = @import("ghostty-vt");
pub const InputAction = ghostty_vt.input.KeyAction;
pub const InputKey = ghostty_vt.input.Key;
pub const InputMods = ghostty_vt.input.KeyMods;
pub const CellColors = struct {
    fg: [4]f32,
    bg: [4]f32,
};

pub const Terminal = struct {
    alloc: std.mem.Allocator,
@@ -126,6 +130,26 @@ pub const Terminal = struct {
        return writer.buffered();
    }

    pub fn cellColors(
        self: *const Terminal,
        cell: ghostty_vt.RenderState.Cell,
    ) CellColors {
        const style: ghostty_vt.Style = switch (cell.raw.content_tag) {
            .bg_color_palette, .bg_color_rgb => cell.style,
            else => if (cell.raw.style_id != 0) cell.style else .{},
        };
        const colors = self.render_state.colors;
        const fg = style.fg(.{
            .default = colors.foreground,
            .palette = &colors.palette,
        });
        const bg = style.bg(&cell.raw, &colors.palette) orelse colors.background;
        return .{
            .fg = rgbToFloat4(fg),
            .bg = rgbToFloat4(bg),
        };
    }

    pub fn resize(self: *Terminal, new_cols: u16, new_rows: u16) !void {
        try self.inner.resize(self.alloc, @intCast(new_cols), @intCast(new_rows));
    }
@@ -145,6 +169,15 @@ pub const Terminal = struct {
    }
};

fn rgbToFloat4(rgb: ghostty_vt.color.RGB) [4]f32 {
    return .{
        @as(f32, @floatFromInt(rgb.r)) / 255.0,
        @as(f32, @floatFromInt(rgb.g)) / 255.0,
        @as(f32, @floatFromInt(rgb.b)) / 255.0,
        1.0,
    };
}

test "Terminal init/deinit" {
    var term = try Terminal.init(std.testing.allocator, .{
        .cols = 80,
@@ -191,3 +224,21 @@ test "Terminal encodes non-text arrow keys" {
    const encoded = try term.encodeKey(.arrow_left, .{}, .press, &buf);
    try std.testing.expectEqualStrings("\x1b[D", encoded);
}

test "Terminal resolves ANSI fg and bg colors from render state" {
    var term = try Terminal.init(std.testing.allocator, .{
        .cols = 80,
        .rows = 24,
    });
    defer term.deinit();

    term.write("\x1b[31;44mA\x1b[0m");
    try term.snapshot();

    const cell = term.render_state.row_data.get(0).cells.get(0);
    const colors = term.cellColors(cell);
    const palette = term.render_state.colors.palette;

    try std.testing.expectEqualDeep(rgbToFloat4(palette[1]), colors.fg);
    try std.testing.expectEqualDeep(rgbToFloat4(palette[4]), colors.bg);
}