font/coretext: tiny shaper improvements
Reduce potential allocation while processing glyphs by ensuring capacity in the buffer ahead of time and also using CTRunGet*Ptr functions first and only allocating for those if that didn't work (it should almost always work in practice.)pull/9002/head
parent
9c8d2e577e
commit
d6063428bd
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
Loading…
Reference in New Issue