font: shaper dynamically allocates cell buffer

Pathlogical grapheme clusters can use a LOT of memory, so we need to be
able to grow.
This commit is contained in:
Mitchell Hashimoto
2023-09-26 17:57:50 -07:00
parent 0c9799ba61
commit 5c1fbd09cd
4 changed files with 54 additions and 99 deletions

View File

@@ -218,10 +218,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
// Create the font shaper. We initially create a shaper that can support
// a width of 160 which is a common width for modern screens to help
// avoid allocations later.
var shape_buf = try alloc.alloc(font.shape.Cell, 160);
errdefer alloc.free(shape_buf);
var font_shaper = try font.Shaper.init(alloc, .{
.cell_buf = shape_buf,
.features = options.config.font_features.items,
});
errdefer font_shaper.deinit();
@@ -288,7 +285,6 @@ pub fn deinit(self: *Metal) void {
self.cells_bg.deinit(self.alloc);
self.font_shaper.deinit();
self.alloc.free(self.font_shaper.cell_buf);
self.config.deinit();
@@ -417,14 +413,6 @@ pub fn setFontSize(self: *Metal, size: font.face.DesiredSize) !void {
if (std.meta.eql(self.cell_size, new_cell_size)) return;
self.cell_size = new_cell_size;
// Resize our font shaping buffer to fit the new width.
if (self.gridSize()) |grid_size| {
var shape_buf = try self.alloc.alloc(font.shape.Cell, grid_size.columns * 2);
errdefer self.alloc.free(shape_buf);
self.alloc.free(self.font_shaper.cell_buf);
self.font_shaper.cell_buf = shape_buf;
}
// Set the sprite font up
self.font_group.group.sprite = font.sprite.Face{
.width = self.cell_size.width,
@@ -998,7 +986,6 @@ pub fn changeConfig(self: *Metal, config: *DerivedConfig) !void {
// easier and rare enough to not cause performance issues.
{
var font_shaper = try font.Shaper.init(self.alloc, .{
.cell_buf = self.font_shaper.cell_buf,
.features = config.font_features.items,
});
errdefer font_shaper.deinit();
@@ -1033,13 +1020,6 @@ pub fn setScreenSize(
.{});
const padded_dim = dim.subPadding(padding);
// Update our shaper
// TODO: don't reallocate if it is close enough (but bigger)
var shape_buf = try self.alloc.alloc(font.shape.Cell, grid_size.columns * 2);
errdefer self.alloc.free(shape_buf);
self.alloc.free(self.font_shaper.cell_buf);
self.font_shaper.cell_buf = shape_buf;
// Set the size of the drawable surface to the bounds
self.swapchain.setProperty("drawableSize", macos.graphics.Size{
.width = @floatFromInt(dim.width),

View File

@@ -280,10 +280,7 @@ pub const DerivedConfig = struct {
pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
// Create the initial font shaper
var shape_buf = try alloc.alloc(font.shape.Cell, 1);
errdefer alloc.free(shape_buf);
var shaper = try font.Shaper.init(alloc, .{
.cell_buf = shape_buf,
.features = options.config.font_features.items,
});
errdefer shaper.deinit();
@@ -318,7 +315,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
pub fn deinit(self: *OpenGL) void {
self.font_shaper.deinit();
self.alloc.free(self.font_shaper.cell_buf);
if (self.gl_state) |*v| v.deinit();
@@ -525,15 +521,6 @@ pub fn setFontSize(self: *OpenGL, size: font.face.DesiredSize) !void {
if (std.meta.eql(self.cell_size, new_cell_size)) return;
self.cell_size = new_cell_size;
// Resize our font shaping buffer to fit the new width.
if (self.screen_size) |dim| {
const grid_size = self.gridSize(dim);
var shape_buf = try self.alloc.alloc(font.shape.Cell, grid_size.columns * 2);
errdefer self.alloc.free(shape_buf);
self.alloc.free(self.font_shaper.cell_buf);
self.font_shaper.cell_buf = shape_buf;
}
// Notify the window that the cell size changed.
_ = self.surface_mailbox.push(.{
.cell_size = new_cell_size,
@@ -1228,7 +1215,6 @@ pub fn changeConfig(self: *OpenGL, config: *DerivedConfig) !void {
// easier and rare enough to not cause performance issues.
{
var font_shaper = try font.Shaper.init(self.alloc, .{
.cell_buf = self.font_shaper.cell_buf,
.features = config.font_features.items,
});
errdefer font_shaper.deinit();
@@ -1264,12 +1250,6 @@ pub fn setScreenSize(
self.padding.explicit,
});
// Update our shaper
var shape_buf = try self.alloc.alloc(font.shape.Cell, grid_size.columns * 2);
errdefer self.alloc.free(shape_buf);
self.alloc.free(self.font_shaper.cell_buf);
self.font_shaper.cell_buf = shape_buf;
// Defer our OpenGL updates
self.deferred_screen_size = .{ .size = dim };
}