font: respect cell width attributes in nerd font constraints

This mostly applies to powerline glyphs, but is also relevant for heavy
bracket characters, which need to always be 1 wide otherwise they look
silly because they misalign depending on if there's a space after them
or not.
This commit is contained in:
Qwerasd
2025-07-06 11:23:49 -06:00
parent 8f989f6bfd
commit c7e65b0c1c
5 changed files with 49 additions and 9 deletions

View File

@ -147,6 +147,9 @@ pub const RenderOptions = struct {
/// Maximum ratio of width to height when resizing. /// Maximum ratio of width to height when resizing.
max_xy_ratio: ?f64 = null, max_xy_ratio: ?f64 = null,
/// Maximum number of cells horizontally to use.
max_constraint_width: u2 = 2,
pub const Size = enum { pub const Size = enum {
/// Don't change the size of this glyph. /// Don't change the size of this glyph.
none, none,
@ -186,16 +189,26 @@ pub const RenderOptions = struct {
pub fn constrain( pub fn constrain(
self: Constraint, self: Constraint,
glyph: GlyphSize, glyph: GlyphSize,
/// Available width /// Width of one cell.
cell_width: f64, cell_width: f64,
/// Available height /// Height of one cell.
cell_height: f64, cell_height: f64,
/// Number of cells horizontally available for this glyph.
constraint_width: u2,
) GlyphSize { ) GlyphSize {
var g = glyph; var g = glyph;
const w = cell_width - const available_width =
self.pad_left * cell_width - cell_width * @as(f64, @floatFromInt(
self.pad_right * cell_width; @min(
self.max_constraint_width,
constraint_width,
),
));
const w = available_width -
self.pad_left * available_width -
self.pad_right * available_width;
const h = cell_height - const h = cell_height -
self.pad_top * cell_height - self.pad_top * cell_height -
self.pad_bottom * cell_height; self.pad_bottom * cell_height;
@ -203,7 +216,7 @@ pub const RenderOptions = struct {
// Subtract padding from the bearings so that our // Subtract padding from the bearings so that our
// alignment and sizing code works correctly. We // alignment and sizing code works correctly. We
// re-add before returning. // re-add before returning.
g.x -= self.pad_left * cell_width; g.x -= self.pad_left * available_width;
g.y -= self.pad_bottom * cell_height; g.y -= self.pad_bottom * cell_height;
switch (self.size_horizontal) { switch (self.size_horizontal) {
@ -305,7 +318,7 @@ pub const RenderOptions = struct {
} }
// Re-add our padding before returning. // Re-add our padding before returning.
g.x += self.pad_left * cell_width; g.x += self.pad_left * available_width;
g.y += self.pad_bottom * cell_height; g.y += self.pad_bottom * cell_height;
return g; return g;

View File

@ -337,7 +337,7 @@ pub const Face = struct {
}; };
const metrics = opts.grid_metrics; const metrics = opts.grid_metrics;
const cell_width: f64 = @floatFromInt(metrics.cell_width * opts.constraint_width); const cell_width: f64 = @floatFromInt(metrics.cell_width);
const cell_height: f64 = @floatFromInt(metrics.cell_height); const cell_height: f64 = @floatFromInt(metrics.cell_height);
const glyph_size = opts.constraint.constrain( const glyph_size = opts.constraint.constrain(
@ -349,6 +349,7 @@ pub const Face = struct {
}, },
cell_width, cell_width,
cell_height, cell_height,
opts.constraint_width,
); );
const width = glyph_size.width; const width = glyph_size.width;

View File

@ -390,7 +390,7 @@ pub const Face = struct {
// Next we need to apply any constraints. // Next we need to apply any constraints.
const metrics = opts.grid_metrics; const metrics = opts.grid_metrics;
const cell_width: f64 = @floatFromInt(metrics.cell_width * opts.constraint_width); const cell_width: f64 = @floatFromInt(metrics.cell_width);
const cell_height: f64 = @floatFromInt(metrics.cell_height); const cell_height: f64 = @floatFromInt(metrics.cell_height);
const glyph_x: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingX); const glyph_x: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingX);
@ -405,6 +405,7 @@ pub const Face = struct {
}, },
cell_width, cell_width,
cell_height, cell_height,
opts.constraint_width,
); );
const width = glyph_size.width; const width = glyph_size.width;

View File

@ -13,6 +13,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.02, .pad_left = -0.02,
@ -24,6 +25,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .fit, .size_vertical = .fit,
.max_constraint_width = 1,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
.pad_left = 0.1, .pad_left = 0.1,
@ -35,6 +37,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .fit, .size_vertical = .fit,
.max_constraint_width = 1,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
.pad_top = 0.3, .pad_top = 0.3,
@ -44,6 +47,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.06, .pad_left = -0.06,
@ -56,6 +60,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.max_xy_ratio = 0.7, .max_xy_ratio = 0.7,
@ -64,6 +69,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.06, .pad_left = -0.06,
@ -76,6 +82,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.max_xy_ratio = 0.7, .max_xy_ratio = 0.7,
@ -84,6 +91,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.06, .pad_left = -0.06,
@ -96,6 +104,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.max_xy_ratio = 0.5, .max_xy_ratio = 0.5,
@ -104,6 +113,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.06, .pad_left = -0.06,
@ -116,6 +126,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.max_xy_ratio = 0.5, .max_xy_ratio = 0.5,
@ -125,6 +136,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.05, .pad_left = -0.05,
@ -137,6 +149,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
}, },
@ -145,6 +158,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.05, .pad_left = -0.05,
@ -157,6 +171,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
}, },
@ -287,6 +302,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.02, .pad_left = -0.02,
@ -299,6 +315,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.02, .pad_left = -0.02,
@ -311,6 +328,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.05, .pad_left = -0.05,
@ -323,6 +341,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .stretch, .size_horizontal = .stretch,
.size_vertical = .stretch, .size_vertical = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end, .align_horizontal = .end,
.align_vertical = .center, .align_vertical = .center,
.pad_left = -0.05, .pad_left = -0.05,

View File

@ -190,6 +190,12 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
s += " .size_horizontal = .fit,\n" s += " .size_horizontal = .fit,\n"
s += " .size_vertical = .fit,\n" s += " .size_vertical = .fit,\n"
# There are two cases where we want to limit the constraint width to 1:
# - If there's a `1` in the stretch mode string.
# - If the stretch mode is `xy` and there's not an explicit `2`.
if "1" in stretch or ("xy" in stretch and "2" not in stretch):
s += " .max_constraint_width = 1,\n"
if align is not None: if align is not None:
s += f" .align_horizontal = {align},\n" s += f" .align_horizontal = {align},\n"
if valign is not None: if valign is not None: