diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/harfbuzz/blob.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/harfbuzz/blob.zig')
| -rw-r--r-- | vendor/libghostty-vt/pkg/harfbuzz/blob.zig | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/pkg/harfbuzz/blob.zig b/vendor/libghostty-vt/pkg/harfbuzz/blob.zig new file mode 100644 index 00000000..9472e4c7 --- /dev/null +++ b/vendor/libghostty-vt/pkg/harfbuzz/blob.zig @@ -0,0 +1,126 @@ +const std = @import("std"); +const c = @import("c.zig").c; +const Error = @import("errors.zig").Error; + +/// Data type holding the memory modes available to client programs. +/// +/// Regarding these various memory-modes: +/// +/// - In no case shall the HarfBuzz client modify memory that is passed to +/// HarfBuzz in a blob. If there is any such possibility, +/// HB_MEMORY_MODE_DUPLICATE should be used such that HarfBuzz makes a +/// copy immediately, +/// +/// - Use HB_MEMORY_MODE_READONLY otherwise, unless you really really really +/// know what you are doing, +/// +/// - HB_MEMORY_MODE_WRITABLE is appropriate if you really made a copy of +/// data solely for the purpose of passing to HarfBuzz and doing that +/// just once (no reuse!), +/// +/// - If the font is mmap()ed, it's okay to use +/// HB_MEMORY_READONLY_MAY_MAKE_WRITABLE , however, using that mode +/// correctly is very tricky. Use HB_MEMORY_MODE_READONLY instead. +pub const MemoryMode = enum(u2) { + /// HarfBuzz immediately makes a copy of the data. + duplicate = c.HB_MEMORY_MODE_DUPLICATE, + + /// HarfBuzz client will never modify the data, and HarfBuzz will never + /// modify the data. + readonly = c.HB_MEMORY_MODE_READONLY, + + /// HarfBuzz client made a copy of the data solely for HarfBuzz, so + /// HarfBuzz may modify the data. + writable = c.HB_MEMORY_MODE_WRITABLE, + + /// See above + readonly_may_make_writable = c.HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, +}; + +/// Blobs wrap a chunk of binary data to handle lifecycle management of data +/// while it is passed between client and HarfBuzz. Blobs are primarily +/// used to create font faces, but also to access font face tables, as well as +/// pass around other binary data. +pub const Blob = struct { + handle: *c.hb_blob_t, + + /// Creates a new "blob" object wrapping data . The mode parameter is used + /// to negotiate ownership and lifecycle of data . + /// + /// Note that this function returns a freshly-allocated empty blob even + /// if length is zero. This is in contrast to hb_blob_create(), which + /// returns the singleton empty blob (as returned by hb_blob_get_empty()) + /// if length is zero. + pub fn create(data: []const u8, mode: MemoryMode) Error!Blob { + const handle = c.hb_blob_create_or_fail( + data.ptr, + @intCast(data.len), + @intFromEnum(mode), + null, + null, + ) orelse return Error.HarfbuzzFailed; + + return Blob{ .handle = handle }; + } + + /// Decreases the reference count on blob , and if it reaches zero, + /// destroys blob , freeing all memory, possibly calling the + /// destroy-callback the blob was created for if it has not been + /// called already. + pub fn destroy(self: *Blob) void { + c.hb_blob_destroy(self.handle); + } + + /// Attaches a user-data key/data pair to the specified blob. + pub fn setUserData( + self: Blob, + comptime T: type, + key: ?*anyopaque, + ptr: ?*T, + comptime destroycb: ?*const fn (?*T) callconv(.c) void, + replace: bool, + ) bool { + const Callback = struct { + pub fn callback(data: ?*anyopaque) callconv(.c) void { + @call(.{ .modifier = .always_inline }, destroycb, .{ + @as(?*T, @ptrCast(@alignCast(data))), + }); + } + }; + + return c.hb_blob_set_user_data( + self.handle, + @ptrCast(key), + ptr, + if (destroycb != null) Callback.callback else null, + if (replace) 1 else 0, + ) > 0; + } + + /// Fetches the user data associated with the specified key, attached to + /// the specified font-functions structure. + pub fn getUserData( + self: Blob, + comptime T: type, + key: ?*anyopaque, + ) ?*T { + const opt = c.hb_blob_get_user_data(self.handle, @ptrCast(key)); + if (opt) |ptr| + return @ptrCast(@alignCast(ptr)) + else + return null; + } +}; + +test { + const testing = std.testing; + + const data = "hello"; + var blob = try Blob.create(data, .readonly); + defer blob.destroy(); + + var userdata: u8 = 127; + var key: u8 = 0; + try testing.expect(blob.setUserData(u8, &key, &userdata, null, false)); + try testing.expect(blob.getUserData(u8, &key).?.* == 127); +} |
