From 939e6e7a65e3ef40b53f81799401e6c17498121a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 2 Oct 2022 11:05:40 -0700 Subject: [PATCH] pkg/harfbuzz: add coretext compilation on macOS --- build.zig | 7 ++++++- pkg/harfbuzz/build.zig | 16 +++++++++++++++- pkg/harfbuzz/c.zig | 3 +++ pkg/harfbuzz/coretext.zig | 30 ++++++++++++++++++++++++++++++ pkg/harfbuzz/freetype.zig | 2 ++ pkg/harfbuzz/main.zig | 1 + 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 pkg/harfbuzz/coretext.zig diff --git a/build.zig b/build.zig index 57bae6254..b090cf49a 100644 --- a/build.zig +++ b/build.zig @@ -258,13 +258,18 @@ fn addDeps( }); // Harfbuzz - _ = try harfbuzz.link(b, step, .{ + const harfbuzz_step = try harfbuzz.link(b, step, .{ .freetype = .{ .enabled = true, .step = freetype_step, .include = &freetype.include_paths, }, + + .coretext = .{ + .enabled = enable_coretext, + }, }); + system_sdk.include(b, harfbuzz_step, .{}); // Libuv const libuv_step = try libuv.link(b, step); diff --git a/pkg/harfbuzz/build.zig b/pkg/harfbuzz/build.zig index b32792609..0ca97c598 100644 --- a/pkg/harfbuzz/build.zig +++ b/pkg/harfbuzz/build.zig @@ -1,5 +1,6 @@ const std = @import("std"); const freetypepkg = @import("../freetype/build.zig"); +const macospkg = @import("../macos/build.zig"); /// Directories with our includes. const root = thisDir() ++ "../../../vendor/harfbuzz/"; @@ -10,7 +11,7 @@ pub const include_paths = .{include_path}; pub const pkg = std.build.Pkg{ .name = "harfbuzz", .source = .{ .path = thisDir() ++ "/main.zig" }, - .dependencies = &.{freetypepkg.pkg}, + .dependencies = &.{ freetypepkg.pkg, macospkg.pkg }, }; fn thisDir() []const u8 { @@ -19,12 +20,17 @@ fn thisDir() []const u8 { pub const Options = struct { freetype: Freetype = .{}, + coretext: CoreText = .{}, pub const Freetype = struct { enabled: bool = false, step: ?*std.build.LibExeObjStep = null, include: ?[]const []const u8 = null, }; + + pub const CoreText = struct { + enabled: bool = false, + }; }; pub fn link( @@ -85,6 +91,14 @@ pub fn buildHarfbuzz( "-DHAVE_FT_GET_TRANSFORM=1", }); + if (opt.coretext.enabled) { + try flags.appendSlice(&.{ + "-DHAVE_CORETEXT=1", + }); + + lib.linkFramework("ApplicationServices"); + } + // C files lib.addCSourceFiles(srcs, flags.items); diff --git a/pkg/harfbuzz/c.zig b/pkg/harfbuzz/c.zig index 958e398ea..9f8790fe5 100644 --- a/pkg/harfbuzz/c.zig +++ b/pkg/harfbuzz/c.zig @@ -1,4 +1,7 @@ +const builtin = @import("builtin"); + pub usingnamespace @cImport({ @cInclude("hb.h"); @cInclude("hb-ft.h"); + if (builtin.os.tag == .macos) @cInclude("hb-coretext.h"); }); diff --git a/pkg/harfbuzz/coretext.zig b/pkg/harfbuzz/coretext.zig new file mode 100644 index 000000000..4253feddb --- /dev/null +++ b/pkg/harfbuzz/coretext.zig @@ -0,0 +1,30 @@ +const macos = @import("macos"); +const std = @import("std"); +const c = @import("c.zig"); +const Face = @import("face.zig").Face; +const Font = @import("font.zig").Font; +const Error = @import("errors.zig").Error; + +// Use custom extern functions so that the proper CoreText structs are used +// without a ptrcast. +extern fn hb_coretext_font_create(ct_face: *macos.text.Font) ?*c.hb_font_t; + +/// Creates an hb_font_t font object from the specified CTFontRef. +pub fn createFont(face: *macos.text.Font) Error!Font { + const handle = hb_coretext_font_create(face) orelse return Error.HarfbuzzFailed; + return Font{ .handle = handle }; +} + +test { + if (!@hasDecl(c, "hb_coretext_font_create")) return error.SkipZigTest; + + const name = try macos.foundation.String.createWithBytes("Monaco", .utf8, false); + defer name.release(); + const desc = try macos.text.FontDescriptor.createWithNameAndSize(name, 12); + defer desc.release(); + const font = try macos.text.Font.createWithFontDescriptor(desc, 12); + defer font.release(); + + var hb_font = try createFont(font); + defer hb_font.destroy(); +} diff --git a/pkg/harfbuzz/freetype.zig b/pkg/harfbuzz/freetype.zig index 6147fcb5e..c7d96b6b7 100644 --- a/pkg/harfbuzz/freetype.zig +++ b/pkg/harfbuzz/freetype.zig @@ -47,6 +47,8 @@ pub fn setFontFuncs(font: Font) void { } test { + if (!@hasDecl(c, "hb_ft_font_create_referenced")) return error.SkipZigTest; + const testing = std.testing; const testFont = freetype.testing.font_regular; const ftc = freetype.c; diff --git a/pkg/harfbuzz/main.zig b/pkg/harfbuzz/main.zig index 27195090f..6cbb1b2c3 100644 --- a/pkg/harfbuzz/main.zig +++ b/pkg/harfbuzz/main.zig @@ -8,6 +8,7 @@ pub usingnamespace @import("font.zig"); pub usingnamespace @import("shape.zig"); pub usingnamespace @import("version.zig"); pub const freetype = @import("freetype.zig"); +pub const coretext = @import("coretext.zig"); test { @import("std").testing.refAllDecls(@This());