mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-24 16:11:43 +00:00
font/coretext: creation functions can return null, handle OOM (#13679)
Catch NULL results from CoreFoundation/CoreText creation functions and return error.OOM rather than null derefs later. I verified that this is possible but didn't verify the behavior when it happens, this is just defensive based on the report here: #13671 because it costs us nothing really.
This commit is contained in:
@@ -21,13 +21,13 @@ pub const String = opaque {
|
||||
|
||||
pub fn createWithCharactersNoCopy(
|
||||
unichars: []const u16,
|
||||
) *String {
|
||||
return @as(*String, @ptrFromInt(@intFromPtr(c.CFStringCreateWithCharactersNoCopy(
|
||||
) Allocator.Error!*String {
|
||||
return @ptrCast(@constCast(c.CFStringCreateWithCharactersNoCopy(
|
||||
null,
|
||||
@ptrCast(unichars.ptr),
|
||||
@intCast(unichars.len),
|
||||
foundation.c.kCFAllocatorNull,
|
||||
))));
|
||||
) orelse return error.OutOfMemory));
|
||||
}
|
||||
|
||||
pub fn release(self: *String) void {
|
||||
|
||||
@@ -27,10 +27,10 @@ pub const Typesetter = opaque {
|
||||
pub fn createLine(
|
||||
self: *Typesetter,
|
||||
range: foundation.c.CFRange,
|
||||
) *text.Line {
|
||||
return @ptrFromInt(@intFromPtr(c.CTTypesetterCreateLine(
|
||||
) Allocator.Error!*text.Line {
|
||||
return @ptrCast(@constCast(c.CTTypesetterCreateLine(
|
||||
@ptrCast(self),
|
||||
range,
|
||||
)));
|
||||
) orelse return error.OutOfMemory));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -361,7 +361,7 @@ pub const Shaper = struct {
|
||||
// Make room for the attributed string, CTTypesetter, and CTLine.
|
||||
try self.cf_release_pool.ensureUnusedCapacity(self.alloc, 4);
|
||||
|
||||
const str = macos.foundation.String.createWithCharactersNoCopy(state.unichars.items);
|
||||
const str = try macos.foundation.String.createWithCharactersNoCopy(state.unichars.items);
|
||||
self.cf_release_pool.appendAssumeCapacity(str);
|
||||
|
||||
// Create an attributed string from our string
|
||||
@@ -381,7 +381,7 @@ pub const Shaper = struct {
|
||||
self.cf_release_pool.appendAssumeCapacity(typesetter);
|
||||
|
||||
// Create a line from the typesetter
|
||||
const line = typesetter.createLine(.{ .location = 0, .length = 0 });
|
||||
const line = try typesetter.createLine(.{ .location = 0, .length = 0 });
|
||||
self.cf_release_pool.appendAssumeCapacity(line);
|
||||
|
||||
// This keeps track of the current x offset (sum of advance.width) and
|
||||
|
||||
@@ -1146,6 +1146,11 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
state: *renderer.State,
|
||||
cursor_blink_visible: bool,
|
||||
) Allocator.Error!void {
|
||||
// CoreText shaping accumulates objects for deferred release over
|
||||
// the course of a frame. Always flush those objects, including
|
||||
// when rebuilding the frame fails due to memory pressure.
|
||||
defer self.font_shaper.endFrame();
|
||||
|
||||
// We fully deinit and reset the terminal state every so often
|
||||
// so that a particularly large terminal state doesn't cause
|
||||
// the renderer to hold on to retained memory.
|
||||
@@ -1444,10 +1449,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
// Update custom shader uniforms that depend on terminal state.
|
||||
self.updateCustomShaderUniformsFromState();
|
||||
}
|
||||
|
||||
// Notify our shaper we're done for the frame. For some shapers,
|
||||
// such as CoreText, this triggers off-thread cleanup logic.
|
||||
self.font_shaper.endFrame();
|
||||
}
|
||||
|
||||
/// Draw the frame to the screen.
|
||||
|
||||
Reference in New Issue
Block a user