ghostty/src/terminal/new/page.zig
2024-03-22 20:27:16 -07:00

110 lines
4.0 KiB
Zig

const std = @import("std");
const assert = std.debug.assert;
const color = @import("../color.zig");
const sgr = @import("../sgr.zig");
const style = @import("style.zig");
const size = @import("size.zig");
const Offset = size.Offset;
const hash_map = @import("hash_map.zig");
const AutoOffsetHashMap = hash_map.AutoOffsetHashMap;
/// A page represents a specific section of terminal screen. The primary
/// idea of a page is that it is a fully self-contained unit that can be
/// serialized, copied, etc. as a convenient way to represent a section
/// of the screen.
///
/// This property is useful for renderers which want to copy just the pages
/// for the visible portion of the screen, or for infinite scrollback where
/// we may want to serialize and store pages that are sufficiently far
/// away from the current viewport.
///
/// Pages are always backed by a single contiguous block of memory that is
/// aligned on a page boundary. This makes it easy and fast to copy pages
/// around. Within the contiguous block of memory, the contents of a page are
/// thoughtfully laid out to optimize primarily for terminal IO (VT streams)
/// and to minimize memory usage.
pub const Page = struct {
/// The backing memory for the page. A page is always made up of a
/// a single contiguous block of memory that is aligned on a page
/// boundary and is a multiple of the system page size.
///
/// The backing memory is always zero initialized, so the zero value
/// of all data within the page must always be valid.
memory: []align(std.mem.page_size) u8,
/// The array of rows in the page. The rows are always in row order
/// (i.e. index 0 is the top row, index 1 is the row below that, etc.)
rows: Offset(Row),
/// The array of cells in the page. The cells are NOT in row order,
/// but they are in column order. To determine the mapping of cells
/// to row, you must use the `rows` field. From the pointer to the
/// first column, all cells in that row are laid out in column order.
cells: Offset(Cell),
};
pub const Row = packed struct {
/// The cells in the row offset from the page.
cells: Offset(Cell),
};
/// A cell represents a single terminal grid cell.
///
/// The zero value of this struct must be a valid cell representing empty,
/// since we zero initialize the backing memory for a page.
pub const Cell = packed struct(u32) {
codepoint: u21 = 0,
};
/// The style attributes for a cell.
pub const Style = struct {
/// Various colors, all self-explanatory.
fg_color: Color = .none,
bg_color: Color = .none,
underline_color: Color = .none,
/// On/off attributes that don't require much bit width so we use
/// a packed struct to make this take up significantly less space.
flags: packed struct {
bold: bool = false,
italic: bool = false,
faint: bool = false,
blink: bool = false,
inverse: bool = false,
invisible: bool = false,
strikethrough: bool = false,
underline: sgr.Attribute.Underline = .none,
} = .{},
/// The color for an SGR attribute. A color can come from multiple
/// sources so we use this to track the source plus color value so that
/// we can properly react to things like palette changes.
pub const Color = union(enum) {
none: void,
palette: u8,
rgb: color.RGB,
};
test {
// The size of the struct so we can be aware of changes.
const testing = std.testing;
try testing.expectEqual(@as(usize, 14), @sizeOf(Style));
}
};
test {
_ = Page;
_ = Style;
}
// test {
// const testing = std.testing;
// const cap = try std.math.ceilPowerOfTwo(usize, 350);
// const StyleIdMap = AutoOffsetHashMap(size.CellCountInt, style.Style);
// const StyleMetadataMap = AutoOffsetHashMap(style.Style, style.Metadata);
//
// var len = StyleIdMap.bufferSize(@intCast(cap));
// len += StyleMetadataMap.bufferSize(@intCast(cap));
// try testing.expectEqual(@as(usize, 0), len);
// }