diff --git a/src/font/DeferredFace.zig b/src/font/DeferredFace.zig index 0a3f974ff..dc3c46d50 100644 --- a/src/font/DeferredFace.zig +++ b/src/font/DeferredFace.zig @@ -11,6 +11,7 @@ const assert = std.debug.assert; const fontconfig = @import("fontconfig"); const options = @import("main.zig").options; const Face = @import("main.zig").Face; +const Presentation = @import("main.zig").Presentation; /// The loaded face (once loaded). face: ?Face = null, @@ -35,3 +36,42 @@ pub fn deinit(self: *DeferredFace) void { pub inline fn loaded(self: DeferredFace) bool { return self.face != null; } + +/// Returns true if this face can satisfy the given codepoint and +/// presentation. If presentation is null, then it just checks if the +/// codepoint is present at all. +/// +/// This should not require the face to be loaded IF we're using a +/// discovery mechanism (i.e. fontconfig). If no discovery is used, +/// the face is always expected to be loaded. +pub fn hasCodepoint(self: DeferredFace, cp: u32, p: ?Presentation) bool { + // If we have the face, use the face. + if (self.face) |face| { + if (p) |desired| if (face.presentation != desired) return false; + return face.glyphIndex(cp) != null; + } + + // If we are using fontconfig, use the fontconfig metadata to + // avoid loading the face. + if (options.fontconfig) { + // Check if char exists + if (!self.fc.charset.hasChar(cp)) return false; + + // If we have a presentation, check it matches + if (p) |desired| { + const emoji_lang = "und-zsye"; + const actual: Presentation = if (self.fc.langset.hasLang(emoji_lang)) + .emoji + else + .text; + + return desired == actual; + } + + return true; + } + + // This is unreachable because discovery mechanisms terminate, and + // if we're not using a discovery mechanism, the face MUST be loaded. + unreachable; +} diff --git a/src/font/Group.zig b/src/font/Group.zig index 80d6e72e0..27ef4545d 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -112,13 +112,7 @@ pub fn indexForCodepoint( fn indexForCodepointExact(self: Group, cp: u32, style: Style, p: ?Presentation) ?FontIndex { for (self.faces.get(style).items) |deferred, i| { - const face = deferred.face.?; - - // If the presentation is null, we allow the first presentation we - // can find. Otherwise, we check for the specific one requested. - if (p != null and face.presentation != p.?) continue; - - if (face.glyphIndex(cp) != null) { + if (deferred.hasCodepoint(cp, p)) { return FontIndex{ .style = style, .idx = @intCast(FontIndex.IndexInt, i),