feat(gui): implement get_fontfaces
This commit is contained in:
parent
6faea2ef02
commit
4ca31b0f75
6 changed files with 95 additions and 2 deletions
|
|
@ -606,6 +606,7 @@ pub fn build_exe(
|
|||
.{ .name = "app", .module = app_mod },
|
||||
.{ .name = "tuirenderer", .module = tui_renderer_mod },
|
||||
.{ .name = "vaxis", .module = vaxis_mod },
|
||||
.{ .name = "rasterizer", .module = truetype_rasterizer_mod },
|
||||
},
|
||||
});
|
||||
break :blk mod;
|
||||
|
|
|
|||
|
|
@ -7,3 +7,12 @@ pub fn findFont(allocator: std.mem.Allocator, name: []const u8) ![]u8 {
|
|||
else => error.FontFinderNotSupported,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns a sorted, deduplicated list of monospace font family names.
|
||||
/// Caller owns the returned slice and each string within it.
|
||||
pub fn listFonts(allocator: std.mem.Allocator) ![][]u8 {
|
||||
return switch (builtin.os.tag) {
|
||||
.linux => @import("font_finder/linux.zig").list(allocator),
|
||||
else => error.FontFinderNotSupported,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,56 @@ const fc = @cImport({
|
|||
@cInclude("fontconfig/fontconfig.h");
|
||||
});
|
||||
|
||||
/// Returns a sorted, deduplicated list of monospace font family names.
|
||||
/// Caller owns the returned slice and each string within it.
|
||||
pub fn list(allocator: std.mem.Allocator) ![][]u8 {
|
||||
const config = fc.FcInitLoadConfigAndFonts() orelse return error.FontconfigInit;
|
||||
defer fc.FcConfigDestroy(config);
|
||||
|
||||
const pat = fc.FcPatternCreate() orelse return error.OutOfMemory;
|
||||
defer fc.FcPatternDestroy(pat);
|
||||
_ = fc.FcPatternAddInteger(pat, fc.FC_SPACING, fc.FC_MONO);
|
||||
|
||||
const os = fc.FcObjectSetCreate() orelse return error.OutOfMemory;
|
||||
defer fc.FcObjectSetDestroy(os);
|
||||
_ = fc.FcObjectSetAdd(os, fc.FC_FAMILY);
|
||||
|
||||
const font_set = fc.FcFontList(config, pat, os) orelse return error.OutOfMemory;
|
||||
defer fc.FcFontSetDestroy(font_set);
|
||||
|
||||
var names: std.ArrayList([]u8) = .empty;
|
||||
errdefer {
|
||||
for (names.items) |n| allocator.free(n);
|
||||
names.deinit(allocator);
|
||||
}
|
||||
|
||||
for (0..@intCast(font_set.*.nfont)) |i| {
|
||||
var family: [*c]fc.FcChar8 = undefined;
|
||||
if (fc.FcPatternGetString(font_set.*.fonts[i], fc.FC_FAMILY, 0, &family) != fc.FcResultMatch)
|
||||
continue;
|
||||
try names.append(allocator, try allocator.dupe(u8, std.mem.sliceTo(family, 0)));
|
||||
}
|
||||
|
||||
const result = try names.toOwnedSlice(allocator);
|
||||
std.mem.sort([]u8, result, {}, struct {
|
||||
fn lessThan(_: void, a: []u8, b: []u8) bool {
|
||||
return std.ascii.lessThanIgnoreCase(a, b);
|
||||
}
|
||||
}.lessThan);
|
||||
|
||||
// Remove adjacent duplicates that survived the sort.
|
||||
var w: usize = 0;
|
||||
for (result) |name| {
|
||||
if (w == 0 or !std.ascii.eqlIgnoreCase(result[w - 1], name)) {
|
||||
result[w] = name;
|
||||
w += 1;
|
||||
} else {
|
||||
allocator.free(name);
|
||||
}
|
||||
}
|
||||
return result[0..w];
|
||||
}
|
||||
|
||||
pub fn find(allocator: std.mem.Allocator, name: []const u8) ![]u8 {
|
||||
const config = fc.FcInitLoadConfigAndFonts() orelse return error.FontconfigInit;
|
||||
defer fc.FcConfigDestroy(config);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const std = @import("std");
|
||||
const TrueType = @import("TrueType");
|
||||
const XY = @import("xy").XY;
|
||||
const font_finder = @import("font_finder.zig");
|
||||
pub const font_finder = @import("font_finder.zig");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,10 @@ pub fn setMouseCursor(shape: vaxis.Mouse.Shape) void {
|
|||
wio.cancelWait();
|
||||
}
|
||||
|
||||
pub fn getFontName() []const u8 {
|
||||
return if (font_name_len > 0) font_name_buf[0..font_name_len] else "monospace";
|
||||
}
|
||||
|
||||
pub fn requestAttention() void {
|
||||
attention_pending.store(true, .release);
|
||||
wio.cancelWait();
|
||||
|
|
|
|||
|
|
@ -381,7 +381,36 @@ pub fn reset_fontface(self: *Self) void {
|
|||
}
|
||||
|
||||
pub fn get_fontfaces(self: *Self) void {
|
||||
_ = self;
|
||||
const font_finder = @import("rasterizer").font_finder;
|
||||
const dispatch = self.dispatch_event orelse return;
|
||||
|
||||
// Report the current font first.
|
||||
if (self.fmtmsg(.{ "fontface", "current", app.getFontName() })) |msg|
|
||||
dispatch(self.handler_ctx, msg)
|
||||
else |_| {}
|
||||
|
||||
// Enumerate all available monospace fonts and report each one.
|
||||
const names = font_finder.listFonts(self.allocator) catch {
|
||||
// If enumeration fails, still close the palette with "done".
|
||||
if (self.fmtmsg(.{ "fontface", "done" })) |msg|
|
||||
dispatch(self.handler_ctx, msg)
|
||||
else |_| {}
|
||||
return;
|
||||
};
|
||||
defer {
|
||||
for (names) |n| self.allocator.free(n);
|
||||
self.allocator.free(names);
|
||||
}
|
||||
|
||||
for (names) |name| {
|
||||
if (self.fmtmsg(.{ "fontface", name })) |msg|
|
||||
dispatch(self.handler_ctx, msg)
|
||||
else |_| {}
|
||||
}
|
||||
|
||||
if (self.fmtmsg(.{ "fontface", "done" })) |msg|
|
||||
dispatch(self.handler_ctx, msg)
|
||||
else |_| {}
|
||||
}
|
||||
|
||||
pub fn set_terminal_cursor_color(self: *Self, color: Color) void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue