Merge pull request #275 from mitchellh/fc-init-once

only initialize font discovery mechanism once, cache on App
This commit is contained in:
Mitchell Hashimoto
2023-08-13 08:19:13 -07:00
committed by GitHub
6 changed files with 52 additions and 18 deletions

View File

@ -45,6 +45,11 @@ quit: bool,
/// from source. This is null if we can't detect it.
resources_dir: ?[]const u8 = null,
/// Font discovery mechanism. This is only safe to use from the main thread.
/// This is lazily initialized on the first call to fontDiscover so do
/// not access this directly.
font_discover: ?font.Discover = null,
/// Initialize the main app instance. This creates the main window, sets
/// up the renderer state, compiles the shaders, etc. This is the primary
/// "startup" logic.
@ -80,6 +85,8 @@ pub fn destroy(self: *App) void {
self.surfaces.deinit(self.alloc);
if (self.resources_dir) |dir| self.alloc.free(dir);
if (self.font_discover) |*v| v.deinit();
self.alloc.destroy(self);
}
@ -151,6 +158,20 @@ pub fn focusedSurface(self: *const App) ?*Surface {
return surface;
}
/// Initialize once and return the font discovery mechanism. This remains
/// initialized throughout the lifetime of the application because some
/// font discovery mechanisms (i.e. fontconfig) are unsafe to reinit.
pub fn fontDiscover(self: *App) !?font.Discover {
// If we're built without a font discovery mechanism, return null
if (comptime font.Discover == void) return null;
// If we initialized, use it
if (self.font_discover) |v| return v;
self.font_discover = font.Discover.init();
return self.font_discover.?;
}
/// Drain the mailbox.
fn drainMailbox(self: *App, rt_app: *apprt.App) !void {
while (self.mailbox.pop()) |message| {

View File

@ -177,8 +177,8 @@ pub fn init(
self: *Surface,
alloc: Allocator,
config: *const configpkg.Config,
app: *App,
app_mailbox: App.Mailbox,
app_resources_dir: ?[]const u8,
rt_surface: *apprt.runtime.Surface,
) !void {
// Initialize our renderer with our initialized surface.
@ -217,8 +217,11 @@ pub fn init(
errdefer group.deinit();
// Search for fonts
if (font.Discover != void) {
var disco = font.Discover.init();
if (font.Discover != void) discover: {
const disco = try app.fontDiscover() orelse {
log.warn("font discovery not available, cannot search for fonts", .{});
break :discover;
};
group.discover = disco;
if (config.@"font-family") |family| {
@ -320,8 +323,7 @@ pub fn init(
// If we're on Mac, then we try to use the Apple Emoji font for Emoji.
if (builtin.os.tag == .macos and font.Discover != void) {
var disco = font.Discover.init();
defer disco.deinit();
if (try app.fontDiscover()) |disco| {
var disco_it = try disco.discover(.{
.family = "Apple Color Emoji",
.size = font_size.points,
@ -332,6 +334,7 @@ pub fn init(
try group.addFace(alloc, .regular, face);
}
}
}
break :group group;
});
@ -402,7 +405,7 @@ pub fn init(
.screen_size = screen_size,
.full_config = config,
.config = try termio.Impl.DerivedConfig.init(alloc, config),
.resources_dir = app_resources_dir,
.resources_dir = app.resources_dir,
.renderer_state = &self.renderer_state,
.renderer_wakeup = render_thread.wakeup,
.renderer_mailbox = render_thread.mailbox,

View File

@ -196,8 +196,8 @@ pub const Surface = struct {
try self.core_surface.init(
app.core_app.alloc,
&config,
app.core_app,
.{ .rt_app = app, .mailbox = &app.core_app.mailbox },
app.core_app.resources_dir,
self,
);
errdefer self.core_surface.deinit();

View File

@ -374,8 +374,8 @@ pub const Surface = struct {
try self.core_surface.init(
app.app.alloc,
&config,
app.app,
.{ .rt_app = app, .mailbox = &app.app.mailbox },
app.app.resources_dir,
self,
);
errdefer self.core_surface.deinit();

View File

@ -789,8 +789,8 @@ pub const Surface = struct {
try self.core_surface.init(
self.app.core_app.alloc,
&config,
self.app.core_app,
.{ .rt_app = self.app, .mailbox = &self.app.core_app.mailbox },
self.app.core_app.resources_dir,
self,
);
errdefer self.core_surface.deinit();
@ -1203,6 +1203,14 @@ pub const Surface = struct {
break :key input.Key.fromASCII(self.im_buf[0]) orelse physical_key;
} else .invalid;
// log.debug("key pressed key={} physical_key={} composing={} text_len={} mods={}", .{
// key,
// physical_key,
// self.im_composing,
// self.im_len,
// mods,
// });
// If both keys are invalid then we won't call the key callback. But
// if either one is valid, we want to give it a chance.
if (key != .invalid or physical_key != .invalid) {
@ -1342,6 +1350,8 @@ pub const Surface = struct {
if (str.len <= self.im_buf.len) {
@memcpy(self.im_buf[0..str.len], str);
self.im_len = @intCast(str.len);
// log.debug("input commit: {x}", .{self.im_buf[0]});
} else {
log.warn("not enough buffer space for input method commit", .{});
}

View File

@ -168,7 +168,7 @@ pub const Fontconfig = struct {
/// Discover fonts from a descriptor. This returns an iterator that can
/// be used to build up the deferred fonts.
pub fn discover(self: *Fontconfig, desc: Descriptor) !DiscoverIterator {
pub fn discover(self: *const Fontconfig, desc: Descriptor) !DiscoverIterator {
// Build our pattern that we'll search for
const pat = desc.toFcPattern();
errdefer pat.destroy();