mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-05-16 21:28:38 +03:00
223 lines
6.4 KiB
Zig
223 lines
6.4 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 @as(
|
|
?*Font,
|
|
@ptrFromInt(@intFromPtr(c.CTFontCreateWithFontDescriptor(
|
|
@ptrCast(desc),
|
|
size,
|
|
null,
|
|
))),
|
|
) orelse Allocator.Error.OutOfMemory;
|
|
}
|
|
|
|
pub fn copyWithAttributes(self: *Font, size: f32, attrs: ?*text.FontDescriptor) Allocator.Error!*Font {
|
|
return @as(
|
|
?*Font,
|
|
@ptrFromInt(@intFromPtr(c.CTFontCreateCopyWithAttributes(
|
|
@ptrCast(self),
|
|
size,
|
|
null,
|
|
@ptrCast(attrs),
|
|
))),
|
|
) 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(self),
|
|
chars.ptr,
|
|
glyphs.ptr,
|
|
@intCast(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(self),
|
|
glyphs.ptr,
|
|
@ptrCast(positions.ptr),
|
|
glyphs.len,
|
|
@ptrCast(context),
|
|
);
|
|
}
|
|
|
|
pub fn getBoundingRectForGlyphs(
|
|
self: *Font,
|
|
orientation: FontOrientation,
|
|
glyphs: []const graphics.Glyph,
|
|
rects: ?[]graphics.Rect,
|
|
) graphics.Rect {
|
|
if (rects) |s| assert(glyphs.len == s.len);
|
|
return @bitCast(c.CTFontGetBoundingRectsForGlyphs(
|
|
@ptrCast(self),
|
|
@intFromEnum(orientation),
|
|
glyphs.ptr,
|
|
@ptrCast(if (rects) |s| s.ptr else null),
|
|
@intCast(glyphs.len),
|
|
));
|
|
}
|
|
|
|
pub fn getAdvancesForGlyphs(
|
|
self: *Font,
|
|
orientation: FontOrientation,
|
|
glyphs: []const graphics.Glyph,
|
|
advances: ?[]graphics.Size,
|
|
) f64 {
|
|
if (advances) |s| assert(glyphs.len == s.len);
|
|
return c.CTFontGetAdvancesForGlyphs(
|
|
@ptrCast(self),
|
|
@intFromEnum(orientation),
|
|
glyphs.ptr,
|
|
@ptrCast(if (advances) |s| s.ptr else null),
|
|
@intCast(glyphs.len),
|
|
);
|
|
}
|
|
|
|
pub fn copyAttribute(self: *Font, comptime attr: text.FontAttribute) attr.Value() {
|
|
return @ptrFromInt(@intFromPtr(c.CTFontCopyAttribute(
|
|
@ptrCast(self),
|
|
@ptrCast(attr.key()),
|
|
)));
|
|
}
|
|
|
|
pub fn copyDisplayName(self: *Font) *foundation.String {
|
|
return @ptrFromInt(@intFromPtr(c.CTFontCopyDisplayName(@ptrCast(self))));
|
|
}
|
|
|
|
pub fn getSymbolicTraits(self: *Font) text.FontSymbolicTraits {
|
|
return @bitCast(c.CTFontGetSymbolicTraits(@ptrCast(self)));
|
|
}
|
|
|
|
pub fn getAscent(self: *Font) f64 {
|
|
return c.CTFontGetAscent(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getDescent(self: *Font) f64 {
|
|
return c.CTFontGetDescent(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getLeading(self: *Font) f64 {
|
|
return c.CTFontGetLeading(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getBoundingBox(self: *Font) graphics.Rect {
|
|
return @bitCast(c.CTFontGetBoundingBox(@ptrCast(self)));
|
|
}
|
|
|
|
pub fn getUnderlinePosition(self: *Font) f64 {
|
|
return c.CTFontGetUnderlinePosition(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getUnderlineThickness(self: *Font) f64 {
|
|
return c.CTFontGetUnderlineThickness(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getUnitsPerEm(self: *Font) u32 {
|
|
return c.CTFontGetUnitsPerEm(@ptrCast(self));
|
|
}
|
|
|
|
pub fn getSize(self: *Font) f64 {
|
|
return c.CTFontGetSize(@ptrCast(self));
|
|
}
|
|
};
|
|
|
|
pub const FontOrientation = enum(c_uint) {
|
|
default = c.kCTFontOrientationDefault,
|
|
horizontal = c.kCTFontOrientationHorizontal,
|
|
vertical = c.kCTFontOrientationVertical,
|
|
};
|
|
|
|
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();
|
|
|
|
// Traits
|
|
{
|
|
const traits = font.getSymbolicTraits();
|
|
try testing.expect(!traits.color_glyphs);
|
|
}
|
|
|
|
var glyphs = [1]graphics.Glyph{0};
|
|
try testing.expect(font.getGlyphsForCharacters(
|
|
&[_]u16{'A'},
|
|
&glyphs,
|
|
));
|
|
try testing.expect(glyphs[0] > 0);
|
|
|
|
// Bounding rect
|
|
{
|
|
var rect = font.getBoundingRectForGlyphs(.horizontal, &glyphs, null);
|
|
try testing.expect(rect.size.width > 0);
|
|
|
|
var singles: [1]graphics.Rect = undefined;
|
|
rect = font.getBoundingRectForGlyphs(.horizontal, &glyphs, &singles);
|
|
try testing.expect(rect.size.width > 0);
|
|
try testing.expect(singles[0].size.width > 0);
|
|
}
|
|
|
|
// Advances
|
|
{
|
|
var advance = font.getAdvancesForGlyphs(.horizontal, &glyphs, null);
|
|
try testing.expect(advance > 0);
|
|
|
|
var singles: [1]graphics.Size = undefined;
|
|
advance = font.getAdvancesForGlyphs(.horizontal, &glyphs, &singles);
|
|
try testing.expect(advance > 0);
|
|
try testing.expect(singles[0].width > 0);
|
|
}
|
|
|
|
// Draw
|
|
{
|
|
const cs = try graphics.ColorSpace.createDeviceGray();
|
|
defer cs.release();
|
|
const ctx = try graphics.BitmapContext.create(null, 80, 80, 8, 80, cs, 0);
|
|
defer ctx.release();
|
|
|
|
var pos = [_]graphics.Point{.{ .x = 0, .y = 0 }};
|
|
font.drawGlyphs(
|
|
&glyphs,
|
|
&pos,
|
|
ctx,
|
|
);
|
|
}
|
|
}
|
|
|
|
test "copy" {
|
|
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();
|
|
|
|
const f2 = try font.copyWithAttributes(14, null);
|
|
defer f2.release();
|
|
}
|