terminal/new: page has graphemes attached

This commit is contained in:
Mitchell Hashimoto
2024-02-21 10:33:50 -08:00
parent ed6a31a692
commit f8f9f74a8e
3 changed files with 56 additions and 5 deletions

View File

@ -125,7 +125,7 @@ pub fn BitmapAllocator(comptime chunk_size: comptime_int) type {
} }
} }
const Layout = struct { pub const Layout = struct {
total_size: usize, total_size: usize,
bitmap_count: usize, bitmap_count: usize,
bitmap_start: usize, bitmap_start: usize,

View File

@ -8,6 +8,7 @@ const size = @import("size.zig");
const getOffset = size.getOffset; const getOffset = size.getOffset;
const Offset = size.Offset; const Offset = size.Offset;
const OffsetBuf = size.OffsetBuf; const OffsetBuf = size.OffsetBuf;
const BitmapAllocator = @import("bitmap_allocator.zig").BitmapAllocator;
const hash_map = @import("hash_map.zig"); const hash_map = @import("hash_map.zig");
const AutoOffsetHashMap = hash_map.AutoOffsetHashMap; const AutoOffsetHashMap = hash_map.AutoOffsetHashMap;
const alignForward = std.mem.alignForward; const alignForward = std.mem.alignForward;
@ -57,7 +58,8 @@ pub const Page = struct {
/// any cell that has more than one codepoint will be stored. This is /// any cell that has more than one codepoint will be stored. This is
/// relatively rare (typically only emoji) so this defaults to a very small /// relatively rare (typically only emoji) so this defaults to a very small
/// size and we force page realloc when it grows. /// size and we force page realloc when it grows.
__todo_graphemes: void = {}, grapheme_alloc: GraphemeAlloc,
grapheme_map: GraphemeMap,
/// The available set of styles in use on this page. /// The available set of styles in use on this page.
styles: style.Set, styles: style.Set,
@ -65,6 +67,18 @@ pub const Page = struct {
/// The capacity of this page. /// The capacity of this page.
capacity: Capacity, capacity: Capacity,
/// The allocator to use for multi-codepoint grapheme data. We use
/// a chunk size of 4 codepoints. It'd be best to set this empirically
/// but it is currently set based on vibes. My thinking around 4 codepoints
/// is that most skin-tone emoji are <= 4 codepoints, letter combiners
/// are usually <= 4 codepoints, and 4 codepoints is a nice power of two
/// for alignment.
const grapheme_chunk = 4 * @sizeOf(u21);
const GraphemeAlloc = BitmapAllocator(grapheme_chunk);
const grapheme_count_default = GraphemeAlloc.bitmap_bit_size;
const grapheme_bytes_default = grapheme_count_default * grapheme_chunk;
const GraphemeMap = AutoOffsetHashMap(Offset(Cell), Offset(u21).Slice);
/// Capacity of this page. /// Capacity of this page.
pub const Capacity = struct { pub const Capacity = struct {
/// Number of columns and rows we can know about. /// Number of columns and rows we can know about.
@ -72,7 +86,10 @@ pub const Page = struct {
rows: usize, rows: usize,
/// Number of unique styles that can be used on this page. /// Number of unique styles that can be used on this page.
styles: u16, styles: u16 = 16,
/// Number of bytes to allocate for grapheme data.
grapheme_bytes: usize = grapheme_bytes_default,
}; };
/// Initialize a new page, allocating the required backing memory. /// Initialize a new page, allocating the required backing memory.
@ -103,7 +120,18 @@ pub const Page = struct {
.memory = backing, .memory = backing,
.rows = rows, .rows = rows,
.cells = cells, .cells = cells,
.styles = style.Set.init(buf.add(l.styles_start), l.styles_layout), .styles = style.Set.init(
buf.add(l.styles_start),
l.styles_layout,
),
.grapheme_alloc = GraphemeAlloc.init(
buf.add(l.grapheme_alloc_start),
l.grapheme_alloc_layout,
),
.grapheme_map = GraphemeMap.init(
buf.add(l.grapheme_map_start),
l.grapheme_map_layout,
),
.capacity = cap, .capacity = cap,
}; };
} }
@ -153,6 +181,10 @@ pub const Page = struct {
cells_start: usize, cells_start: usize,
styles_start: usize, styles_start: usize,
styles_layout: style.Set.Layout, styles_layout: style.Set.Layout,
grapheme_alloc_start: usize,
grapheme_alloc_layout: GraphemeAlloc.Layout,
grapheme_map_start: usize,
grapheme_map_layout: GraphemeMap.Layout,
}; };
/// The memory layout for a page given a desired minimum cols /// The memory layout for a page given a desired minimum cols
@ -169,7 +201,16 @@ pub const Page = struct {
const styles_start = alignForward(usize, cells_end, style.Set.base_align); const styles_start = alignForward(usize, cells_end, style.Set.base_align);
const styles_end = styles_start + styles_layout.total_size; const styles_end = styles_start + styles_layout.total_size;
const total_size = styles_end; const grapheme_alloc_layout = GraphemeAlloc.layout(cap.grapheme_bytes);
const grapheme_alloc_start = alignForward(usize, styles_end, GraphemeAlloc.base_align);
const grapheme_alloc_end = grapheme_alloc_start + grapheme_alloc_layout.total_size;
const grapheme_count = @divFloor(cap.grapheme_bytes, grapheme_chunk);
const grapheme_map_layout = GraphemeMap.layout(@intCast(grapheme_count));
const grapheme_map_start = alignForward(usize, grapheme_alloc_end, GraphemeMap.base_align);
const grapheme_map_end = grapheme_map_start + grapheme_map_layout.total_size;
const total_size = grapheme_map_end;
return .{ return .{
.total_size = total_size, .total_size = total_size,
@ -177,6 +218,10 @@ pub const Page = struct {
.cells_start = cells_start, .cells_start = cells_start,
.styles_start = styles_start, .styles_start = styles_start,
.styles_layout = styles_layout, .styles_layout = styles_layout,
.grapheme_alloc_start = grapheme_alloc_start,
.grapheme_alloc_layout = grapheme_alloc_layout,
.grapheme_map_start = grapheme_map_start,
.grapheme_map_layout = grapheme_map_layout,
}; };
} }
}; };

View File

@ -24,6 +24,12 @@ pub fn Offset(comptime T: type) type {
offset: OffsetInt = 0, offset: OffsetInt = 0,
/// A slice of type T that stores via a base offset and len.
pub const Slice = struct {
offset: Self,
len: usize,
};
/// Returns a pointer to the start of the data, properly typed. /// Returns a pointer to the start of the data, properly typed.
pub fn ptr(self: Self, base: anytype) [*]T { pub fn ptr(self: Self, base: anytype) [*]T {
// The offset must be properly aligned for the type since // The offset must be properly aligned for the type since