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 = "app", .module = app_mod },
|
||||||
.{ .name = "tuirenderer", .module = tui_renderer_mod },
|
.{ .name = "tuirenderer", .module = tui_renderer_mod },
|
||||||
.{ .name = "vaxis", .module = vaxis_mod },
|
.{ .name = "vaxis", .module = vaxis_mod },
|
||||||
|
.{ .name = "rasterizer", .module = truetype_rasterizer_mod },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
break :blk mod;
|
break :blk mod;
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,12 @@ pub fn findFont(allocator: std.mem.Allocator, name: []const u8) ![]u8 {
|
||||||
else => error.FontFinderNotSupported,
|
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");
|
@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 {
|
pub fn find(allocator: std.mem.Allocator, name: []const u8) ![]u8 {
|
||||||
const config = fc.FcInitLoadConfigAndFonts() orelse return error.FontconfigInit;
|
const config = fc.FcInitLoadConfigAndFonts() orelse return error.FontconfigInit;
|
||||||
defer fc.FcConfigDestroy(config);
|
defer fc.FcConfigDestroy(config);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const TrueType = @import("TrueType");
|
const TrueType = @import("TrueType");
|
||||||
const XY = @import("xy").XY;
|
const XY = @import("xy").XY;
|
||||||
const font_finder = @import("font_finder.zig");
|
pub const font_finder = @import("font_finder.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,10 @@ pub fn setMouseCursor(shape: vaxis.Mouse.Shape) void {
|
||||||
wio.cancelWait();
|
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 {
|
pub fn requestAttention() void {
|
||||||
attention_pending.store(true, .release);
|
attention_pending.store(true, .release);
|
||||||
wio.cancelWait();
|
wio.cancelWait();
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,36 @@ pub fn reset_fontface(self: *Self) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_fontfaces(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 {
|
pub fn set_terminal_cursor_color(self: *Self, color: Color) void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue