font: test loading deferred face for fontconfig

This commit is contained in:
Mitchell Hashimoto
2022-09-24 06:24:51 -07:00
parent 88a4cb65f3
commit b11ed06fc2
3 changed files with 46 additions and 15 deletions

View File

@ -10,11 +10,10 @@ const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const fontconfig = @import("fontconfig"); const fontconfig = @import("fontconfig");
const options = @import("main.zig").options; const options = @import("main.zig").options;
const Library = @import("main.zig").Library;
const Face = @import("main.zig").Face; const Face = @import("main.zig").Face;
const Presentation = @import("main.zig").Presentation; const Presentation = @import("main.zig").Presentation;
const Library = @import("main.zig").Library;
/// The loaded face (once loaded). /// The loaded face (once loaded).
face: ?Face = null, face: ?Face = null,
@ -61,19 +60,22 @@ pub inline fn loaded(self: DeferredFace) bool {
return self.face != null; 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 // No-op if we already loaded
if (self.face != null) return; if (self.face != null) return;
if (options.fontconfig) { if (options.fontconfig) {
try self.loadFontconfig(); try self.loadFontconfig(lib);
return; return;
} }
// Unreachable because we must be already loaded or have the
// proper configuration for one of the other deferred mechanisms.
unreachable; unreachable;
} }
fn loadFontconfig(self: *DeferredFace) !void { fn loadFontconfig(self: *DeferredFace, lib: Library) !void {
assert(self.face == null); assert(self.face == null);
const fc = self.fc.?; const fc = self.fc.?;
@ -81,7 +83,7 @@ fn loadFontconfig(self: *DeferredFace) !void {
const filename = (try fc.pattern.get(.file, 0)).string; const filename = (try fc.pattern.get(.file, 0)).string;
const face_index = (try fc.pattern.get(.index, 0)).integer; 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, .points = fc.req_size,
}); });
} }
@ -127,7 +129,7 @@ pub fn hasCodepoint(self: DeferredFace, cp: u32, p: ?Presentation) bool {
unreachable; unreachable;
} }
test { test "preloaded" {
const testing = std.testing; const testing = std.testing;
const testFont = @import("test.zig").fontRegular; const testFont = @import("test.zig").fontRegular;
@ -142,3 +144,29 @@ test {
try testing.expect(def.hasCodepoint(' ', null)); 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);
}

View File

@ -1,16 +1,17 @@
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const fontconfig = @import("fontconfig"); const fontconfig = @import("fontconfig");
const options = @import("main.zig").options;
const DeferredFace = @import("main.zig").DeferredFace; const DeferredFace = @import("main.zig").DeferredFace;
const log = std.log.named(.discovery); const log = std.log.named(.discovery);
pub const Error = error{ /// Discover implementation for the compile options.
FontConfigFailed, pub const Discover = if (options.fontconfig) Fontconfig else void;
};
/// Descriptor is used to search for fonts. The only required field /// 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 { pub const Descriptor = struct {
/// Font family to search for. This can be a fully qualified font /// Font family to search for. This can be a fully qualified font
/// name such as "Fira Code", "monospace", "serif", etc. Memory is /// name such as "Fira Code", "monospace", "serif", etc. Memory is
@ -74,7 +75,7 @@ pub const Fontconfig = struct {
// Search // Search
const res = self.fc_config.fontSort(pat, true, null); 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(); errdefer res.fs.destroy();
return DiscoverIterator{ return DiscoverIterator{
@ -129,6 +130,8 @@ pub const Fontconfig = struct {
}; };
test { test {
if (!options.fontconfig) return error.SkipZigTest;
const testing = std.testing; const testing = std.testing;
var fc = Fontconfig.init(); var fc = Fontconfig.init();

View File

@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const build_options = @import("build_options"); const build_options = @import("build_options");
pub const discovery = @import("discovery.zig");
pub const DeferredFace = @import("DeferredFace.zig"); pub const DeferredFace = @import("DeferredFace.zig");
pub const Face = @import("Face.zig"); pub const Face = @import("Face.zig");
pub const Group = @import("Group.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 Glyph = @import("Glyph.zig");
pub const Library = @import("Library.zig"); pub const Library = @import("Library.zig");
pub const Shaper = @import("Shaper.zig"); pub const Shaper = @import("Shaper.zig");
pub const Descriptor = discovery.Descriptor;
pub const Discover = discovery.Discover;
/// Build options /// Build options
pub const options: struct { pub const options: struct {
@ -42,7 +45,4 @@ pub const Metrics = struct {
test { test {
@import("std").testing.refAllDecls(@This()); @import("std").testing.refAllDecls(@This());
// TODO
if (options.fontconfig) _ = @import("discovery.zig");
} }