diff --git a/src/Window.zig b/src/Window.zig index c4ec2a012..748d75148 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -175,12 +175,12 @@ pub fn create(alloc: Allocator, app: *App, config: *const Config) !*Window { errdefer alloc.destroy(font_group); font_group.* = try font.GroupCache.init(alloc, group: { var group = try font.Group.init(alloc, font_lib, font_size); - errdefer group.deinit(alloc); + errdefer group.deinit(); // Search for fonts if (font.Discover != void) { var disco = font.Discover.init(); - defer disco.deinit(); + group.discover = disco; if (config.@"font-family") |family| { var disco_it = try disco.discover(.{ diff --git a/src/font/Group.zig b/src/font/Group.zig index b7173fc61..1d1f168fc 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -29,6 +29,9 @@ const log = std.log.scoped(.font_group); // to the user so we can change this later. const StyleArray = std.EnumArray(Style, std.ArrayListUnmanaged(DeferredFace)); +/// The allocator for this group +alloc: Allocator, + /// The library being used for all the faces. lib: Library, @@ -39,12 +42,16 @@ size: font.face.DesiredSize, /// Instead, use the functions available on Group. faces: StyleArray, +/// If discovery is available, we'll look up fonts where we can't find +/// the codepoint. +discover: ?font.Discover = null, + pub fn init( alloc: Allocator, lib: Library, size: font.face.DesiredSize, ) !Group { - var result = Group{ .lib = lib, .size = size, .faces = undefined }; + var result = Group{ .alloc = alloc, .lib = lib, .size = size, .faces = undefined }; // Initialize all our styles to initially sized lists. var i: usize = 0; @@ -56,11 +63,15 @@ pub fn init( return result; } -pub fn deinit(self: *Group, alloc: Allocator) void { +pub fn deinit(self: *Group) void { var it = self.faces.iterator(); while (it.next()) |entry| { for (entry.value.items) |*item| item.deinit(); - entry.value.deinit(alloc); + entry.value.deinit(self.alloc); + } + + if (font.Discover != void) { + if (self.discover) |*discover| discover.deinit(); } } @@ -126,7 +137,7 @@ pub const FontIndex = packed struct { /// is allowed. This func will NOT determine the default presentation for /// a code point. pub fn indexForCodepoint( - self: Group, + self: *Group, cp: u32, style: Style, p: ?Presentation, @@ -134,6 +145,28 @@ pub fn indexForCodepoint( // If we can find the exact value, then return that. if (self.indexForCodepointExact(cp, style, p)) |value| return value; + // Try looking for another font that will satisfy this request. + if (font.Discover != void) { + if (self.discover) |*disco| discover: { + var disco_it = disco.discover(.{ + .codepoint = cp, + .size = self.size.points, + .bold = style == .bold or style == .bold_italic, + .italic = style == .italic or style == .bold_italic, + }) catch break :discover; + defer disco_it.deinit(); + + if (disco_it.next() catch break :discover) |face| { + log.info("found codepoint 0x{x} in fallback face={s}", .{ + cp, + face.name() catch "", + }); + self.addFace(self.alloc, style, face) catch break :discover; + if (self.indexForCodepointExact(cp, style, p)) |value| return value; + } + } + } + // If this is already regular, we're done falling back. if (style == .regular and p == null) return null; @@ -200,7 +233,7 @@ test { defer lib.deinit(); var group = try init(alloc, lib, .{ .points = 12 }); - defer group.deinit(alloc); + defer group.deinit(); try group.addFace(alloc, .regular, DeferredFace.initLoaded(try Face.init(lib, testFont, .{ .points = 12 }))); try group.addFace(alloc, .regular, DeferredFace.initLoaded(try Face.init(lib, testEmoji, .{ .points = 12 }))); @@ -257,7 +290,7 @@ test "resize" { defer lib.deinit(); var group = try init(alloc, lib, .{ .points = 12, .xdpi = 96, .ydpi = 96 }); - defer group.deinit(alloc); + defer group.deinit(); try group.addFace(alloc, .regular, DeferredFace.initLoaded(try Face.init(lib, testFont, .{ .points = 12, .xdpi = 96, .ydpi = 96 }))); @@ -311,7 +344,7 @@ test "discover monospace with fontconfig and freetype" { var lib = try Library.init(); defer lib.deinit(); var group = try init(alloc, lib, .{ .points = 12 }); - defer group.deinit(alloc); + defer group.deinit(); try group.addFace(alloc, .regular, (try it.next()).?); // Should find all visible ASCII diff --git a/src/font/GroupCache.zig b/src/font/GroupCache.zig index 44e7d8337..4ed68f6dc 100644 --- a/src/font/GroupCache.zig +++ b/src/font/GroupCache.zig @@ -70,7 +70,7 @@ pub fn deinit(self: *GroupCache, alloc: Allocator) void { self.glyphs.deinit(alloc); self.atlas_greyscale.deinit(alloc); self.atlas_color.deinit(alloc); - self.group.deinit(alloc); + self.group.deinit(); } /// Reset the cache. This should be called: