mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
terminal/page: improved capacity adjust logic
This commit is contained in:

committed by
Mitchell Hashimoto

parent
fd9280429e
commit
9630c39ea4
@ -15,6 +15,7 @@ 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;
|
||||||
|
const alignBackward = std.mem.alignBackward;
|
||||||
|
|
||||||
/// The allocator to use for multi-codepoint grapheme data. We use
|
/// 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
|
/// a chunk size of 4 codepoints. It'd be best to set this empirically
|
||||||
@ -587,16 +588,39 @@ pub const Capacity = struct {
|
|||||||
pub fn adjust(self: Capacity, req: Adjustment) Allocator.Error!Capacity {
|
pub fn adjust(self: Capacity, req: Adjustment) Allocator.Error!Capacity {
|
||||||
var adjusted = self;
|
var adjusted = self;
|
||||||
if (req.cols) |cols| {
|
if (req.cols) |cols| {
|
||||||
// The calculations below only work if cells/rows match size.
|
// The math below only works if there is no alignment gap between
|
||||||
assert(@sizeOf(Cell) == @sizeOf(Row));
|
// the end of the rows array and the start of the cells array.
|
||||||
|
//
|
||||||
|
// To guarantee this, we assert that Row's size is a multiple of
|
||||||
|
// Cell's alignment, so that any length array of Rows will end on
|
||||||
|
// a valid alignment for the start of the Cell array.
|
||||||
|
assert(@sizeOf(Row) % @alignOf(Cell) == 0);
|
||||||
|
|
||||||
// total_size = (Nrows * sizeOf(Row)) + (Nrows * Ncells * sizeOf(Cell))
|
|
||||||
// with some algebra:
|
|
||||||
// Nrows = total_size / (sizeOf(Row) + (Ncells * sizeOf(Cell)))
|
|
||||||
const layout = Page.layout(self);
|
const layout = Page.layout(self);
|
||||||
const total_size = layout.rows_size + layout.cells_size;
|
|
||||||
const denom = @sizeOf(Row) + (@sizeOf(Cell) * @as(usize, @intCast(cols)));
|
// In order to determine the amount of space in the page available
|
||||||
const new_rows = @divFloor(total_size, denom);
|
// for rows & cells (which will allow us to calculate the number of
|
||||||
|
// rows we can fit at a certain column width) we need to layout the
|
||||||
|
// "meta" members of the page (i.e. everything else) from the end.
|
||||||
|
const grapheme_map_start = alignBackward(
|
||||||
|
usize,
|
||||||
|
layout.total_size - layout.grapheme_map_layout.total_size,
|
||||||
|
GraphemeMap.base_align
|
||||||
|
);
|
||||||
|
const grapheme_alloc_start = alignBackward(
|
||||||
|
usize,
|
||||||
|
grapheme_map_start - layout.grapheme_alloc_layout.total_size,
|
||||||
|
GraphemeAlloc.base_align
|
||||||
|
);
|
||||||
|
const styles_start = alignBackward(
|
||||||
|
usize,
|
||||||
|
grapheme_alloc_start - layout.styles_layout.total_size,
|
||||||
|
style.Set.base_align
|
||||||
|
);
|
||||||
|
|
||||||
|
const available_size = styles_start;
|
||||||
|
const size_per_row = @sizeOf(Row) + (@sizeOf(Cell) * @as(usize, @intCast(cols)));
|
||||||
|
const new_rows = @divFloor(available_size, size_per_row);
|
||||||
|
|
||||||
// If our rows go to zero then we can't fit any row metadata
|
// If our rows go to zero then we can't fit any row metadata
|
||||||
// for the desired number of columns.
|
// for the desired number of columns.
|
||||||
@ -606,24 +630,6 @@ pub const Capacity = struct {
|
|||||||
adjusted.rows = @intCast(new_rows);
|
adjusted.rows = @intCast(new_rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust our rows so that we have an exact total size count.
|
|
||||||
// I think we could do this with basic math but my grade school
|
|
||||||
// algebra skills are failing me and I'm embarassed so please someone
|
|
||||||
// fix this. This is tested so you can fiddle around.
|
|
||||||
const old_size = Page.layout(self).total_size;
|
|
||||||
var new_size = Page.layout(adjusted).total_size;
|
|
||||||
while (old_size != new_size) {
|
|
||||||
// Our math above is usually PRETTY CLOSE (like within 1 row)
|
|
||||||
// so we can just adjust by 1 row at a time.
|
|
||||||
if (new_size > old_size) {
|
|
||||||
adjusted.rows -= 1;
|
|
||||||
} else {
|
|
||||||
adjusted.rows += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_size = Page.layout(adjusted).total_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjusted;
|
return adjusted;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user