ghostty/pkg/macos/text/font.zig
2022-10-07 21:04:30 -07:00

99 lines
2.9 KiB
Zig

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),
);
}
pub fn drawGlyphs(
self: *Font,
glyphs: []const graphics.Glyph,
positions: []const graphics.Point,
context: anytype, // Must be some context type from graphics
) void {
assert(positions.len == glyphs.len);
c.CTFontDrawGlyphs(
@ptrCast(c.CTFontRef, self),
glyphs.ptr,
@ptrCast([*]const c.struct_CGPoint, positions.ptr),
glyphs.len,
@ptrCast(c.CGContextRef, context),
);
}
pub fn copyAttribute(self: *Font, comptime attr: text.FontAttribute) attr.Value() {
return @intToPtr(attr.Value(), @ptrToInt(c.CTFontCopyAttribute(
@ptrCast(c.CTFontRef, self),
@ptrCast(c.CFStringRef, attr.key()),
)));
}
pub fn copyDisplayName(self: *Font) *foundation.String {
return @intToPtr(
*foundation.String,
@ptrToInt(c.CTFontCopyDisplayName(@ptrCast(c.CTFontRef, self))),
);
}
};
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);
// Draw
{
const cs = try graphics.ColorSpace.createDeviceGray();
defer cs.release();
const ctx = try graphics.BitmapContext.create(null, 80, 80, 8, 80, cs);
defer ctx.release();
var pos = [_]graphics.Point{.{ .x = 0, .y = 0 }};
font.drawGlyphs(
&glyphs,
&pos,
ctx,
);
}
}