mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
font: coretext shaper owns the cf release pool
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const macos = @import("macos");
|
const macos = @import("macos");
|
||||||
@ -49,13 +50,18 @@ pub const Shaper = struct {
|
|||||||
/// and releasing many objects when shaping.
|
/// and releasing many objects when shaping.
|
||||||
writing_direction: *macos.foundation.Array,
|
writing_direction: *macos.foundation.Array,
|
||||||
|
|
||||||
/// List where we cache fonts, so we don't have to
|
/// List where we cache fonts, so we don't have to remake them for
|
||||||
/// remake them for every single shaping operation.
|
/// every single shaping operation.
|
||||||
///
|
///
|
||||||
/// Fonts are cached as attribute dictionaries to
|
/// Fonts are cached as attribute dictionaries to be applied directly to
|
||||||
/// be applied directly to attributed strings.
|
/// attributed strings.
|
||||||
cached_fonts: std.ArrayList(?*macos.foundation.Dictionary),
|
cached_fonts: std.ArrayList(?*macos.foundation.Dictionary),
|
||||||
|
|
||||||
|
/// The list of CoreFoundation objects to release on the dedicated
|
||||||
|
/// release thread. This is built up over the course of shaping and
|
||||||
|
/// sent to the release thread when endFrame is called.
|
||||||
|
cf_release_pool: std.ArrayListUnmanaged(*anyopaque),
|
||||||
|
|
||||||
const CellBuf = std.ArrayListUnmanaged(font.shape.Cell);
|
const CellBuf = std.ArrayListUnmanaged(font.shape.Cell);
|
||||||
const CodepointList = std.ArrayListUnmanaged(Codepoint);
|
const CodepointList = std.ArrayListUnmanaged(Codepoint);
|
||||||
const Codepoint = struct {
|
const Codepoint = struct {
|
||||||
@ -209,13 +215,14 @@ pub const Shaper = struct {
|
|||||||
const cached_fonts = std.ArrayList(?*macos.foundation.Dictionary).init(alloc);
|
const cached_fonts = std.ArrayList(?*macos.foundation.Dictionary).init(alloc);
|
||||||
errdefer cached_fonts.deinit();
|
errdefer cached_fonts.deinit();
|
||||||
|
|
||||||
return Shaper{
|
return .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.cell_buf = .{},
|
.cell_buf = .{},
|
||||||
.run_state = run_state,
|
.run_state = run_state,
|
||||||
.features = feats,
|
.features = feats,
|
||||||
.writing_direction = writing_direction,
|
.writing_direction = writing_direction,
|
||||||
.cached_fonts = cached_fonts,
|
.cached_fonts = cached_fonts,
|
||||||
|
.cf_release_pool = .{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +234,19 @@ pub const Shaper = struct {
|
|||||||
|
|
||||||
self.releaseCachedFonts();
|
self.releaseCachedFonts();
|
||||||
self.cached_fonts.deinit();
|
self.cached_fonts.deinit();
|
||||||
|
|
||||||
|
if (self.cf_release_pool.items.len > 0) {
|
||||||
|
for (self.cf_release_pool.items) |ref| macos.foundation.CFRelease(ref);
|
||||||
|
|
||||||
|
// For tests this logic is normal because we don't want to
|
||||||
|
// wait for a release thread. But in production this is a bug
|
||||||
|
// and we should warn.
|
||||||
|
if (comptime !builtin.is_test) log.warn(
|
||||||
|
"BUG: CFRelease pool was not empty, releasing remaining objects",
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.cf_release_pool.deinit(self.alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Release all cached fonts.
|
/// Release all cached fonts.
|
||||||
@ -256,13 +276,12 @@ pub const Shaper = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expects an ArrayList `cf_release_pool` in which `CFTypeRef`s
|
/// Note that this will accumulate garbage in the release pool. The
|
||||||
/// can be placed, which guarantees that they will be `CFRelease`d
|
/// caller must ensure you're properly calling endFrame to release
|
||||||
/// eventually.
|
/// all the objects.
|
||||||
pub fn shape(
|
pub fn shape(
|
||||||
self: *Shaper,
|
self: *Shaper,
|
||||||
run: font.shape.TextRun,
|
run: font.shape.TextRun,
|
||||||
cf_release_pool: *std.ArrayList(*anyopaque),
|
|
||||||
) ![]const font.shape.Cell {
|
) ![]const font.shape.Cell {
|
||||||
const state = &self.run_state;
|
const state = &self.run_state;
|
||||||
|
|
||||||
@ -297,25 +316,24 @@ pub const Shaper = struct {
|
|||||||
const attr_dict: *macos.foundation.Dictionary = try self.getFont(
|
const attr_dict: *macos.foundation.Dictionary = try self.getFont(
|
||||||
run.grid,
|
run.grid,
|
||||||
run.font_index,
|
run.font_index,
|
||||||
cf_release_pool,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Make room for the attributed string and the CTLine.
|
// Make room for the attributed string and the CTLine.
|
||||||
try cf_release_pool.ensureUnusedCapacity(3);
|
try self.cf_release_pool.ensureUnusedCapacity(self.alloc, 3);
|
||||||
|
|
||||||
const str = macos.foundation.String.createWithCharactersNoCopy(state.unichars.items);
|
const str = macos.foundation.String.createWithCharactersNoCopy(state.unichars.items);
|
||||||
cf_release_pool.appendAssumeCapacity(str);
|
self.cf_release_pool.appendAssumeCapacity(str);
|
||||||
|
|
||||||
// Create an attributed string from our string
|
// Create an attributed string from our string
|
||||||
const attr_str = try macos.foundation.AttributedString.create(
|
const attr_str = try macos.foundation.AttributedString.create(
|
||||||
str,
|
str,
|
||||||
attr_dict,
|
attr_dict,
|
||||||
);
|
);
|
||||||
cf_release_pool.appendAssumeCapacity(attr_str);
|
self.cf_release_pool.appendAssumeCapacity(attr_str);
|
||||||
|
|
||||||
// We should always have one run because we do our own run splitting.
|
// We should always have one run because we do our own run splitting.
|
||||||
const line = try macos.text.Line.createWithAttributedString(attr_str);
|
const line = try macos.text.Line.createWithAttributedString(attr_str);
|
||||||
cf_release_pool.appendAssumeCapacity(line);
|
self.cf_release_pool.appendAssumeCapacity(line);
|
||||||
|
|
||||||
// This keeps track of the current offsets within a single cell.
|
// This keeps track of the current offsets within a single cell.
|
||||||
var cell_offset: struct {
|
var cell_offset: struct {
|
||||||
@ -411,7 +429,6 @@ pub const Shaper = struct {
|
|||||||
self: *Shaper,
|
self: *Shaper,
|
||||||
grid: *font.SharedGrid,
|
grid: *font.SharedGrid,
|
||||||
index: font.Collection.Index,
|
index: font.Collection.Index,
|
||||||
cf_release_pool: *std.ArrayList(*anyopaque),
|
|
||||||
) !*macos.foundation.Dictionary {
|
) !*macos.foundation.Dictionary {
|
||||||
const index_int = index.int();
|
const index_int = index.int();
|
||||||
|
|
||||||
@ -426,7 +443,8 @@ pub const Shaper = struct {
|
|||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
try cf_release_pool.ensureUnusedCapacity(3);
|
// Features dictionary, font descriptor, font
|
||||||
|
try self.cf_release_pool.ensureUnusedCapacity(self.alloc, 3);
|
||||||
|
|
||||||
const run_font = font: {
|
const run_font = font: {
|
||||||
// The CoreText shaper relies on CoreText and CoreText claims
|
// The CoreText shaper relies on CoreText and CoreText claims
|
||||||
@ -450,17 +468,17 @@ pub const Shaper = struct {
|
|||||||
const original = face.font;
|
const original = face.font;
|
||||||
|
|
||||||
const attrs = try self.features.attrsDict(face.quirks_disable_default_font_features);
|
const attrs = try self.features.attrsDict(face.quirks_disable_default_font_features);
|
||||||
cf_release_pool.appendAssumeCapacity(attrs);
|
self.cf_release_pool.appendAssumeCapacity(attrs);
|
||||||
|
|
||||||
const desc = try macos.text.FontDescriptor.createWithAttributes(attrs);
|
const desc = try macos.text.FontDescriptor.createWithAttributes(attrs);
|
||||||
cf_release_pool.appendAssumeCapacity(desc);
|
self.cf_release_pool.appendAssumeCapacity(desc);
|
||||||
|
|
||||||
const copied = try original.copyWithAttributes(0, null, desc);
|
const copied = try original.copyWithAttributes(0, null, desc);
|
||||||
errdefer copied.release();
|
errdefer copied.release();
|
||||||
|
|
||||||
break :font copied;
|
break :font copied;
|
||||||
};
|
};
|
||||||
cf_release_pool.appendAssumeCapacity(run_font);
|
self.cf_release_pool.appendAssumeCapacity(run_font);
|
||||||
|
|
||||||
// Get our font and use that get the attributes to set for the
|
// Get our font and use that get the attributes to set for the
|
||||||
// attributed string so the whole string uses the same font.
|
// attributed string so the whole string uses the same font.
|
||||||
@ -500,7 +518,7 @@ pub const Shaper = struct {
|
|||||||
|
|
||||||
const pair = macos.foundation.stringGetSurrogatePairForLongCharacter(
|
const pair = macos.foundation.stringGetSurrogatePairForLongCharacter(
|
||||||
cp,
|
cp,
|
||||||
state.unichars.items[state.unichars.items.len-2..][0..2],
|
state.unichars.items[state.unichars.items.len - 2 ..][0..2],
|
||||||
);
|
);
|
||||||
if (!pair) {
|
if (!pair) {
|
||||||
state.unichars.items.len -= 1;
|
state.unichars.items.len -= 1;
|
||||||
@ -599,14 +617,6 @@ test "run iterator: empty cells with background set" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -646,7 +656,7 @@ test "run iterator: empty cells with background set" {
|
|||||||
);
|
);
|
||||||
{
|
{
|
||||||
const run = (try it.next(alloc)).?;
|
const run = (try it.next(alloc)).?;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 3), cells.len);
|
try testing.expectEqual(@as(usize, 3), cells.len);
|
||||||
}
|
}
|
||||||
try testing.expect(try it.next(alloc) == null);
|
try testing.expect(try it.next(alloc) == null);
|
||||||
@ -657,14 +667,6 @@ test "shape" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -691,7 +693,7 @@ test "shape" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -700,14 +702,6 @@ test "shape nerd fonts" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaperWithFont(alloc, .nerd_font);
|
var testdata = try testShaperWithFont(alloc, .nerd_font);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -734,7 +728,7 @@ test "shape nerd fonts" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -743,14 +737,6 @@ test "shape inconsolata ligs" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -771,7 +757,7 @@ test "shape inconsolata ligs" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 2), cells.len);
|
try testing.expectEqual(@as(usize, 2), cells.len);
|
||||||
try testing.expect(cells[0].glyph_index != null);
|
try testing.expect(cells[0].glyph_index != null);
|
||||||
try testing.expect(cells[1].glyph_index == null);
|
try testing.expect(cells[1].glyph_index == null);
|
||||||
@ -796,7 +782,7 @@ test "shape inconsolata ligs" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 3), cells.len);
|
try testing.expectEqual(@as(usize, 3), cells.len);
|
||||||
try testing.expect(cells[0].glyph_index != null);
|
try testing.expect(cells[0].glyph_index != null);
|
||||||
try testing.expect(cells[1].glyph_index == null);
|
try testing.expect(cells[1].glyph_index == null);
|
||||||
@ -810,14 +796,6 @@ test "shape monaspace ligs" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaperWithFont(alloc, .monaspace_neon);
|
var testdata = try testShaperWithFont(alloc, .monaspace_neon);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -838,7 +816,7 @@ test "shape monaspace ligs" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 3), cells.len);
|
try testing.expectEqual(@as(usize, 3), cells.len);
|
||||||
try testing.expect(cells[0].glyph_index != null);
|
try testing.expect(cells[0].glyph_index != null);
|
||||||
try testing.expect(cells[1].glyph_index == null);
|
try testing.expect(cells[1].glyph_index == null);
|
||||||
@ -853,14 +831,6 @@ test "shape left-replaced lig in last run" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaperWithFont(alloc, .geist_mono);
|
var testdata = try testShaperWithFont(alloc, .geist_mono);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -881,7 +851,7 @@ test "shape left-replaced lig in last run" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 3), cells.len);
|
try testing.expectEqual(@as(usize, 3), cells.len);
|
||||||
try testing.expect(cells[0].glyph_index != null);
|
try testing.expect(cells[0].glyph_index != null);
|
||||||
try testing.expect(cells[1].glyph_index == null);
|
try testing.expect(cells[1].glyph_index == null);
|
||||||
@ -896,14 +866,6 @@ test "shape left-replaced lig in early run" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaperWithFont(alloc, .geist_mono);
|
var testdata = try testShaperWithFont(alloc, .geist_mono);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -922,7 +884,7 @@ test "shape left-replaced lig in early run" {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const run = (try it.next(alloc)).?;
|
const run = (try it.next(alloc)).?;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 4), cells.len);
|
try testing.expectEqual(@as(usize, 4), cells.len);
|
||||||
try testing.expect(cells[0].glyph_index != null);
|
try testing.expect(cells[0].glyph_index != null);
|
||||||
try testing.expect(cells[1].glyph_index == null);
|
try testing.expect(cells[1].glyph_index == null);
|
||||||
@ -936,14 +898,6 @@ test "shape U+3C9 with JB Mono" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaperWithFont(alloc, .jetbrains_mono);
|
var testdata = try testShaperWithFont(alloc, .jetbrains_mono);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -965,7 +919,7 @@ test "shape U+3C9 with JB Mono" {
|
|||||||
var cell_count: usize = 0;
|
var cell_count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
run_count += 1;
|
run_count += 1;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
cell_count += cells.len;
|
cell_count += cells.len;
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), run_count);
|
try testing.expectEqual(@as(usize, 1), run_count);
|
||||||
@ -977,14 +931,6 @@ test "shape emoji width" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1005,7 +951,7 @@ test "shape emoji width" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 1), cells.len);
|
try testing.expectEqual(@as(usize, 1), cells.len);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
@ -1016,14 +962,6 @@ test "shape emoji width long" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1052,7 +990,7 @@ test "shape emoji width long" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
|
|
||||||
// screen.testWriteString isn't grapheme aware, otherwise this is one
|
// screen.testWriteString isn't grapheme aware, otherwise this is one
|
||||||
try testing.expectEqual(@as(usize, 5), cells.len);
|
try testing.expectEqual(@as(usize, 5), cells.len);
|
||||||
@ -1064,14 +1002,6 @@ test "shape variation selector VS15" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1097,7 +1027,7 @@ test "shape variation selector VS15" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 1), cells.len);
|
try testing.expectEqual(@as(usize, 1), cells.len);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
@ -1107,14 +1037,6 @@ test "shape variation selector VS16" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1140,7 +1062,7 @@ test "shape variation selector VS16" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 1), cells.len);
|
try testing.expectEqual(@as(usize, 1), cells.len);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
@ -1150,14 +1072,6 @@ test "shape with empty cells in between" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1181,7 +1095,7 @@ test "shape with empty cells in between" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
try testing.expectEqual(@as(usize, 7), cells.len);
|
try testing.expectEqual(@as(usize, 7), cells.len);
|
||||||
}
|
}
|
||||||
@ -1191,14 +1105,6 @@ test "shape Chinese characters" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1227,7 +1133,7 @@ test "shape Chinese characters" {
|
|||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 4), cells.len);
|
try testing.expectEqual(@as(usize, 4), cells.len);
|
||||||
try testing.expectEqual(@as(u16, 0), cells[0].x);
|
try testing.expectEqual(@as(u16, 0), cells[0].x);
|
||||||
try testing.expectEqual(@as(u16, 0), cells[1].x);
|
try testing.expectEqual(@as(u16, 0), cells[1].x);
|
||||||
@ -1241,14 +1147,6 @@ test "shape box glyphs" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1274,7 +1172,7 @@ test "shape box glyphs" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
const cells = try shaper.shape(run, &cf_release_pool);
|
const cells = try shaper.shape(run);
|
||||||
try testing.expectEqual(@as(usize, 2), cells.len);
|
try testing.expectEqual(@as(usize, 2), cells.len);
|
||||||
try testing.expectEqual(@as(u32, 0x2500), cells[0].glyph_index.?);
|
try testing.expectEqual(@as(u32, 0x2500), cells[0].glyph_index.?);
|
||||||
try testing.expectEqual(@as(u16, 0), cells[0].x);
|
try testing.expectEqual(@as(u16, 0), cells[0].x);
|
||||||
@ -1288,14 +1186,6 @@ test "shape selection boundary" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1322,7 +1212,7 @@ test "shape selection boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1345,7 +1235,7 @@ test "shape selection boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1368,7 +1258,7 @@ test "shape selection boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1391,7 +1281,7 @@ test "shape selection boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 3), count);
|
try testing.expectEqual(@as(usize, 3), count);
|
||||||
}
|
}
|
||||||
@ -1414,7 +1304,7 @@ test "shape selection boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 3), count);
|
try testing.expectEqual(@as(usize, 3), count);
|
||||||
}
|
}
|
||||||
@ -1424,14 +1314,6 @@ test "shape cursor boundary" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1454,7 +1336,7 @@ test "shape cursor boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1473,7 +1355,7 @@ test "shape cursor boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1492,7 +1374,7 @@ test "shape cursor boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 3), count);
|
try testing.expectEqual(@as(usize, 3), count);
|
||||||
}
|
}
|
||||||
@ -1511,7 +1393,7 @@ test "shape cursor boundary" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1521,14 +1403,6 @@ test "shape cursor boundary and colored emoji" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1551,7 +1425,7 @@ test "shape cursor boundary and colored emoji" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1570,7 +1444,7 @@ test "shape cursor boundary and colored emoji" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1587,7 +1461,7 @@ test "shape cursor boundary and colored emoji" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1597,14 +1471,6 @@ test "shape cell attribute change" {
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
macos.foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
var testdata = try testShaper(alloc);
|
var testdata = try testShaper(alloc);
|
||||||
defer testdata.deinit();
|
defer testdata.deinit();
|
||||||
|
|
||||||
@ -1625,7 +1491,7 @@ test "shape cell attribute change" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1649,7 +1515,7 @@ test "shape cell attribute change" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1674,7 +1540,7 @@ test "shape cell attribute change" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 2), count);
|
try testing.expectEqual(@as(usize, 2), count);
|
||||||
}
|
}
|
||||||
@ -1699,7 +1565,7 @@ test "shape cell attribute change" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
@ -1723,7 +1589,7 @@ test "shape cell attribute change" {
|
|||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (try it.next(alloc)) |run| {
|
while (try it.next(alloc)) |run| {
|
||||||
count += 1;
|
count += 1;
|
||||||
_ = try shaper.shape(run, &cf_release_pool);
|
_ = try shaper.shape(run);
|
||||||
}
|
}
|
||||||
try testing.expectEqual(@as(usize, 1), count);
|
try testing.expectEqual(@as(usize, 1), count);
|
||||||
}
|
}
|
||||||
|
@ -1018,9 +1018,6 @@ pub fn updateFrame(
|
|||||||
if (critical.preedit) |p| p.deinit(self.alloc);
|
if (critical.preedit) |p| p.deinit(self.alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(self.alloc);
|
|
||||||
try cf_release_pool.ensureTotalCapacity(state.terminal.rows * 8);
|
|
||||||
|
|
||||||
// Build our GPU cells
|
// Build our GPU cells
|
||||||
try self.rebuildCells(
|
try self.rebuildCells(
|
||||||
critical.full_rebuild,
|
critical.full_rebuild,
|
||||||
@ -1029,27 +1026,23 @@ pub fn updateFrame(
|
|||||||
critical.preedit,
|
critical.preedit,
|
||||||
critical.cursor_style,
|
critical.cursor_style,
|
||||||
&critical.color_palette,
|
&critical.color_palette,
|
||||||
&cf_release_pool,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (cf_release_pool.items.len > 0) {
|
if (self.font_shaper.cf_release_pool.items.len > 0) {
|
||||||
const items = try cf_release_pool.toOwnedSlice();
|
const alloc = self.font_shaper.alloc;
|
||||||
|
const items = try self.font_shaper.cf_release_pool.toOwnedSlice(alloc);
|
||||||
if (self.cf_release_thread.mailbox.push(
|
if (self.cf_release_thread.mailbox.push(
|
||||||
.{ .release = .{
|
.{ .release = .{
|
||||||
.refs = items,
|
.refs = items,
|
||||||
.alloc = self.alloc,
|
.alloc = alloc,
|
||||||
} },
|
} },
|
||||||
.{ .forever = {} },
|
.{ .forever = {} },
|
||||||
) != 0) {
|
) != 0) {
|
||||||
try self.cf_release_thread.wakeup.notify();
|
try self.cf_release_thread.wakeup.notify();
|
||||||
} else {
|
} else {
|
||||||
for (items) |ref| {
|
for (items) |ref| macos.foundation.CFRelease(ref);
|
||||||
macos.foundation.CFRelease(ref);
|
alloc.free(items);
|
||||||
}
|
|
||||||
self.alloc.free(items);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update our viewport pin
|
// Update our viewport pin
|
||||||
@ -1931,7 +1924,6 @@ fn rebuildCells(
|
|||||||
preedit: ?renderer.State.Preedit,
|
preedit: ?renderer.State.Preedit,
|
||||||
cursor_style_: ?renderer.CursorStyle,
|
cursor_style_: ?renderer.CursorStyle,
|
||||||
color_palette: *const terminal.color.Palette,
|
color_palette: *const terminal.color.Palette,
|
||||||
cf_release_pool: *std.ArrayList(*anyopaque),
|
|
||||||
) !void {
|
) !void {
|
||||||
// const start = try std.time.Instant.now();
|
// const start = try std.time.Instant.now();
|
||||||
// const start_micro = std.time.microTimestamp();
|
// const start_micro = std.time.microTimestamp();
|
||||||
@ -2013,10 +2005,7 @@ fn rebuildCells(
|
|||||||
while (try iter.next(self.alloc)) |run| {
|
while (try iter.next(self.alloc)) |run| {
|
||||||
// Try to read the cells from the shaping cache if we can.
|
// Try to read the cells from the shaping cache if we can.
|
||||||
const shaper_cells = self.font_shaper_cache.get(run) orelse cache: {
|
const shaper_cells = self.font_shaper_cache.get(run) orelse cache: {
|
||||||
const cells = if (font.options.backend == .coretext)
|
const cells = try self.font_shaper.shape(run);
|
||||||
try self.font_shaper.shape(run, cf_release_pool)
|
|
||||||
else
|
|
||||||
try self.font_shaper.shape(run);
|
|
||||||
|
|
||||||
// Try to cache them. If caching fails for any reason we continue
|
// Try to cache them. If caching fails for any reason we continue
|
||||||
// because it is just a performance optimization, not a correctness
|
// because it is just a performance optimization, not a correctness
|
||||||
|
@ -1025,16 +1025,7 @@ pub fn rebuildCells(
|
|||||||
while (try iter.next(self.alloc)) |run| {
|
while (try iter.next(self.alloc)) |run| {
|
||||||
// Try to read the cells from the shaping cache if we can.
|
// Try to read the cells from the shaping cache if we can.
|
||||||
const shaper_cells = self.font_shaper_cache.get(run) orelse cache: {
|
const shaper_cells = self.font_shaper_cache.get(run) orelse cache: {
|
||||||
const cells = if (font.options.backend == .coretext) ct: {
|
const cells = try self.font_shaper.shape(run);
|
||||||
var cf_release_pool = std.ArrayList(*anyopaque).init(self.alloc);
|
|
||||||
defer {
|
|
||||||
for (cf_release_pool.items) |ref| {
|
|
||||||
@import("macos").foundation.CFRelease(ref);
|
|
||||||
}
|
|
||||||
cf_release_pool.deinit();
|
|
||||||
}
|
|
||||||
break :ct try self.font_shaper.shape(run, &cf_release_pool);
|
|
||||||
} else try self.font_shaper.shape(run);
|
|
||||||
|
|
||||||
// Try to cache them. If caching fails for any reason we continue
|
// Try to cache them. If caching fails for any reason we continue
|
||||||
// because it is just a performance optimization, not a correctness
|
// because it is just a performance optimization, not a correctness
|
||||||
|
Reference in New Issue
Block a user