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/fontconfig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/fontconfig')
22 files changed, 1467 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/pkg/fontconfig/build.zig b/vendor/libghostty-vt/pkg/fontconfig/build.zig new file mode 100644 index 00000000..7c87d1f2 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/build.zig @@ -0,0 +1,298 @@ +const std = @import("std"); +const NativeTargetInfo = std.zig.system.NativeTargetInfo; + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const libxml2_enabled = b.option(bool, "enable-libxml2", "Build libxml2") orelse true; + const libxml2_iconv_enabled = b.option( + bool, + "enable-libxml2-iconv", + "Build libxml2 with iconv", + ) orelse (target.result.os.tag != .windows); + const freetype_enabled = b.option(bool, "enable-freetype", "Build freetype") orelse true; + + const module = b.addModule("fontconfig", .{ + .root_source_file = b.path("main.zig"), + .target = target, + .optimize = optimize, + }); + + // For dynamic linking, we prefer dynamic linking and to search by + // mode first. Mode first will search all paths for a dynamic library + // before falling back to static. + const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{ + .preferred_link_mode = .dynamic, + .search_strategy = .mode_first, + }; + + const test_exe = b.addTest(.{ + .name = "test", + .root_module = b.createModule(.{ + .root_source_file = b.path("main.zig"), + .target = target, + .optimize = optimize, + }), + }); + const tests_run = b.addRunArtifact(test_exe); + const test_step = b.step("test", "Run tests"); + test_step.dependOn(&tests_run.step); + + if (b.systemIntegrationOption("fontconfig", .{})) { + module.linkSystemLibrary("fontconfig", dynamic_link_opts); + test_exe.linkSystemLibrary2("fontconfig", dynamic_link_opts); + } else { + const lib = try buildLib(b, module, .{ + .target = target, + .optimize = optimize, + + .libxml2_enabled = libxml2_enabled, + .libxml2_iconv_enabled = libxml2_iconv_enabled, + .freetype_enabled = freetype_enabled, + + .dynamic_link_opts = dynamic_link_opts, + }); + + test_exe.linkLibrary(lib); + } +} + +fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Build.Step.Compile { + const target = options.target; + const optimize = options.optimize; + + const libxml2_enabled = options.libxml2_enabled; + const libxml2_iconv_enabled = options.libxml2_iconv_enabled; + const freetype_enabled = options.freetype_enabled; + + const lib = b.addLibrary(.{ + .name = "fontconfig", + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + }), + .linkage = .static, + }); + lib.linkLibC(); + if (target.result.os.tag != .windows) { + lib.linkSystemLibrary("pthread"); + } + + lib.addIncludePath(b.path("override/include")); + module.addIncludePath(b.path("override/include")); + + var flags: std.ArrayList([]const u8) = .empty; + defer flags.deinit(b.allocator); + try flags.appendSlice(b.allocator, &.{ + "-DHAVE_DIRENT_H", + "-DHAVE_FCNTL_H", + "-DHAVE_STDLIB_H", + "-DHAVE_STRING_H", + "-DHAVE_UNISTD_H", + "-DHAVE_SYS_PARAM_H", + + "-DHAVE_MKSTEMP", + //"-DHAVE_GETPROGNAME", + //"-DHAVE_GETEXECNAME", + "-DHAVE_RAND", + //"-DHAVE_RANDOM_R", + "-DHAVE_VPRINTF", + + "-DHAVE_FT_GET_BDF_PROPERTY", + "-DHAVE_FT_GET_PS_FONT_INFO", + "-DHAVE_FT_HAS_PS_GLYPH_NAMES", + "-DHAVE_FT_GET_X11_FONT_FORMAT", + "-DHAVE_FT_DONE_MM_VAR", + + "-DHAVE_POSIX_FADVISE", + + //"-DHAVE_STRUCT_STATVFS_F_BASETYPE", + // "-DHAVE_STRUCT_STATVFS_F_FSTYPENAME", + // "-DHAVE_STRUCT_STATFS_F_FLAGS", + // "-DHAVE_STRUCT_STATFS_F_FSTYPENAME", + // "-DHAVE_STRUCT_DIRENT_D_TYPE", + + "-DFLEXIBLE_ARRAY_MEMBER", + + "-DHAVE_STDATOMIC_PRIMITIVES", + + "-DFC_GPERF_SIZE_T=size_t", + + // Default errors that fontconfig can't handle + "-Wno-implicit-function-declaration", + "-Wno-int-conversion", + + // https://gitlab.freedesktop.org/fontconfig/fontconfig/-/merge_requests/231 + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", + }); + + switch (target.result.ptrBitWidth()) { + 32 => try flags.appendSlice(b.allocator, &.{ + "-DSIZEOF_VOID_P=4", + "-DALIGNOF_VOID_P=4", + }), + + 64 => try flags.appendSlice(b.allocator, &.{ + "-DSIZEOF_VOID_P=8", + "-DALIGNOF_VOID_P=8", + }), + + else => @panic("unsupported arch"), + } + if (target.result.os.tag == .windows) { + try flags.appendSlice(b.allocator, &.{ + "-DFC_CACHEDIR=\"LOCAL_APPDATA_FONTCONFIG_CACHE\"", + "-DFC_TEMPLATEDIR=\"c:/share/fontconfig/conf.avail\"", + "-DCONFIGDIR=\"c:/etc/fonts/conf.d\"", + "-DFC_DEFAULT_FONTS=\"\\t<dir>WINDOWSFONTDIR</dir>\\n\\t<dir>WINDOWSUSERFONTDIR</dir>\\n\"", + }); + } else { + try flags.appendSlice(b.allocator, &.{ + "-DHAVE_FSTATFS", + "-DHAVE_FSTATVFS", + "-DHAVE_GETOPT", + "-DHAVE_GETOPT_LONG", + "-DHAVE_LINK", + "-DHAVE_LRAND48", + "-DHAVE_LSTAT", + "-DHAVE_MKDTEMP", + "-DHAVE_MKOSTEMP", + "-DHAVE__MKTEMP_S", + "-DHAVE_MMAP", + "-DHAVE_PTHREAD", + "-DHAVE_RANDOM", + "-DHAVE_RAND_R", + "-DHAVE_READLINK", + "-DHAVE_SYS_MOUNT_H", + "-DHAVE_SYS_STATVFS_H", + + "-DFC_CACHEDIR=\"/var/cache/fontconfig\"", + "-DFC_DEFAULT_FONTS=\"<dir>/usr/share/fonts</dir><dir>/usr/local/share/fonts</dir>\"", + }); + + if (target.result.os.tag == .freebsd) { + try flags.appendSlice(b.allocator, &.{ + "-DFC_TEMPLATEDIR=\"/usr/local/etc/fonts/conf.avail\"", + "-DFONTCONFIG_PATH=\"/usr/local/etc/fonts\"", + "-DCONFIGDIR=\"/usr/local/etc/fonts/conf.d\"", + }); + } else { + try flags.appendSlice(b.allocator, &.{ + "-DFC_TEMPLATEDIR=\"/usr/share/fontconfig/conf.avail\"", + "-DFONTCONFIG_PATH=\"/etc/fonts\"", + "-DCONFIGDIR=\"/usr/local/fontconfig/conf.d\"", + }); + } + + if (target.result.os.tag == .linux) { + try flags.appendSlice(b.allocator, &.{ + "-DHAVE_SYS_STATFS_H", + "-DHAVE_SYS_VFS_H", + }); + } + } + + const dynamic_link_opts = options.dynamic_link_opts; + + // Freetype2 + _ = b.systemIntegrationOption("freetype", .{}); // So it shows up in help + if (freetype_enabled) { + if (b.systemIntegrationOption("freetype", .{})) { + lib.linkSystemLibrary2("freetype2", dynamic_link_opts); + } else { + if (b.lazyDependency( + "freetype", + .{ .target = target, .optimize = optimize }, + )) |freetype_dep| { + lib.linkLibrary(freetype_dep.artifact("freetype")); + } + } + } + + // Libxml2 + _ = b.systemIntegrationOption("libxml2", .{}); // So it shows up in help + if (libxml2_enabled) { + try flags.appendSlice(b.allocator, &.{ + "-DENABLE_LIBXML2", + "-DLIBXML_STATIC", + "-DLIBXML_PUSH_ENABLED", + }); + if (target.result.os.tag == .windows) { + // NOTE: this should be defined on all targets + try flags.appendSlice(b.allocator, &.{ + "-Werror=implicit-function-declaration", + }); + } + + if (b.systemIntegrationOption("libxml2", .{})) { + lib.linkSystemLibrary2("libxml-2.0", dynamic_link_opts); + } else { + if (b.lazyDependency("libxml2", .{ + .target = target, + .optimize = optimize, + .iconv = libxml2_iconv_enabled, + })) |libxml2_dep| { + lib.linkLibrary(libxml2_dep.artifact("xml2")); + } + } + } + + if (b.lazyDependency("fontconfig", .{})) |upstream| { + lib.addIncludePath(upstream.path("")); + module.addIncludePath(upstream.path("")); + lib.addCSourceFiles(.{ + .root = upstream.path(""), + .files = srcs, + .flags = flags.items, + }); + + lib.installHeadersDirectory( + upstream.path("fontconfig"), + "fontconfig", + .{ .include_extensions = &.{".h"} }, + ); + } + + b.installArtifact(lib); + + return lib; +} + +const headers = &.{ + "fontconfig/fontconfig.h", + "fontconfig/fcprivate.h", + "fontconfig/fcfreetype.h", +}; + +const srcs: []const []const u8 = &.{ + "src/fcatomic.c", + "src/fccache.c", + "src/fccfg.c", + "src/fccharset.c", + "src/fccompat.c", + "src/fcdbg.c", + "src/fcdefault.c", + "src/fcdir.c", + "src/fcformat.c", + "src/fcfreetype.c", + "src/fcfs.c", + "src/fcptrlist.c", + "src/fchash.c", + "src/fcinit.c", + "src/fclang.c", + "src/fclist.c", + "src/fcmatch.c", + "src/fcmatrix.c", + "src/fcname.c", + "src/fcobjs.c", + "src/fcpat.c", + "src/fcrange.c", + "src/fcserialize.c", + "src/fcstat.c", + "src/fcstr.c", + "src/fcweight.c", + "src/fcxml.c", + "src/ftglue.c", +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/build.zig.zon b/vendor/libghostty-vt/pkg/fontconfig/build.zig.zon new file mode 100644 index 00000000..b1387b87 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/build.zig.zon @@ -0,0 +1,16 @@ +.{ + .name = .fontconfig, + .version = "2.14.2", + .fingerprint = 0x4a79a5a40c6d6d8, + .paths = .{""}, + .dependencies = .{ + .fontconfig = .{ + .url = "https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz", + .hash = "N-V-__8AAIrfdwARSa-zMmxWwFuwpXf1T3asIN7s5jqi9c1v", + .lazy = true, + }, + + .freetype = .{ .path = "../freetype", .lazy = true }, + .libxml2 = .{ .path = "../libxml2", .lazy = true }, + }, +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/c.zig b/vendor/libghostty-vt/pkg/fontconfig/c.zig new file mode 100644 index 00000000..6e8ae76b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/c.zig @@ -0,0 +1,3 @@ +pub const c = @cImport({ + @cInclude("fontconfig/fontconfig.h"); +}); diff --git a/vendor/libghostty-vt/pkg/fontconfig/char_set.zig b/vendor/libghostty-vt/pkg/fontconfig/char_set.zig new file mode 100644 index 00000000..b0e3a341 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/char_set.zig @@ -0,0 +1,40 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; + +pub const CharSet = opaque { + pub fn create() *CharSet { + return @ptrCast(c.FcCharSetCreate()); + } + + pub fn destroy(self: *CharSet) void { + c.FcCharSetDestroy(self.cval()); + } + + pub fn addChar(self: *CharSet, cp: u32) bool { + return c.FcCharSetAddChar(self.cval(), cp) == c.FcTrue; + } + + pub fn hasChar(self: *const CharSet, cp: u32) bool { + return c.FcCharSetHasChar(self.cvalConst(), cp) == c.FcTrue; + } + + pub inline fn cval(self: *CharSet) *c.struct__FcCharSet { + return @ptrCast(self); + } + + pub inline fn cvalConst(self: *const CharSet) *const c.struct__FcCharSet { + return @ptrCast(self); + } +}; + +test "create" { + const testing = std.testing; + + var fs = CharSet.create(); + defer fs.destroy(); + + try testing.expect(!fs.hasChar(0x20)); + try testing.expect(fs.addChar(0x20)); + try testing.expect(fs.hasChar(0x20)); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/common.zig b/vendor/libghostty-vt/pkg/fontconfig/common.zig new file mode 100644 index 00000000..6ad6f568 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/common.zig @@ -0,0 +1,139 @@ +const std = @import("std"); +const c = @import("c.zig").c; +const Error = @import("main.zig").Error; + +pub const Weight = enum(c_uint) { + thin = c.FC_WEIGHT_THIN, + extralight = c.FC_WEIGHT_EXTRALIGHT, + light = c.FC_WEIGHT_LIGHT, + demilight = c.FC_WEIGHT_DEMILIGHT, + book = c.FC_WEIGHT_BOOK, + regular = c.FC_WEIGHT_REGULAR, + medium = c.FC_WEIGHT_MEDIUM, + demibold = c.FC_WEIGHT_DEMIBOLD, + bold = c.FC_WEIGHT_BOLD, + extrabold = c.FC_WEIGHT_EXTRABOLD, + black = c.FC_WEIGHT_BLACK, + extrablack = c.FC_WEIGHT_EXTRABLACK, +}; + +pub const Slant = enum(c_uint) { + roman = c.FC_SLANT_ROMAN, + italic = c.FC_SLANT_ITALIC, + oblique = c.FC_SLANT_OBLIQUE, +}; + +pub const Spacing = enum(c_uint) { + proportional = c.FC_PROPORTIONAL, + dual = c.FC_DUAL, + mono = c.FC_MONO, + charcell = c.FC_CHARCELL, +}; + +pub const Property = enum { + family, + style, + slant, + weight, + size, + aspect, + pixel_size, + spacing, + foundry, + antialias, + hinting, + hint_style, + vertical_layout, + autohint, + global_advance, + width, + file, + index, + ft_face, + rasterizer, + outline, + scalable, + color, + variable, + scale, + symbol, + dpi, + rgba, + minspace, + source, + charset, + lang, + fontversion, + fullname, + familylang, + stylelang, + fullnamelang, + capability, + embolden, + embedded_bitmap, + decorative, + lcd_filter, + font_features, + font_variations, + namelang, + prgname, + hash, + postscript_name, + font_has_hint, + order, + + pub fn cval(self: Property) [:0]const u8 { + @setEvalBranchQuota(10_000); + inline for (@typeInfo(Property).@"enum".fields) |field| { + if (self == @field(Property, field.name)) { + // Build our string in a comptime context so it is a binary + // constant and not stack allocated. + return comptime name: { + // Replace _ with "" + var buf: [field.name.len]u8 = undefined; + const count = std.mem.replace(u8, field.name, "_", "", &buf); + const replaced = buf[0 .. field.name.len - count]; + + // Build our string + var name: [replaced.len:0]u8 = undefined; + @memcpy(&name, replaced); + name[replaced.len] = 0; + const final = name; + break :name &final; + }; + } + } + + unreachable; + } + + test "cval" { + const testing = std.testing; + try testing.expectEqualStrings("family", Property.family.cval()); + try testing.expectEqualStrings("pixelsize", Property.pixel_size.cval()); + } +}; + +pub const Result = enum(c_uint) { + match = c.FcResultMatch, + no_match = c.FcResultNoMatch, + type_mismatch = c.FcResultTypeMismatch, + no_id = c.FcResultNoId, + out_of_memory = c.FcResultOutOfMemory, + + pub fn toError(self: Result) Error!void { + return switch (self) { + .match => {}, + .no_match => Error.FontconfigNoMatch, + .type_mismatch => Error.FontconfigTypeMismatch, + .no_id => Error.FontconfigNoId, + .out_of_memory => Error.OutOfMemory, + }; + } +}; + +pub const MatchKind = enum(c_uint) { + pattern = c.FcMatchPattern, + font = c.FcMatchFont, + scan = c.FcMatchScan, +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/config.zig b/vendor/libghostty-vt/pkg/fontconfig/config.zig new file mode 100644 index 00000000..2b3674c5 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/config.zig @@ -0,0 +1,61 @@ +const std = @import("std"); +const c = @import("c.zig").c; +const Error = @import("main.zig").Error; +const CharSet = @import("char_set.zig").CharSet; +const FontSet = @import("font_set.zig").FontSet; +const ObjectSet = @import("object_set.zig").ObjectSet; +const Pattern = @import("pattern.zig").Pattern; +const Result = @import("main.zig").Result; +const MatchKind = @import("main.zig").MatchKind; + +pub const Config = opaque { + pub fn destroy(self: *Config) void { + c.FcConfigDestroy(@ptrCast(self)); + } + + pub fn fontList(self: *Config, pat: *Pattern, os: *ObjectSet) *FontSet { + return @ptrCast(c.FcFontList(self.cval(), pat.cval(), os.cval())); + } + + pub fn fontSort( + self: *Config, + pat: *Pattern, + trim: bool, + charset: ?[*]*CharSet, + ) FontSortResult { + var result: FontSortResult = undefined; + result.fs = @ptrCast(c.FcFontSort( + self.cval(), + pat.cval(), + if (trim) c.FcTrue else c.FcFalse, + @ptrCast(charset), + @ptrCast(&result.result), + )); + + return result; + } + + pub fn fontRenderPrepare(self: *Config, pat: *Pattern, font: *Pattern) Error!*Pattern { + return @as( + ?*Pattern, + @ptrCast(c.FcFontRenderPrepare(self.cval(), pat.cval(), font.cval())), + ) orelse Error.FontconfigFailed; + } + + pub fn substituteWithPat(self: *Config, pat: *Pattern, kind: MatchKind) bool { + return c.FcConfigSubstitute( + self.cval(), + pat.cval(), + @intFromEnum(kind), + ) == c.FcTrue; + } + + pub inline fn cval(self: *Config) *c.struct__FcConfig { + return @ptrCast(self); + } +}; + +pub const FontSortResult = struct { + result: Result, + fs: *FontSet, +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/error.zig b/vendor/libghostty-vt/pkg/fontconfig/error.zig new file mode 100644 index 00000000..dd88b411 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/error.zig @@ -0,0 +1,7 @@ +pub const Error = error{ + OutOfMemory, + FontconfigFailed, + FontconfigNoMatch, + FontconfigTypeMismatch, + FontconfigNoId, +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/font_set.zig b/vendor/libghostty-vt/pkg/fontconfig/font_set.zig new file mode 100644 index 00000000..c5a8c5f9 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/font_set.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; +const Pattern = @import("pattern.zig").Pattern; + +pub const FontSet = opaque { + pub fn create() *FontSet { + return @ptrCast(c.FcFontSetCreate()); + } + + pub fn destroy(self: *FontSet) void { + c.FcFontSetDestroy(self.cval()); + } + + pub fn fonts(self: *FontSet) []*Pattern { + const empty: [0]*Pattern = undefined; + const s = self.cval(); + if (s.fonts == null) return ∅ + const ptr: [*]*Pattern = @ptrCast(@alignCast(s.fonts)); + const len: usize = @intCast(s.nfont); + return ptr[0..len]; + } + + pub fn add(self: *FontSet, pat: *Pattern) bool { + return c.FcFontSetAdd(self.cval(), pat.cval()) == c.FcTrue; + } + + pub fn print(self: *FontSet) void { + c.FcFontSetPrint(self.cval()); + } + + pub inline fn cval(self: *FontSet) *c.struct__FcFontSet { + return @ptrCast(@alignCast(self)); + } +}; + +test "create" { + const testing = std.testing; + + var fs = FontSet.create(); + defer fs.destroy(); + + try testing.expectEqual(@as(usize, 0), fs.fonts().len); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/init.zig b/vendor/libghostty-vt/pkg/fontconfig/init.zig new file mode 100644 index 00000000..6e8f4d61 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/init.zig @@ -0,0 +1,43 @@ +const std = @import("std"); +const c = @import("c.zig").c; +const Config = @import("config.zig").Config; + +pub fn init() bool { + return c.FcInit() == c.FcTrue; +} + +pub fn fini() void { + c.FcFini(); +} + +pub fn initLoadConfig() *Config { + return @ptrCast(c.FcInitLoadConfig()); +} + +pub fn initLoadConfigAndFonts() *Config { + return @ptrCast(c.FcInitLoadConfigAndFonts()); +} + +pub fn version() u32 { + return @intCast(c.FcGetVersion()); +} + +test "version" { + const testing = std.testing; + try testing.expect(version() > 0); +} + +test "init" { + try std.testing.expect(init()); + defer fini(); +} + +test "initLoadConfig" { + var config = initLoadConfig(); + defer config.destroy(); +} + +test "initLoadConfigAndFonts" { + var config = initLoadConfigAndFonts(); + defer config.destroy(); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/lang_set.zig b/vendor/libghostty-vt/pkg/fontconfig/lang_set.zig new file mode 100644 index 00000000..abefcc3e --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/lang_set.zig @@ -0,0 +1,61 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; + +pub const LangSet = opaque { + pub fn create() *LangSet { + return @ptrCast(c.FcLangSetCreate()); + } + + pub fn destroy(self: *LangSet) void { + c.FcLangSetDestroy(self.cval()); + } + + pub fn addLang(self: *LangSet, lang: [:0]const u8) bool { + return c.FcLangSetAdd(self.cval(), lang.ptr) == c.FcTrue; + } + + pub fn hasLang(self: *const LangSet, lang: [:0]const u8) bool { + return c.FcLangSetHasLang(self.cvalConst(), lang.ptr) == c.FcLangEqual; + } + + pub inline fn cval(self: *LangSet) *c.struct__FcLangSet { + return @ptrCast(self); + } + + pub inline fn cvalConst(self: *const LangSet) *const c.struct__FcLangSet { + return @ptrCast(self); + } +}; + +test "create" { + const testing = std.testing; + + var fs = LangSet.create(); + defer fs.destroy(); + + try testing.expect(!fs.hasLang("und-zsye")); +} + +test "hasLang exact match" { + const testing = std.testing; + + // Test exact match: langset with "en-US" should return true for "en-US" + var fs = LangSet.create(); + defer fs.destroy(); + try testing.expect(fs.addLang("en-US")); + try testing.expect(fs.hasLang("en-US")); + + // Test exact match: langset with "und-zsye" should return true for "und-zsye" + var fs_emoji = LangSet.create(); + defer fs_emoji.destroy(); + try testing.expect(fs_emoji.addLang("und-zsye")); + try testing.expect(fs_emoji.hasLang("und-zsye")); + + // Test mismatch: langset with "en-US" should return false for "fr" + try testing.expect(!fs.hasLang("fr")); + + // Test partial match: langset with "en-US" should return false for "en-GB" + // (different territory, but we only want exact matches) + try testing.expect(!fs.hasLang("en-GB")); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/main.zig b/vendor/libghostty-vt/pkg/fontconfig/main.zig new file mode 100644 index 00000000..61f8a329 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/main.zig @@ -0,0 +1,45 @@ +const initpkg = @import("init.zig"); +const char_set = @import("char_set.zig"); +const common = @import("common.zig"); +const config = @import("config.zig"); +const errorpkg = @import("error.zig"); +const font_set = @import("font_set.zig"); +const lang_set = @import("lang_set.zig"); +const matrix = @import("matrix.zig"); +const object_set = @import("object_set.zig"); +const pattern = @import("pattern.zig"); +const range = @import("range.zig"); +const value = @import("value.zig"); + +pub const c = @import("c.zig").c; +pub const init = initpkg.init; +pub const fini = initpkg.fini; +pub const initLoadConfig = initpkg.initLoadConfig; +pub const initLoadConfigAndFonts = initpkg.initLoadConfigAndFonts; +pub const version = initpkg.version; +pub const CharSet = char_set.CharSet; +pub const Weight = common.Weight; +pub const Slant = common.Slant; +pub const Spacing = common.Spacing; +pub const Property = common.Property; +pub const Result = common.Result; +pub const MatchKind = common.MatchKind; +pub const Config = config.Config; +pub const Error = errorpkg.Error; +pub const FontSet = font_set.FontSet; +pub const LangSet = lang_set.LangSet; +pub const Matrix = matrix.Matrix; +pub const ObjectSet = object_set.ObjectSet; +pub const Pattern = pattern.Pattern; +pub const Range = range.Range; +pub const Type = value.Type; +pub const Value = value.Value; +pub const ValueBinding = value.ValueBinding; + +test { + @import("std").testing.refAllDecls(@This()); +} + +test { + _ = @import("test.zig"); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/matrix.zig b/vendor/libghostty-vt/pkg/fontconfig/matrix.zig new file mode 100644 index 00000000..a9b05a9e --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/matrix.zig @@ -0,0 +1,10 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; + +pub const Matrix = extern struct { + xx: f64, + xy: f64, + yx: f64, + yy: f64, +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/object_set.zig b/vendor/libghostty-vt/pkg/fontconfig/object_set.zig new file mode 100644 index 00000000..29cf6386 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/object_set.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const c = @import("c.zig").c; +const Property = @import("main.zig").Property; + +pub const ObjectSet = opaque { + pub fn create() *ObjectSet { + return @ptrCast(c.FcObjectSetCreate()); + } + + pub fn destroy(self: *ObjectSet) void { + c.FcObjectSetDestroy(self.cval()); + } + + pub fn add(self: *ObjectSet, p: Property) bool { + return c.FcObjectSetAdd(self.cval(), p.cval().ptr) == c.FcTrue; + } + + pub inline fn cval(self: *ObjectSet) *c.struct__FcObjectSet { + return @ptrCast(@alignCast(self)); + } +}; + +test "create" { + const testing = std.testing; + + var os = ObjectSet.create(); + defer os.destroy(); + + try testing.expect(os.add(.family)); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/override/include/fcalias.h b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcalias.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcalias.h diff --git a/vendor/libghostty-vt/pkg/fontconfig/override/include/fcaliastail.h b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcaliastail.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcaliastail.h diff --git a/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftalias.h b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftalias.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftalias.h diff --git a/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftaliastail.h b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftaliastail.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcftaliastail.h diff --git a/vendor/libghostty-vt/pkg/fontconfig/override/include/fcobjshash.h b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcobjshash.h new file mode 100644 index 00000000..f06234ac --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/override/include/fcobjshash.h @@ -0,0 +1,347 @@ +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf --pic -m 100 fcobjshash.gperf */ +/* Computed positions: -k'3,5' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." +#endif + +#line 1 "fcobjshash.gperf" + +#line 13 "fcobjshash.gperf" +struct FcObjectTypeInfo { +int name; +int id; +}; +#include <string.h> +/* maximum key range = 59, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +FcObjectTypeHash (register const char *str, register size_t len) +{ + static const unsigned char asso_values[] = + { + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 4, 10, 32, + 21, 29, 28, 49, 14, 4, 66, 66, 5, 31, + 18, 22, 27, 66, 15, 9, 8, 23, 23, 13, + 23, 16, 4, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66 + }; + register unsigned int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[4]]; + /*FALLTHROUGH*/ + case 4: + case 3: + hval += asso_values[(unsigned char)str[2]]; + break; + } + return hval; +} + +struct FcObjectTypeNamePool_t + { + char FcObjectTypeNamePool_str7[sizeof("dpi")]; + char FcObjectTypeNamePool_str8[sizeof("size")]; + char FcObjectTypeNamePool_str9[sizeof("file")]; + char FcObjectTypeNamePool_str13[sizeof("hash")]; + char FcObjectTypeNamePool_str14[sizeof("rgba")]; + char FcObjectTypeNamePool_str15[sizeof("spacing")]; + char FcObjectTypeNamePool_str16[sizeof("scalable")]; + char FcObjectTypeNamePool_str17[sizeof("slant")]; + char FcObjectTypeNamePool_str18[sizeof("matrix")]; + char FcObjectTypeNamePool_str19[sizeof("outline")]; + char FcObjectTypeNamePool_str20[sizeof("charset")]; + char FcObjectTypeNamePool_str21[sizeof("antialias")]; + char FcObjectTypeNamePool_str22[sizeof("lang")]; + char FcObjectTypeNamePool_str23[sizeof("embolden")]; + char FcObjectTypeNamePool_str24[sizeof("weight")]; + char FcObjectTypeNamePool_str25[sizeof("color")]; + char FcObjectTypeNamePool_str26[sizeof("charwidth")]; + char FcObjectTypeNamePool_str27[sizeof("variable")]; + char FcObjectTypeNamePool_str28[sizeof("charheight")]; + char FcObjectTypeNamePool_str29[sizeof("hinting")]; + char FcObjectTypeNamePool_str30[sizeof("autohint")]; + char FcObjectTypeNamePool_str31[sizeof("fullname")]; + char FcObjectTypeNamePool_str32[sizeof("postscriptname")]; + char FcObjectTypeNamePool_str33[sizeof("verticallayout")]; + char FcObjectTypeNamePool_str34[sizeof("lcdfilter")]; + char FcObjectTypeNamePool_str35[sizeof("fullnamelang")]; + char FcObjectTypeNamePool_str36[sizeof("hintstyle")]; + char FcObjectTypeNamePool_str37[sizeof("pixelsize")]; + char FcObjectTypeNamePool_str38[sizeof("scale")]; + char FcObjectTypeNamePool_str39[sizeof("globaladvance")]; + char FcObjectTypeNamePool_str40[sizeof("width")]; + char FcObjectTypeNamePool_str41[sizeof("order")]; + char FcObjectTypeNamePool_str42[sizeof("family")]; + char FcObjectTypeNamePool_str43[sizeof("fonthashint")]; + char FcObjectTypeNamePool_str44[sizeof("namelang")]; + char FcObjectTypeNamePool_str45[sizeof("embeddedbitmap")]; + char FcObjectTypeNamePool_str46[sizeof("familylang")]; + char FcObjectTypeNamePool_str47[sizeof("capability")]; + char FcObjectTypeNamePool_str48[sizeof("rasterizer")]; + char FcObjectTypeNamePool_str49[sizeof("index")]; + char FcObjectTypeNamePool_str50[sizeof("style")]; + char FcObjectTypeNamePool_str51[sizeof("foundry")]; + char FcObjectTypeNamePool_str52[sizeof("fontversion")]; + char FcObjectTypeNamePool_str53[sizeof("minspace")]; + char FcObjectTypeNamePool_str54[sizeof("stylelang")]; + char FcObjectTypeNamePool_str55[sizeof("fontvariations")]; + char FcObjectTypeNamePool_str56[sizeof("fontformat")]; + char FcObjectTypeNamePool_str57[sizeof("decorative")]; + char FcObjectTypeNamePool_str58[sizeof("fontfeatures")]; + char FcObjectTypeNamePool_str59[sizeof("symbol")]; + char FcObjectTypeNamePool_str60[sizeof("prgname")]; + char FcObjectTypeNamePool_str65[sizeof("aspect")]; + }; +static const struct FcObjectTypeNamePool_t FcObjectTypeNamePool_contents = + { + "dpi", + "size", + "file", + "hash", + "rgba", + "spacing", + "scalable", + "slant", + "matrix", + "outline", + "charset", + "antialias", + "lang", + "embolden", + "weight", + "color", + "charwidth", + "variable", + "charheight", + "hinting", + "autohint", + "fullname", + "postscriptname", + "verticallayout", + "lcdfilter", + "fullnamelang", + "hintstyle", + "pixelsize", + "scale", + "globaladvance", + "width", + "order", + "family", + "fonthashint", + "namelang", + "embeddedbitmap", + "familylang", + "capability", + "rasterizer", + "index", + "style", + "foundry", + "fontversion", + "minspace", + "stylelang", + "fontvariations", + "fontformat", + "decorative", + "fontfeatures", + "symbol", + "prgname", + "aspect" + }; +#define FcObjectTypeNamePool ((const char *) &FcObjectTypeNamePool_contents) +const struct FcObjectTypeInfo * +FcObjectTypeLookup (register const char *str, register size_t len) +{ + enum + { + TOTAL_KEYWORDS = 52, + MIN_WORD_LENGTH = 3, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 7, + MAX_HASH_VALUE = 65 + }; + + static const struct FcObjectTypeInfo wordlist[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 43 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str7,FC_DPI_OBJECT}, +#line 27 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str8,FC_SIZE_OBJECT}, +#line 38 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str9,FC_FILE_OBJECT}, + {-1}, {-1}, {-1}, +#line 62 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str13,FC_HASH_OBJECT}, +#line 44 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str14,FC_RGBA_OBJECT}, +#line 30 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str15,FC_SPACING_OBJECT}, +#line 42 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str16,FC_SCALABLE_OBJECT}, +#line 24 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str17,FC_SLANT_OBJECT}, +#line 49 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str18,FC_MATRIX_OBJECT}, +#line 41 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str19,FC_OUTLINE_OBJECT}, +#line 50 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str20,FC_CHARSET_OBJECT}, +#line 32 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str21,FC_ANTIALIAS_OBJECT}, +#line 51 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str22,FC_LANG_OBJECT}, +#line 55 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str23,FC_EMBOLDEN_OBJECT}, +#line 25 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str24,FC_WEIGHT_OBJECT}, +#line 64 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str25,FC_COLOR_OBJECT}, +#line 47 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str26,FC_CHARWIDTH_OBJECT}, +#line 67 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str27,FC_VARIABLE_OBJECT}, +#line 48 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str28,FC_CHAR_HEIGHT_OBJECT}, +#line 34 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str29,FC_HINTING_OBJECT}, +#line 36 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str30,FC_AUTOHINT_OBJECT}, +#line 22 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str31,FC_FULLNAME_OBJECT}, +#line 63 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str32,FC_POSTSCRIPT_NAME_OBJECT}, +#line 35 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str33,FC_VERTICAL_LAYOUT_OBJECT}, +#line 58 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str34,FC_LCD_FILTER_OBJECT}, +#line 23 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str35,FC_FULLNAMELANG_OBJECT}, +#line 33 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str36,FC_HINT_STYLE_OBJECT}, +#line 29 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str37,FC_PIXEL_SIZE_OBJECT}, +#line 45 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str38,FC_SCALE_OBJECT}, +#line 37 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str39,FC_GLOBAL_ADVANCE_OBJECT}, +#line 26 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str40,FC_WIDTH_OBJECT}, +#line 69 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str41,FC_ORDER_OBJECT}, +#line 18 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str42,FC_FAMILY_OBJECT}, +#line 68 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str43,FC_FONT_HAS_HINT_OBJECT}, +#line 59 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str44,FC_NAMELANG_OBJECT}, +#line 56 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str45,FC_EMBEDDED_BITMAP_OBJECT}, +#line 19 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str46,FC_FAMILYLANG_OBJECT}, +#line 53 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str47,FC_CAPABILITY_OBJECT}, +#line 40 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str48,FC_RASTERIZER_OBJECT}, +#line 39 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str49,FC_INDEX_OBJECT}, +#line 20 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str50,FC_STYLE_OBJECT}, +#line 31 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str51,FC_FOUNDRY_OBJECT}, +#line 52 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str52,FC_FONTVERSION_OBJECT}, +#line 46 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str53,FC_MINSPACE_OBJECT}, +#line 21 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str54,FC_STYLELANG_OBJECT}, +#line 66 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str55,FC_FONT_VARIATIONS_OBJECT}, +#line 54 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str56,FC_FONTFORMAT_OBJECT}, +#line 57 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str57,FC_DECORATIVE_OBJECT}, +#line 60 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str58,FC_FONT_FEATURES_OBJECT}, +#line 65 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str59,FC_SYMBOL_OBJECT}, +#line 61 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str60,FC_PRGNAME_OBJECT}, + {-1}, {-1}, {-1}, {-1}, +#line 28 "fcobjshash.gperf" + {(int)(size_t)&((struct FcObjectTypeNamePool_t *)0)->FcObjectTypeNamePool_str65,FC_ASPECT_OBJECT} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register unsigned int key = FcObjectTypeHash (str, len); + + if (key <= MAX_HASH_VALUE) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + FcObjectTypeNamePool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[key]; + } + } + } + return 0; +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/pattern.zig b/vendor/libghostty-vt/pkg/fontconfig/pattern.zig new file mode 100644 index 00000000..3a623e22 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/pattern.zig @@ -0,0 +1,168 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; +const Error = @import("main.zig").Error; +const ObjectSet = @import("main.zig").ObjectSet; +const Property = @import("main.zig").Property; +const Result = @import("main.zig").Result; +const Value = @import("main.zig").Value; +const ValueBinding = @import("main.zig").ValueBinding; +const Weight = @import("main.zig").Weight; + +pub const Pattern = opaque { + pub fn create() *Pattern { + return @ptrCast(c.FcPatternCreate()); + } + + pub fn parse(str: [:0]const u8) *Pattern { + return @ptrCast(c.FcNameParse(str.ptr)); + } + + pub fn destroy(self: *Pattern) void { + c.FcPatternDestroy(self.cval()); + } + + pub fn defaultSubstitute(self: *Pattern) void { + c.FcDefaultSubstitute(self.cval()); + } + + pub fn add(self: *Pattern, prop: Property, value: Value, append: bool) bool { + return c.FcPatternAdd( + self.cval(), + prop.cval().ptr, + value.cval(), + if (append) c.FcTrue else c.FcFalse, + ) == c.FcTrue; + } + + pub fn get(self: *Pattern, prop: Property, id: u32) Error!Value { + var val: c.struct__FcValue = undefined; + try @as(Result, @enumFromInt(c.FcPatternGet( + self.cval(), + prop.cval().ptr, + @intCast(id), + &val, + ))).toError(); + + return .init(&val); + } + + pub fn delete(self: *Pattern, prop: Property) bool { + return c.FcPatternDel(self.cval(), prop.cval()) == c.FcTrue; + } + + pub fn filter(self: *Pattern, os: *const ObjectSet) *Pattern { + return @ptrCast(c.FcPatternFilter(self.cval(), os.cval())); + } + + pub fn objectIterator(self: *Pattern) ObjectIterator { + return .{ .pat = self.cval(), .iter = null }; + } + + pub fn print(self: *Pattern) void { + c.FcPatternPrint(self.cval()); + } + + pub inline fn cval(self: *Pattern) *c.struct__FcPattern { + return @ptrCast(self); + } + + pub const ObjectIterator = struct { + pat: *c.struct__FcPattern, + iter: ?c.struct__FcPatternIter, + + /// Move to the next object, returns true if there is another + /// object and false otherwise. If this is the first call, this + /// will be the first object. + pub fn next(self: *ObjectIterator) bool { + // Null means our first iterator + if (self.iter == null) { + // If we have no objects, do not create iterator + if (c.FcPatternObjectCount(self.pat) == 0) return false; + + var iter: c.struct__FcPatternIter = undefined; + c.FcPatternIterStart( + self.pat, + &iter, + ); + assert(c.FcPatternIterIsValid(self.pat, &iter) == c.FcTrue); + self.iter = iter; + + // Return right away because the fontconfig iterator pattern + // is do/while. + return true; + } + + return c.FcPatternIterNext(self.pat, @ptrCast(&self.iter)) == c.FcTrue; + } + + pub fn object(self: *ObjectIterator) []const u8 { + return std.mem.sliceTo(c.FcPatternIterGetObject( + self.pat, + &self.iter.?, + ), 0); + } + + pub fn valueLen(self: *ObjectIterator) usize { + return @intCast(c.FcPatternIterValueCount(self.pat, &self.iter.?)); + } + + pub fn valueIterator(self: *ObjectIterator) ValueIterator { + return .{ + .pat = self.pat, + .iter = &self.iter.?, + .max = c.FcPatternIterValueCount(self.pat, &self.iter.?), + }; + } + }; + + pub const ValueIterator = struct { + pat: *c.struct__FcPattern, + iter: *c.struct__FcPatternIter, + max: c_int, + id: c_int = 0, + + pub const Entry = struct { + result: Result, + value: Value, + binding: ValueBinding, + }; + + pub fn next(self: *ValueIterator) ?Entry { + if (self.id >= self.max) return null; + var value: c.struct__FcValue = undefined; + var binding: c.FcValueBinding = undefined; + const result = c.FcPatternIterGetValue(self.pat, self.iter, self.id, &value, &binding); + self.id += 1; + + return Entry{ + .result = @enumFromInt(result), + .binding = @enumFromInt(binding), + .value = .init(&value), + }; + } + }; +}; + +test "create" { + const testing = std.testing; + + var pat = Pattern.create(); + defer pat.destroy(); + + try testing.expect(pat.add(.family, .{ .string = "monospace" }, false)); + try testing.expect(pat.add(.weight, .{ .integer = @intFromEnum(Weight.bold) }, false)); + + { + const val = try pat.get(.family, 0); + try testing.expect(val == .string); + try testing.expectEqualStrings("monospace", val.string); + } +} + +test "name parse" { + var pat = Pattern.parse(":monospace"); + defer pat.destroy(); + + pat.defaultSubstitute(); +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/range.zig b/vendor/libghostty-vt/pkg/fontconfig/range.zig new file mode 100644 index 00000000..9eb0ef26 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/range.zig @@ -0,0 +1,13 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; + +pub const Range = opaque { + pub fn destroy(self: *Range) void { + c.FcRangeDestroy(self.cval()); + } + + pub inline fn cval(self: *Range) *c.struct__FcRange { + return @ptrCast(self); + } +}; diff --git a/vendor/libghostty-vt/pkg/fontconfig/test.zig b/vendor/libghostty-vt/pkg/fontconfig/test.zig new file mode 100644 index 00000000..bd121c1b --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/test.zig @@ -0,0 +1,66 @@ +const std = @import("std"); +const fontconfig = @import("main.zig"); + +test "fc-list" { + const testing = std.testing; + + var cfg = fontconfig.initLoadConfigAndFonts(); + defer cfg.destroy(); + + var pat = fontconfig.Pattern.create(); + defer pat.destroy(); + + var os = fontconfig.ObjectSet.create(); + defer os.destroy(); + + var fs = cfg.fontList(pat, os); + defer fs.destroy(); + + // Note: this is environmental, but in general we expect all our + // testing environments to have at least one font. + try testing.expect(fs.fonts().len > 0); +} + +test "fc-match" { + const testing = std.testing; + + var cfg = fontconfig.initLoadConfigAndFonts(); + defer cfg.destroy(); + + var pat = fontconfig.Pattern.create(); + errdefer pat.destroy(); + try testing.expect(cfg.substituteWithPat(pat, .pattern)); + pat.defaultSubstitute(); + + const result = cfg.fontSort(pat, false, null); + errdefer result.fs.destroy(); + + var fs = fontconfig.FontSet.create(); + defer fs.destroy(); + defer for (fs.fonts()) |font| font.destroy(); + + { + const fonts = result.fs.fonts(); + try testing.expect(fonts.len > 0); + for (fonts) |font| { + const pat_prep = try cfg.fontRenderPrepare(pat, font); + try testing.expect(fs.add(pat_prep)); + } + result.fs.destroy(); + pat.destroy(); + } + + { + for (fs.fonts()) |font| { + var it = font.objectIterator(); + while (it.next()) { + try testing.expect(it.object().len > 0); + try testing.expect(it.valueLen() > 0); + var value_it = it.valueIterator(); + while (value_it.next()) |entry| { + try testing.expect(entry.value != .unknown); + } + } + } + } +} diff --git a/vendor/libghostty-vt/pkg/fontconfig/value.zig b/vendor/libghostty-vt/pkg/fontconfig/value.zig new file mode 100644 index 00000000..89f796a2 --- /dev/null +++ b/vendor/libghostty-vt/pkg/fontconfig/value.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig").c; +const CharSet = @import("main.zig").CharSet; +const LangSet = @import("main.zig").LangSet; +const Matrix = @import("main.zig").Matrix; +const Range = @import("main.zig").Range; + +pub const Type = enum(c_int) { + unknown = c.FcTypeUnknown, + void = c.FcTypeVoid, + integer = c.FcTypeInteger, + double = c.FcTypeDouble, + string = c.FcTypeString, + bool = c.FcTypeBool, + matrix = c.FcTypeMatrix, + char_set = c.FcTypeCharSet, + ft_face = c.FcTypeFTFace, + lang_set = c.FcTypeLangSet, + range = c.FcTypeRange, +}; + +pub const Value = union(Type) { + unknown: void, + void: void, + integer: i32, + double: f64, + string: [:0]const u8, + bool: bool, + matrix: *const Matrix, + char_set: *const CharSet, + ft_face: *anyopaque, + lang_set: *const LangSet, + range: *const Range, + + pub fn init(cvalue: *c.struct__FcValue) Value { + return switch (@as(Type, @enumFromInt(cvalue.type))) { + .unknown => .{ .unknown = {} }, + .void => .{ .void = {} }, + .string => .{ .string = std.mem.sliceTo(cvalue.u.s, 0) }, + .integer => .{ .integer = @intCast(cvalue.u.i) }, + .double => .{ .double = cvalue.u.d }, + .bool => .{ .bool = cvalue.u.b == c.FcTrue }, + .matrix => .{ .matrix = @ptrCast(cvalue.u.m) }, + .char_set => .{ .char_set = @ptrCast(cvalue.u.c) }, + .ft_face => .{ .ft_face = @ptrCast(cvalue.u.f) }, + .lang_set => .{ .lang_set = @ptrCast(cvalue.u.l) }, + .range => .{ .range = @ptrCast(cvalue.u.r) }, + }; + } + + pub fn cval(self: Value) c.struct__FcValue { + return .{ + .type = @intFromEnum(std.meta.activeTag(self)), + .u = switch (self) { + .unknown => undefined, + .void => undefined, + .integer => |v| .{ .i = @intCast(v) }, + .double => |v| .{ .d = v }, + .string => |v| .{ .s = v.ptr }, + .bool => |v| .{ .b = if (v) c.FcTrue else c.FcFalse }, + .matrix => |v| .{ .m = @ptrCast(v) }, + .char_set => |v| .{ .c = @ptrCast(v) }, + .ft_face => |v| .{ .f = v }, + .lang_set => |v| .{ .l = @ptrCast(v) }, + .range => |v| .{ .r = @ptrCast(v) }, + }, + }; + } +}; + +pub const ValueBinding = enum(c_int) { + weak = c.FcValueBindingWeak, + strong = c.FcValueBindingStrong, + same = c.FcValueBindingSame, +}; |
