Something went wrong. Try again.
Something went wrong. Try again.
5.1 kB · 168 lines
Zig
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169const 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();}