diff --git a/pkg/macos/text/run.zig b/pkg/macos/text/run.zig index 9d40de81f..2895bfe34 100644 --- a/pkg/macos/text/run.zig +++ b/pkg/macos/text/run.zig @@ -15,10 +15,13 @@ pub const Run = opaque { return @intCast(c.CTRunGetGlyphCount(@ptrCast(self))); } - pub fn getGlyphsPtr(self: *Run) []const graphics.Glyph { + pub fn getGlyphsPtr(self: *Run) ?[]const graphics.Glyph { const len = self.getGlyphCount(); if (len == 0) return &.{}; - const ptr = c.CTRunGetGlyphsPtr(@ptrCast(self)) orelse &.{}; + const ptr: [*c]const graphics.Glyph = @ptrCast( + c.CTRunGetGlyphsPtr(@ptrCast(self)), + ); + if (ptr == null) return null; return ptr[0..len]; } @@ -34,10 +37,13 @@ pub const Run = opaque { return ptr; } - pub fn getPositionsPtr(self: *Run) []const graphics.Point { + pub fn getPositionsPtr(self: *Run) ?[]const graphics.Point { const len = self.getGlyphCount(); if (len == 0) return &.{}; - const ptr = c.CTRunGetPositionsPtr(@ptrCast(self)) orelse &.{}; + const ptr: [*c]const graphics.Point = @ptrCast( + c.CTRunGetPositionsPtr(@ptrCast(self)), + ); + if (ptr == null) return null; return ptr[0..len]; } @@ -53,10 +59,13 @@ pub const Run = opaque { return ptr; } - pub fn getAdvancesPtr(self: *Run) []const graphics.Size { + pub fn getAdvancesPtr(self: *Run) ?[]const graphics.Size { const len = self.getGlyphCount(); if (len == 0) return &.{}; - const ptr = c.CTRunGetAdvancesPtr(@ptrCast(self)) orelse &.{}; + const ptr: [*c]const graphics.Size = @ptrCast( + c.CTRunGetAdvancesPtr(@ptrCast(self)), + ); + if (ptr == null) return null; return ptr[0..len]; } @@ -72,10 +81,13 @@ pub const Run = opaque { return ptr; } - pub fn getStringIndicesPtr(self: *Run) []const usize { + pub fn getStringIndicesPtr(self: *Run) ?[]const usize { const len = self.getGlyphCount(); if (len == 0) return &.{}; - const ptr = c.CTRunGetStringIndicesPtr(@ptrCast(self)) orelse &.{}; + const ptr: [*c]const usize = @ptrCast( + c.CTRunGetStringIndicesPtr(@ptrCast(self)), + ); + if (ptr == null) return null; return ptr[0..len]; } @@ -90,4 +102,16 @@ pub const Run = opaque { ); return ptr; } + + pub fn getStatus(self: *Run) Status { + return @bitCast(c.CTRunGetStatus(@ptrCast(self))); + } +}; + +/// https://developer.apple.com/documentation/coretext/ctrunstatus?language=objc +pub const Status = packed struct(u32) { + right_to_left: bool, + non_monotonic: bool, + has_non_identity_matrix: bool, + _pad: u29 = 0, }; diff --git a/src/font/shaper/coretext.zig b/src/font/shaper/coretext.zig index 285a5a6b9..b00610d2f 100644 --- a/src/font/shaper/coretext.zig +++ b/src/font/shaper/coretext.zig @@ -369,7 +369,12 @@ pub const Shaper = struct { x: f64 = 0, y: f64 = 0, } = .{}; + + // Clear our cell buf and make sure we have enough room for the whole + // line of glyphs, so that we can just assume capacity when appending + // instead of maybe allocating. self.cell_buf.clearRetainingCapacity(); + try self.cell_buf.ensureTotalCapacity(self.alloc, line.getGlyphCount()); // CoreText may generate multiple runs even though our input to // CoreText is already split into runs by our own run iterator. @@ -381,9 +386,9 @@ pub const Shaper = struct { const ctrun = runs.getValueAtIndex(macos.text.Run, i); // Get our glyphs and positions - const glyphs = try ctrun.getGlyphs(alloc); - const advances = try ctrun.getAdvances(alloc); - const indices = try ctrun.getStringIndices(alloc); + const glyphs = ctrun.getGlyphsPtr() orelse try ctrun.getGlyphs(alloc); + const advances = ctrun.getAdvancesPtr() orelse try ctrun.getAdvances(alloc); + const indices = ctrun.getStringIndicesPtr() orelse try ctrun.getStringIndices(alloc); assert(glyphs.len == advances.len); assert(glyphs.len == indices.len); @@ -406,7 +411,7 @@ pub const Shaper = struct { cell_offset = .{ .cluster = cluster }; } - try self.cell_buf.append(self.alloc, .{ + self.cell_buf.appendAssumeCapacity(.{ .x = @intCast(cluster), .x_offset = @intFromFloat(@round(cell_offset.x)), .y_offset = @intFromFloat(@round(cell_offset.y)),