diff --git a/pkg/macos/foundation/string.zig b/pkg/macos/foundation/string.zig index fb322c8b3..ce06fa410 100644 --- a/pkg/macos/foundation/string.zig +++ b/pkg/macos/foundation/string.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const assert = std.debug.assert; const Allocator = std.mem.Allocator; const foundation = @import("../foundation.zig"); const c = @import("c.zig"); @@ -100,6 +101,14 @@ pub const StringEncoding = enum(u32) { utf32_le = 0x1c000100, }; +pub fn stringGetSurrogatePairForLongCharacter( + ch: u32, + surrogates: []u16, +) bool { + assert(surrogates.len >= 2); + return c.CFStringGetSurrogatePairForLongCharacter(ch, surrogates.ptr) == 1; +} + test "string" { const testing = std.testing; @@ -119,3 +128,10 @@ test "string" { try testing.expectEqualStrings("hello world", cstr); } } + +test "unichar" { + const testing = std.testing; + + var unichars: [2]u16 = undefined; + try testing.expect(!stringGetSurrogatePairForLongCharacter('A', &unichars)); +} diff --git a/pkg/macos/graphics.zig b/pkg/macos/graphics.zig new file mode 100644 index 000000000..6a5a75933 --- /dev/null +++ b/pkg/macos/graphics.zig @@ -0,0 +1,6 @@ +pub const c = @import("graphics/c.zig"); +pub usingnamespace @import("graphics/font.zig"); + +test { + @import("std").testing.refAllDecls(@This()); +} diff --git a/pkg/macos/graphics/c.zig b/pkg/macos/graphics/c.zig new file mode 100644 index 000000000..fe755e76c --- /dev/null +++ b/pkg/macos/graphics/c.zig @@ -0,0 +1,3 @@ +pub usingnamespace @cImport({ + @cInclude("CoreGraphics/CoreGraphics.h"); +}); diff --git a/pkg/macos/graphics/font.zig b/pkg/macos/graphics/font.zig new file mode 100644 index 000000000..47089a70b --- /dev/null +++ b/pkg/macos/graphics/font.zig @@ -0,0 +1,3 @@ +const c = @import("c.zig"); + +pub const Glyph = c.CGGlyph; diff --git a/pkg/macos/main.zig b/pkg/macos/main.zig index d938a633d..91b99ce48 100644 --- a/pkg/macos/main.zig +++ b/pkg/macos/main.zig @@ -1,4 +1,5 @@ pub const foundation = @import("foundation.zig"); +pub const graphics = @import("graphics.zig"); pub const text = @import("text.zig"); test { diff --git a/pkg/macos/text.zig b/pkg/macos/text.zig index 4954e0afc..164e60d4e 100644 --- a/pkg/macos/text.zig +++ b/pkg/macos/text.zig @@ -1,3 +1,4 @@ +pub usingnamespace @import("text/font.zig"); pub usingnamespace @import("text/font_collection.zig"); pub usingnamespace @import("text/font_descriptor.zig"); diff --git a/pkg/macos/text/font.zig b/pkg/macos/text/font.zig new file mode 100644 index 000000000..3a7db565a --- /dev/null +++ b/pkg/macos/text/font.zig @@ -0,0 +1,53 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const foundation = @import("../foundation.zig"); +const graphics = @import("../graphics.zig"); +const text = @import("../text.zig"); +const c = @import("c.zig"); + +pub const Font = opaque { + pub fn createWithFontDescriptor(desc: *text.FontDescriptor, size: f32) Allocator.Error!*Font { + return @intToPtr( + ?*Font, + @ptrToInt(c.CTFontCreateWithFontDescriptor( + @ptrCast(c.CTFontDescriptorRef, desc), + size, + null, + )), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn release(self: *Font) void { + c.CFRelease(self); + } + + pub fn getGlyphsForCharacters(self: *Font, chars: []const u16, glyphs: []graphics.Glyph) bool { + assert(chars.len == glyphs.len); + return c.CTFontGetGlyphsForCharacters( + @ptrCast(c.CTFontRef, self), + chars.ptr, + glyphs.ptr, + @intCast(c_long, chars.len), + ); + } +}; + +test { + const testing = std.testing; + + const name = try foundation.String.createWithBytes("Monaco", .utf8, false); + defer name.release(); + const desc = try text.FontDescriptor.createWithNameAndSize(name, 12); + defer desc.release(); + + const font = try Font.createWithFontDescriptor(desc, 12); + defer font.release(); + + var glyphs = [1]graphics.Glyph{0}; + try testing.expect(font.getGlyphsForCharacters( + &[_]u16{'A'}, + &glyphs, + )); + try testing.expect(glyphs[0] > 0); +}