mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
search for unknown codepoints in any available font face
If an unknown codepoint is rendered, we now will query the OS for ANY font that can satisfy the codepoint (rather than rendering `?`).
This commit is contained in:
@ -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(.{
|
||||
|
@ -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 "<error>",
|
||||
});
|
||||
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
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user