renderer: apply glyph constraints when rasterizing glyphs

This commit is contained in:
Qwerasd
2025-07-03 16:04:04 -06:00
parent 1775b75f2c
commit 95c8747ab5
2 changed files with 60 additions and 0 deletions

View File

@ -223,6 +223,60 @@ pub const FgMode = enum {
powerline,
};
/// Returns the appropriate `constraint_width` for
/// the provided cell when rendering its glyph(s).
pub fn constraintWidth(cell_pin: terminal.Pin) u2 {
const cell = cell_pin.rowAndCell().cell;
const cp = cell.codepoint();
if (!ziglyph.general_category.isPrivateUse(cp) and
!ziglyph.blocks.isDingbats(cp))
{
return cell.gridWidth();
}
// If we are at the end of the screen it must be constrained to one cell.
if (cell_pin.x == cell_pin.node.data.size.cols - 1) return 1;
// If we have a previous cell and it was PUA then we need to
// also constrain. This is so that multiple PUA glyphs align.
// As an exception, we ignore powerline glyphs since they are
// used for box drawing and we consider them whitespace.
if (cell_pin.x > 0) prev: {
const prev_cp = prev_cp: {
var copy = cell_pin;
copy.x -= 1;
const prev_cell = copy.rowAndCell().cell;
break :prev_cp prev_cell.codepoint();
};
// We consider powerline glyphs whitespace.
if (isPowerline(prev_cp)) break :prev;
if (ziglyph.general_category.isPrivateUse(prev_cp)) {
return 1;
}
}
// If the next cell is whitespace, then
// we allow it to be up to two cells wide.
const next_cp = next_cp: {
var copy = cell_pin;
copy.x += 1;
const next_cell = copy.rowAndCell().cell;
break :next_cp next_cell.codepoint();
};
if (next_cp == 0 or
isSpace(next_cp) or
isPowerline(next_cp))
{
return 2;
}
// Must be constrained
return 1;
}
/// Returns the appropriate foreground mode for the given cell. This is
/// meant to be called from the typical updateCell function within a
/// renderer.

View File

@ -14,6 +14,7 @@ const Surface = @import("../Surface.zig");
const link = @import("link.zig");
const cellpkg = @import("cell.zig");
const fgMode = cellpkg.fgMode;
const constraintWidth = cellpkg.constraintWidth;
const isCovering = cellpkg.isCovering;
const imagepkg = @import("image.zig");
const Image = imagepkg.Image;
@ -26,6 +27,8 @@ const ArenaAllocator = std.heap.ArenaAllocator;
const Terminal = terminal.Terminal;
const Health = renderer.Health;
const getConstraint = @import("../font/nerd_font_attributes.zig").getConstraint;
const FileType = @import("../file_type.zig").FileType;
const macos = switch (builtin.os.tag) {
@ -3030,6 +3033,9 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
.grid_metrics = self.grid_metrics,
.thicken = self.config.font_thicken,
.thicken_strength = self.config.font_thicken_strength,
.cell_width = cell.gridWidth(),
.constraint = getConstraint(cell.codepoint()),
.constraint_width = constraintWidth(cell_pin),
},
);