mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
font/harfbuzz: work with new font structures
This commit is contained in:
@ -554,6 +554,8 @@ test getIndex {
|
||||
}
|
||||
|
||||
test autoItalicize {
|
||||
if (comptime !@hasDecl(Face, "italicize")) return error.SkipZigTest;
|
||||
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
const testFont = @import("test.zig").fontRegular;
|
||||
|
@ -4,10 +4,10 @@ const Allocator = std.mem.Allocator;
|
||||
const harfbuzz = @import("harfbuzz");
|
||||
const font = @import("../main.zig");
|
||||
const Face = font.Face;
|
||||
const Collection = font.Collection;
|
||||
const DeferredFace = font.DeferredFace;
|
||||
const Group = font.Group;
|
||||
const GroupCache = font.GroupCache;
|
||||
const Library = font.Library;
|
||||
const SharedGrid = font.SharedGrid;
|
||||
const Style = font.Style;
|
||||
const Presentation = font.Presentation;
|
||||
const terminal = @import("../../terminal/main.zig");
|
||||
@ -83,7 +83,7 @@ pub const Shaper = struct {
|
||||
/// and assume the y value matches.
|
||||
pub fn runIterator(
|
||||
self: *Shaper,
|
||||
group: *GroupCache,
|
||||
grid: *SharedGrid,
|
||||
screen: *const terminal.Screen,
|
||||
row: terminal.Pin,
|
||||
selection: ?terminal.Selection,
|
||||
@ -91,7 +91,7 @@ pub const Shaper = struct {
|
||||
) font.shape.RunIterator {
|
||||
return .{
|
||||
.hooks = .{ .shaper = self },
|
||||
.group = group,
|
||||
.grid = grid,
|
||||
.screen = screen,
|
||||
.row = row,
|
||||
.selection = selection,
|
||||
@ -110,7 +110,13 @@ pub const Shaper = struct {
|
||||
// We only do shaping if the font is not a special-case. For special-case
|
||||
// fonts, the codepoint == glyph_index so we don't need to run any shaping.
|
||||
if (run.font_index.special() == null) {
|
||||
const face = try run.group.group.faceFromIndex(run.font_index);
|
||||
// We have to lock the grid to get the face and unfortunately
|
||||
// freetype faces (typically used with harfbuzz) are not thread
|
||||
// safe so this has to be an exclusive lock.
|
||||
run.grid.lock.lock();
|
||||
defer run.grid.lock.unlock();
|
||||
|
||||
const face = try run.grid.resolver.collection.getFace(run.font_index);
|
||||
const i = if (!face.quirks_disable_default_font_features) 0 else i: {
|
||||
// If we are disabling default font features we just offset
|
||||
// our features by the hardcoded items because always
|
||||
@ -251,7 +257,7 @@ test "run iterator" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -270,7 +276,7 @@ test "run iterator" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -290,7 +296,7 @@ test "run iterator" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -342,7 +348,7 @@ test "run iterator: empty cells with background set" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -385,7 +391,7 @@ test "shape" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -414,7 +420,7 @@ test "shape inconsolata ligs" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -439,7 +445,7 @@ test "shape inconsolata ligs" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -473,7 +479,7 @@ test "shape monaspace ligs" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -507,7 +513,7 @@ test "shape emoji width" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -547,7 +553,7 @@ test "shape emoji width long" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -586,7 +592,7 @@ test "shape variation selector VS15" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -623,7 +629,7 @@ test "shape variation selector VS16" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -657,7 +663,7 @@ test "shape with empty cells in between" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -695,7 +701,7 @@ test "shape Chinese characters" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -722,13 +728,6 @@ test "shape box glyphs" {
|
||||
var testdata = try testShaper(alloc);
|
||||
defer testdata.deinit();
|
||||
|
||||
// Setup the box font
|
||||
testdata.cache.group.sprite = font.sprite.Face{
|
||||
.width = 18,
|
||||
.height = 36,
|
||||
.thickness = 2,
|
||||
};
|
||||
|
||||
var buf: [32]u8 = undefined;
|
||||
var buf_idx: usize = 0;
|
||||
buf_idx += try std.unicode.utf8Encode(0x2500, buf[buf_idx..]); // horiz line
|
||||
@ -742,7 +741,7 @@ test "shape box glyphs" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -779,7 +778,7 @@ test "shape selection boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
terminal.Selection.init(
|
||||
@ -802,7 +801,7 @@ test "shape selection boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
terminal.Selection.init(
|
||||
@ -825,7 +824,7 @@ test "shape selection boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
terminal.Selection.init(
|
||||
@ -848,7 +847,7 @@ test "shape selection boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
terminal.Selection.init(
|
||||
@ -871,7 +870,7 @@ test "shape selection boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
terminal.Selection.init(
|
||||
@ -907,7 +906,7 @@ test "shape cursor boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -926,7 +925,7 @@ test "shape cursor boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -945,7 +944,7 @@ test "shape cursor boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -964,7 +963,7 @@ test "shape cursor boundary" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -996,7 +995,7 @@ test "shape cursor boundary and colored emoji" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1015,7 +1014,7 @@ test "shape cursor boundary and colored emoji" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1032,7 +1031,7 @@ test "shape cursor boundary and colored emoji" {
|
||||
// Get our run iterator
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1062,7 +1061,7 @@ test "shape cell attribute change" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1086,7 +1085,7 @@ test "shape cell attribute change" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1111,7 +1110,7 @@ test "shape cell attribute change" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1136,7 +1135,7 @@ test "shape cell attribute change" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1160,7 +1159,7 @@ test "shape cell attribute change" {
|
||||
|
||||
var shaper = &testdata.shaper;
|
||||
var it = shaper.runIterator(
|
||||
testdata.cache,
|
||||
testdata.grid,
|
||||
&screen,
|
||||
screen.pages.pin(.{ .screen = .{ .y = 0 } }).?,
|
||||
null,
|
||||
@ -1178,13 +1177,13 @@ test "shape cell attribute change" {
|
||||
const TestShaper = struct {
|
||||
alloc: Allocator,
|
||||
shaper: Shaper,
|
||||
cache: *GroupCache,
|
||||
grid: *SharedGrid,
|
||||
lib: Library,
|
||||
|
||||
pub fn deinit(self: *TestShaper) void {
|
||||
self.shaper.deinit();
|
||||
self.cache.deinit(self.alloc);
|
||||
self.alloc.destroy(self.cache);
|
||||
self.grid.deinit(self.alloc);
|
||||
self.alloc.destroy(self.grid);
|
||||
self.lib.deinit();
|
||||
}
|
||||
};
|
||||
@ -1210,17 +1209,11 @@ fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
|
||||
var lib = try Library.init();
|
||||
errdefer lib.deinit();
|
||||
|
||||
var cache_ptr = try alloc.create(GroupCache);
|
||||
errdefer alloc.destroy(cache_ptr);
|
||||
cache_ptr.* = try GroupCache.init(alloc, try Group.init(
|
||||
alloc,
|
||||
lib,
|
||||
.{ .points = 12 },
|
||||
));
|
||||
errdefer cache_ptr.*.deinit(alloc);
|
||||
var c = try Collection.init(alloc);
|
||||
c.load_options = .{ .library = lib };
|
||||
|
||||
// Setup group
|
||||
_ = try cache_ptr.group.addFace(.regular, .{ .loaded = try Face.init(
|
||||
_ = try c.add(alloc, .regular, .{ .loaded = try Face.init(
|
||||
lib,
|
||||
testFont,
|
||||
.{ .size = .{ .points = 12 } },
|
||||
@ -1228,7 +1221,7 @@ fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
|
||||
|
||||
if (font.options.backend != .coretext) {
|
||||
// Coretext doesn't support Noto's format
|
||||
_ = try cache_ptr.group.addFace(.regular, .{ .loaded = try Face.init(
|
||||
_ = try c.add(alloc, .regular, .{ .loaded = try Face.init(
|
||||
lib,
|
||||
testEmoji,
|
||||
.{ .size = .{ .points = 12 } },
|
||||
@ -1245,21 +1238,26 @@ fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
|
||||
defer disco_it.deinit();
|
||||
var face = (try disco_it.next()).?;
|
||||
errdefer face.deinit();
|
||||
_ = try cache_ptr.group.addFace(.regular, .{ .deferred = face });
|
||||
_ = try c.add(alloc, .regular, .{ .deferred = face });
|
||||
}
|
||||
_ = try cache_ptr.group.addFace(.regular, .{ .loaded = try Face.init(
|
||||
_ = try c.add(alloc, .regular, .{ .loaded = try Face.init(
|
||||
lib,
|
||||
testEmojiText,
|
||||
.{ .size = .{ .points = 12 } },
|
||||
) });
|
||||
|
||||
const grid_ptr = try alloc.create(SharedGrid);
|
||||
errdefer alloc.destroy(grid_ptr);
|
||||
grid_ptr.* = try SharedGrid.init(alloc, .{ .collection = c }, false);
|
||||
errdefer grid_ptr.*.deinit(alloc);
|
||||
|
||||
var shaper = try Shaper.init(alloc, .{});
|
||||
errdefer shaper.deinit();
|
||||
|
||||
return TestShaper{
|
||||
.alloc = alloc,
|
||||
.shaper = shaper,
|
||||
.cache = cache_ptr,
|
||||
.grid = grid_ptr,
|
||||
.lib = lib,
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user