From 3c077ee19b490013f8f9f565e47eee6e535b21a6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 28 Aug 2022 11:42:57 -0700 Subject: [PATCH] pkg/harfbuzz: buffer init, add --- pkg/harfbuzz/buffer.zig | 164 ++++++++++++++++++++++++++++++++++++++++ pkg/harfbuzz/main.zig | 1 + 2 files changed, 165 insertions(+) create mode 100644 pkg/harfbuzz/buffer.zig diff --git a/pkg/harfbuzz/buffer.zig b/pkg/harfbuzz/buffer.zig new file mode 100644 index 000000000..dc0ea73b9 --- /dev/null +++ b/pkg/harfbuzz/buffer.zig @@ -0,0 +1,164 @@ +const std = @import("std"); +const c = @import("c.zig"); +const Error = @import("errors.zig").Error; + +/// Buffers serve a dual role in HarfBuzz; before shaping, they hold the +/// input characters that are passed to hb_shape(), and after shaping they +/// hold the output glyphs. +pub const Buffer = struct { + handle: *c.hb_buffer_t, + + /// Creates a new hb_buffer_t with all properties to defaults. + pub fn create() Error!Buffer { + const handle = c.hb_buffer_create() orelse return Error.HarfbuzzFailed; + return Buffer{ .handle = handle }; + } + + /// Deallocate the buffer . Decreases the reference count on buffer by one. + /// If the result is zero, then buffer and all associated resources are + /// freed. See hb_buffer_reference(). + pub fn destroy(self: *Buffer) void { + c.hb_buffer_destroy(self.handle); + } + + /// Resets the buffer to its initial status, as if it was just newly + /// created with hb_buffer_create(). + pub fn reset(self: Buffer) void { + c.hb_buffer_reset(self.handle); + } + + /// Sets the type of buffer contents. Buffers are either empty, contain + /// characters (before shaping), or contain glyphs (the result of shaping). + pub fn setContentType(self: Buffer, ct: ContentType) void { + c.hb_buffer_set_content_type(self.handle, @enumToInt(ct)); + } + + /// Fetches the type of buffer contents. Buffers are either empty, contain + /// characters (before shaping), or contain glyphs (the result of shaping). + pub fn getContentType(self: Buffer) ContentType { + return @intToEnum(ContentType, c.hb_buffer_get_content_type(self.handle)); + } + + /// Appends a character with the Unicode value of codepoint to buffer, + /// and gives it the initial cluster value of cluster . Clusters can be + /// any thing the client wants, they are usually used to refer to the + /// index of the character in the input text stream and are output in + /// hb_glyph_info_t.cluster field. + /// + /// This function does not check the validity of codepoint, it is up to + /// the caller to ensure it is a valid Unicode code point. + pub fn add(self: Buffer, cp: u32, cluster: u32) void { + c.hb_buffer_add(self.handle, cp, cluster); + } + + /// Appends characters from text array to buffer . The item_offset is the + /// position of the first character from text that will be appended, and + /// item_length is the number of character. When shaping part of a larger + /// text (e.g. a run of text from a paragraph), instead of passing just + /// the substring corresponding to the run, it is preferable to pass the + /// whole paragraph and specify the run start and length as item_offset and + /// item_length , respectively, to give HarfBuzz the full context to be + /// able, for example, to do cross-run Arabic shaping or properly handle + /// combining marks at stat of run. + /// + /// This function does not check the validity of text , it is up to the + /// caller to ensure it contains a valid Unicode code points. + pub fn addCodepoints(self: Buffer, text: []const u32) void { + c.hb_buffer_add_codepoints( + self.handle, + text.ptr, + @intCast(c_int, text.len), + 0, + @intCast(c_int, text.len), + ); + } + + /// See hb_buffer_add_codepoints(). + /// + /// Replaces invalid UTF-32 characters with the buffer replacement code + /// point, see hb_buffer_set_replacement_codepoint(). + pub fn addUTF32(self: Buffer, text: []const u32) void { + c.hb_buffer_add_utf32( + self.handle, + text.ptr, + @intCast(c_int, text.len), + 0, + @intCast(c_int, text.len), + ); + } + + /// See hb_buffer_add_codepoints(). + /// + /// Replaces invalid UTF-16 characters with the buffer replacement code + /// point, see hb_buffer_set_replacement_codepoint(). + pub fn addUTF16(self: Buffer, text: []const u16) void { + c.hb_buffer_add_utf16( + self.handle, + text.ptr, + @intCast(c_int, text.len), + 0, + @intCast(c_int, text.len), + ); + } + + /// See hb_buffer_add_codepoints(). + /// + /// Replaces invalid UTF-8 characters with the buffer replacement code + /// point, see hb_buffer_set_replacement_codepoint(). + pub fn addUTF8(self: Buffer, text: []const u8) void { + c.hb_buffer_add_utf8( + self.handle, + text.ptr, + @intCast(c_int, text.len), + 0, + @intCast(c_int, text.len), + ); + } + + /// Similar to hb_buffer_add_codepoints(), but allows only access to first + /// 256 Unicode code points that can fit in 8-bit strings. + pub fn addLatin1(self: Buffer, text: []const u8) void { + c.hb_buffer_add_latin1( + self.handle, + text.ptr, + @intCast(c_int, text.len), + 0, + @intCast(c_int, text.len), + ); + } +}; + +/// The type of hb_buffer_t contents. +pub const ContentType = enum(u2) { + /// Initial value for new buffer. + invalid = c.HB_BUFFER_CONTENT_TYPE_INVALID, + + /// The buffer contains input characters (before shaping). + unicode = c.HB_BUFFER_CONTENT_TYPE_UNICODE, + + /// The buffer contains output glyphs (after shaping). + glyphs = c.HB_BUFFER_CONTENT_TYPE_GLYPHS, +}; + +test "create" { + const testing = std.testing; + + var buffer = try Buffer.create(); + defer buffer.destroy(); + buffer.reset(); + + // Content type + buffer.setContentType(.unicode); + try testing.expectEqual(ContentType.unicode, buffer.getContentType()); + + // Try add functions + buffer.add('🥹', 27); + var utf32 = [_]u32{ 'A', 'B', 'C' }; + var utf16 = [_]u16{ 'A', 'B', 'C' }; + var utf8 = [_]u8{ 'A', 'B', 'C' }; + buffer.addCodepoints(&utf32); + buffer.addUTF32(&utf32); + buffer.addUTF16(&utf16); + buffer.addUTF8(&utf8); + buffer.addLatin1(&utf8); +} diff --git a/pkg/harfbuzz/main.zig b/pkg/harfbuzz/main.zig index 12894b16d..70548e93f 100644 --- a/pkg/harfbuzz/main.zig +++ b/pkg/harfbuzz/main.zig @@ -1,5 +1,6 @@ pub const c = @import("c.zig"); pub usingnamespace @import("blob.zig"); +pub usingnamespace @import("buffer.zig"); pub usingnamespace @import("errors.zig"); pub usingnamespace @import("face.zig"); pub usingnamespace @import("font.zig");