aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/pkg/fontconfig/pattern.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/fontconfig/pattern.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/fontconfig/pattern.zig')
-rw-r--r--vendor/libghostty-vt/pkg/fontconfig/pattern.zig168
1 files changed, 168 insertions, 0 deletions
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();
+}