From b11ed06fc27986257211c59883e9e6c6602cdcf8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 24 Sep 2022 06:24:51 -0700 Subject: [PATCH] font: test loading deferred face for fontconfig --- src/font/DeferredFace.zig | 42 ++++++++++++++++++++++++++++++++------- src/font/discovery.zig | 13 +++++++----- src/font/main.zig | 6 +++--- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/font/DeferredFace.zig b/src/font/DeferredFace.zig index 7c82cb5de..4693ed5bc 100644 --- a/src/font/DeferredFace.zig +++ b/src/font/DeferredFace.zig @@ -10,11 +10,10 @@ const std = @import("std"); const assert = std.debug.assert; const fontconfig = @import("fontconfig"); const options = @import("main.zig").options; +const Library = @import("main.zig").Library; const Face = @import("main.zig").Face; const Presentation = @import("main.zig").Presentation; -const Library = @import("main.zig").Library; - /// The loaded face (once loaded). face: ?Face = null, @@ -61,19 +60,22 @@ pub inline fn loaded(self: DeferredFace) bool { return self.face != null; } -pub fn load(self: *DeferredFace) !void { +/// Load the deferred font face. This does nothing if the face is loaded. +pub fn load(self: *DeferredFace, lib: Library) !void { // No-op if we already loaded if (self.face != null) return; if (options.fontconfig) { - try self.loadFontconfig(); + try self.loadFontconfig(lib); return; } + // Unreachable because we must be already loaded or have the + // proper configuration for one of the other deferred mechanisms. unreachable; } -fn loadFontconfig(self: *DeferredFace) !void { +fn loadFontconfig(self: *DeferredFace, lib: Library) !void { assert(self.face == null); const fc = self.fc.?; @@ -81,7 +83,7 @@ fn loadFontconfig(self: *DeferredFace) !void { const filename = (try fc.pattern.get(.file, 0)).string; const face_index = (try fc.pattern.get(.index, 0)).integer; - self.face = try Face.initFile(filename, face_index, .{ + self.face = try Face.initFile(lib, filename, face_index, .{ .points = fc.req_size, }); } @@ -127,7 +129,7 @@ pub fn hasCodepoint(self: DeferredFace, cp: u32, p: ?Presentation) bool { unreachable; } -test { +test "preloaded" { const testing = std.testing; const testFont = @import("test.zig").fontRegular; @@ -142,3 +144,29 @@ test { try testing.expect(def.hasCodepoint(' ', null)); } + +test "fontconfig" { + if (!options.fontconfig) return error.SkipZigTest; + + const discovery = @import("main.zig").discovery; + const testing = std.testing; + + // Load freetype + var lib = try Library.init(); + defer lib.deinit(); + + // Get a deferred face from fontconfig + var def = def: { + var fc = discovery.Fontconfig.init(); + var it = try fc.discover(.{ .family = "monospace", .size = 12 }); + defer it.deinit(); + break :def (try it.next()).?; + }; + defer def.deinit(); + try testing.expect(!def.loaded()); + + // Load it and verify it works + try def.load(lib); + try testing.expect(def.hasCodepoint(' ', null)); + try testing.expect(def.face.?.glyphIndex(' ') != null); +} diff --git a/src/font/discovery.zig b/src/font/discovery.zig index dcdb818f6..b5f725a42 100644 --- a/src/font/discovery.zig +++ b/src/font/discovery.zig @@ -1,16 +1,17 @@ const std = @import("std"); const assert = std.debug.assert; const fontconfig = @import("fontconfig"); +const options = @import("main.zig").options; const DeferredFace = @import("main.zig").DeferredFace; const log = std.log.named(.discovery); -pub const Error = error{ - FontConfigFailed, -}; +/// Discover implementation for the compile options. +pub const Discover = if (options.fontconfig) Fontconfig else void; /// Descriptor is used to search for fonts. The only required field -/// is "family". The rest are ignored unless they're set to a non-zero value. +/// is "family". The rest are ignored unless they're set to a non-zero +/// value. pub const Descriptor = struct { /// Font family to search for. This can be a fully qualified font /// name such as "Fira Code", "monospace", "serif", etc. Memory is @@ -74,7 +75,7 @@ pub const Fontconfig = struct { // Search const res = self.fc_config.fontSort(pat, true, null); - if (res.result != .match) return Error.FontConfigFailed; + if (res.result != .match) return error.FontConfigFailed; errdefer res.fs.destroy(); return DiscoverIterator{ @@ -129,6 +130,8 @@ pub const Fontconfig = struct { }; test { + if (!options.fontconfig) return error.SkipZigTest; + const testing = std.testing; var fc = Fontconfig.init(); diff --git a/src/font/main.zig b/src/font/main.zig index bdb6060da..eaa947dfa 100644 --- a/src/font/main.zig +++ b/src/font/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const build_options = @import("build_options"); +pub const discovery = @import("discovery.zig"); pub const DeferredFace = @import("DeferredFace.zig"); pub const Face = @import("Face.zig"); pub const Group = @import("Group.zig"); @@ -8,6 +9,8 @@ pub const GroupCache = @import("GroupCache.zig"); pub const Glyph = @import("Glyph.zig"); pub const Library = @import("Library.zig"); pub const Shaper = @import("Shaper.zig"); +pub const Descriptor = discovery.Descriptor; +pub const Discover = discovery.Discover; /// Build options pub const options: struct { @@ -42,7 +45,4 @@ pub const Metrics = struct { test { @import("std").testing.refAllDecls(@This()); - - // TODO - if (options.fontconfig) _ = @import("discovery.zig"); }