diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig')
| -rw-r--r-- | vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig b/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig new file mode 100644 index 00000000..563165bc --- /dev/null +++ b/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig @@ -0,0 +1,287 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const foundation = @import("../foundation.zig"); +const c = @import("c.zig").c; + +pub const FontDescriptor = opaque { + pub fn createWithNameAndSize(name: *foundation.String, size: f64) Allocator.Error!*FontDescriptor { + return @as( + ?*FontDescriptor, + @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateWithNameAndSize(@ptrCast(name), size))), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn createWithAttributes(dict: *foundation.Dictionary) Allocator.Error!*FontDescriptor { + return @as( + ?*FontDescriptor, + @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateWithAttributes(@ptrCast(dict)))), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn createCopyWithAttributes( + original: *FontDescriptor, + dict: *foundation.Dictionary, + ) Allocator.Error!*FontDescriptor { + return @as( + ?*FontDescriptor, + @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateCopyWithAttributes( + @ptrCast(original), + @ptrCast(dict), + ))), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn createCopyWithVariation( + original: *FontDescriptor, + id: *foundation.Number, + value: f64, + ) Allocator.Error!*FontDescriptor { + return @as( + ?*FontDescriptor, + @ptrCast(@constCast(c.CTFontDescriptorCreateCopyWithVariation( + @ptrCast(original), + @ptrCast(id), + value, + ))), + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn retain(self: *FontDescriptor) void { + _ = c.CFRetain(self); + } + + pub fn release(self: *FontDescriptor) void { + c.CFRelease(self); + } + + pub fn copyAttribute(self: *const FontDescriptor, comptime attr: FontAttribute) ?attr.Value() { + return @ptrFromInt(@intFromPtr(c.CTFontDescriptorCopyAttribute( + @ptrCast(self), + @ptrCast(attr.key()), + ))); + } + + pub fn copyAttributes(self: *const FontDescriptor) *foundation.Dictionary { + return @ptrFromInt(@intFromPtr(c.CTFontDescriptorCopyAttributes( + @ptrCast(self), + ))); + } +}; + +pub const FontAttribute = enum { + url, + name, + display_name, + family_name, + style_name, + traits, + variation, + size, + matrix, + cascade_list, + character_set, + languages, + baseline_adjust, + macintosh_encodings, + features, + feature_settings, + fixed_advance, + orientation, + format, + registration_scope, + priority, + enabled, + downloadable, + downloaded, + + // https://developer.apple.com/documentation/coretext/core_text_constants?language=objc + variation_axes, + + pub fn key(self: FontAttribute) *foundation.String { + return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) { + .url => c.kCTFontURLAttribute, + .name => c.kCTFontNameAttribute, + .display_name => c.kCTFontDisplayNameAttribute, + .family_name => c.kCTFontFamilyNameAttribute, + .style_name => c.kCTFontStyleNameAttribute, + .traits => c.kCTFontTraitsAttribute, + .variation => c.kCTFontVariationAttribute, + .size => c.kCTFontSizeAttribute, + .matrix => c.kCTFontMatrixAttribute, + .cascade_list => c.kCTFontCascadeListAttribute, + .character_set => c.kCTFontCharacterSetAttribute, + .languages => c.kCTFontLanguagesAttribute, + .baseline_adjust => c.kCTFontBaselineAdjustAttribute, + .macintosh_encodings => c.kCTFontMacintoshEncodingsAttribute, + .features => c.kCTFontFeaturesAttribute, + .feature_settings => c.kCTFontFeatureSettingsAttribute, + .fixed_advance => c.kCTFontFixedAdvanceAttribute, + .orientation => c.kCTFontOrientationAttribute, + .format => c.kCTFontFormatAttribute, + .registration_scope => c.kCTFontRegistrationScopeAttribute, + .priority => c.kCTFontPriorityAttribute, + .enabled => c.kCTFontEnabledAttribute, + .downloadable => c.kCTFontDownloadableAttribute, + .downloaded => c.kCTFontDownloadedAttribute, + .variation_axes => c.kCTFontVariationAxesAttribute, + }))); + } + + pub fn Value(comptime self: FontAttribute) type { + return switch (self) { + .url => *foundation.URL, + .name => *foundation.String, + .display_name => *foundation.String, + .family_name => *foundation.String, + .style_name => *foundation.String, + .traits => *foundation.Dictionary, + .variation => *foundation.Dictionary, + .size => *foundation.Number, + .matrix => *anyopaque, // CFDataRef + .cascade_list => *foundation.Array, + .character_set => *anyopaque, // CFCharacterSetRef + .languages => *foundation.Array, + .baseline_adjust => *foundation.Number, + .macintosh_encodings => *foundation.Number, + .features => *foundation.Array, + .feature_settings => *foundation.Array, + .fixed_advance => *foundation.Number, + .orientation => *foundation.Number, + .format => *foundation.Number, + .registration_scope => *foundation.Number, + .priority => *foundation.Number, + .enabled => *foundation.Number, + .downloadable => *anyopaque, // CFBoolean + .downloaded => *anyopaque, // CFBoolean + .variation_axes => *foundation.Array, + }; + } +}; + +pub const FontTraitKey = enum { + symbolic, + weight, + width, + slant, + + pub fn key(self: FontTraitKey) *foundation.String { + return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) { + .symbolic => c.kCTFontSymbolicTrait, + .weight => c.kCTFontWeightTrait, + .width => c.kCTFontWidthTrait, + .slant => c.kCTFontSlantTrait, + }))); + } + + pub fn Value(self: FontTraitKey) type { + return switch (self) { + .symbolic => *foundation.Number, + .weight => *foundation.Number, + .width => *foundation.Number, + .slant => *foundation.Number, + }; + } +}; + +// https://developer.apple.com/documentation/coretext/ctfont/font_variation_axis_dictionary_keys?language=objc +pub const FontVariationAxisKey = enum { + identifier, + minimum_value, + maximum_value, + default_value, + name, + hidden, + + pub fn key(self: FontVariationAxisKey) *foundation.String { + return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) { + .identifier => c.kCTFontVariationAxisIdentifierKey, + .minimum_value => c.kCTFontVariationAxisMinimumValueKey, + .maximum_value => c.kCTFontVariationAxisMaximumValueKey, + .default_value => c.kCTFontVariationAxisDefaultValueKey, + .name => c.kCTFontVariationAxisNameKey, + .hidden => c.kCTFontVariationAxisHiddenKey, + }))); + } + + pub fn Value(comptime self: FontVariationAxisKey) type { + return switch (self) { + .identifier => foundation.Number, + .minimum_value => foundation.Number, + .maximum_value => foundation.Number, + .default_value => foundation.Number, + .name => foundation.String, + .hidden => foundation.Number, + }; + } +}; + +pub const FontSymbolicTraits = packed struct(u32) { + italic: bool = false, + bold: bool = false, + _unused1: u3 = 0, + expanded: bool = false, + condensed: bool = false, + _unused2: u3 = 0, + monospace: bool = false, + vertical: bool = false, + ui_optimized: bool = false, + color_glyphs: bool = false, + composite: bool = false, + _padding: u17 = 0, + + pub fn init(num: *foundation.Number) FontSymbolicTraits { + var raw: i32 = undefined; + _ = num.getValue(.sint32, &raw); + return @as(FontSymbolicTraits, @bitCast(raw)); + } + + test { + try std.testing.expectEqual( + @bitSizeOf(c.CTFontSymbolicTraits), + @bitSizeOf(FontSymbolicTraits), + ); + } + + test "bitcast" { + const actual: c.CTFontSymbolicTraits = c.kCTFontTraitMonoSpace | c.kCTFontTraitExpanded; + const expected: FontSymbolicTraits = .{ + .monospace = true, + .expanded = true, + }; + + try std.testing.expectEqual(actual, @as(c.CTFontSymbolicTraits, @bitCast(expected))); + } + + test "number" { + const raw: i32 = c.kCTFontTraitMonoSpace | c.kCTFontTraitExpanded; + const num = try foundation.Number.create(.sint32, &raw); + defer num.release(); + + const expected: FontSymbolicTraits = .{ .monospace = true, .expanded = true }; + const actual = FontSymbolicTraits.init(num); + try std.testing.expect(std.meta.eql(expected, actual)); + } +}; + +test { + @import("std").testing.refAllDecls(@This()); +} + +test "descriptor" { + const testing = std.testing; + + const name = try foundation.String.createWithBytes("foo", .utf8, false); + defer name.release(); + + const v = try FontDescriptor.createWithNameAndSize(name, 12); + defer v.release(); + + const copy_name = v.copyAttribute(.name).?; + defer copy_name.release(); + + { + var buf: [128]u8 = undefined; + const cstr = copy_name.cstring(&buf, .utf8).?; + try testing.expectEqualStrings("foo", cstr); + } +} |
