font: add cursor-height metric, and adjust- config for it.

This commit is contained in:
Qwerasd
2024-12-21 20:15:32 -05:00
parent dd6460bc77
commit 077dad11b4
4 changed files with 27 additions and 27 deletions

View File

@ -241,16 +241,15 @@ const c = @cImport({
/// `-100%`) can cause the terminal to be unusable. Use with caution and reason.
///
/// Some values are clamped to minimum or maximum values. This can make it
/// appear that certain values are ignored. For example, the underline position
/// is clamped to the height of a cell. If you set the underline position so
/// high that it extends beyond the bottom of the cell size, it will be clamped
/// to the bottom of the cell.
/// appear that certain values are ignored. For example, many `*-thickness`
/// adjustments cannot go below 1px.
///
/// `adjust-cell-height` has some additional behaviors to describe:
///
/// * The font will be centered vertically in the cell.
///
/// * The cursor will remain the same size as the font.
/// * The cursor will remain the same size as the font, but may be
/// adjusted separately with `adjust-cursor-height`.
///
/// * Powerline glyphs will be adjusted along with the cell height so
/// that things like status lines continue to look aligned.
@ -276,6 +275,9 @@ const c = @cImport({
@"adjust-overline-thickness": ?MetricModifier = null,
/// Thickness in pixels of the bar cursor and outlined rect cursor.
@"adjust-cursor-thickness": ?MetricModifier = null,
/// Height in pixels of the cursor. Currently applies to all cursor types:
/// bar, rect, and outlined rect.
@"adjust-cursor-height": ?MetricModifier = null,
/// Thickness in pixels of box drawing characters.
@"adjust-box-thickness": ?MetricModifier = null,

View File

@ -430,6 +430,7 @@ pub const DerivedConfig = struct {
@"adjust-overline-position": ?Metrics.Modifier,
@"adjust-overline-thickness": ?Metrics.Modifier,
@"adjust-cursor-thickness": ?Metrics.Modifier,
@"adjust-cursor-height": ?Metrics.Modifier,
@"adjust-box-thickness": ?Metrics.Modifier,
@"freetype-load-flags": font.face.FreetypeLoadFlags,
@ -468,6 +469,7 @@ pub const DerivedConfig = struct {
.@"adjust-overline-position" = config.@"adjust-overline-position",
.@"adjust-overline-thickness" = config.@"adjust-overline-thickness",
.@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness",
.@"adjust-cursor-height" = config.@"adjust-cursor-height",
.@"adjust-box-thickness" = config.@"adjust-box-thickness",
.@"freetype-load-flags" = if (font.face.FreetypeLoadFlags != void) config.@"freetype-load-flags" else {},
@ -613,6 +615,7 @@ pub const Key = struct {
if (config.@"adjust-overline-position") |m| try set.put(alloc, .overline_position, m);
if (config.@"adjust-overline-thickness") |m| try set.put(alloc, .overline_thickness, m);
if (config.@"adjust-cursor-thickness") |m| try set.put(alloc, .cursor_thickness, m);
if (config.@"adjust-cursor-height") |m| try set.put(alloc, .cursor_height, m);
if (config.@"adjust-box-thickness") |m| try set.put(alloc, .box_thickness, m);
break :set set;
};

View File

@ -32,10 +32,12 @@ box_thickness: u32,
/// because it is not determined by fonts but rather by user configuration.
cursor_thickness: u32 = 1,
/// Original cell width and height. These are used to render the cursor
/// in the original cell size after modification.
/// The height in pixels of the cursor sprite.
cursor_height: u32,
/// Original cell width in pixels. This is used to keep
/// glyphs centered if the cell width is adjusted wider.
original_cell_width: ?u32 = null,
original_cell_height: ?u32 = null,
/// Minimum acceptable values for some fields to prevent modifiers
/// from being able to, for example, cause 0-thickness underlines.
@ -47,6 +49,7 @@ const Minimums = struct {
const overline_thickness = 1;
const box_thickness = 1;
const cursor_thickness = 1;
const cursor_height = 1;
};
const CalcOpts = struct {
@ -167,6 +170,7 @@ pub fn calc(opts: CalcOpts) Metrics {
.overline_position = 0,
.overline_thickness = @intFromFloat(underline_thickness),
.box_thickness = @intFromFloat(underline_thickness),
.cursor_height = @intFromFloat(cell_height),
};
// Ensure all metrics are within their allowable range.
@ -192,10 +196,9 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void {
const new = @max(entry.value_ptr.apply(original), 1);
if (new == original) continue;
// Preserve the original cell width and height if not set.
// Preserve the original cell width if not set.
if (self.original_cell_width == null) {
self.original_cell_width = self.cell_width;
self.original_cell_height = self.cell_height;
}
// Set the new value
@ -410,6 +413,7 @@ fn init() Metrics {
.overline_position = 0,
.overline_thickness = 0,
.box_thickness = 0,
.cursor_height = 0,
};
}
@ -445,7 +449,7 @@ test "Metrics: adjust cell height smaller" {
try testing.expectEqual(@as(u32, 25), m.cell_baseline);
try testing.expectEqual(@as(u32, 30), m.underline_position);
try testing.expectEqual(@as(u32, 5), m.strikethrough_position);
try testing.expectEqual(@as(u32, 100), m.original_cell_height.?);
try testing.expectEqual(@as(u32, 100), m.cursor_height);
}
test "Metrics: adjust cell height larger" {
@ -466,7 +470,7 @@ test "Metrics: adjust cell height larger" {
try testing.expectEqual(@as(u32, 100), m.cell_baseline);
try testing.expectEqual(@as(u32, 105), m.underline_position);
try testing.expectEqual(@as(u32, 80), m.strikethrough_position);
try testing.expectEqual(@as(u32, 100), m.original_cell_height.?);
try testing.expectEqual(@as(u32, 100), m.cursor_height);
}
test "Modifier: parse absolute" {

View File

@ -126,29 +126,20 @@ pub fn renderGlyph(
},
.cursor => cursor: {
// Cursors should be drawn with the original cell height if
// it has been adjusted larger, so they don't get stretched.
const height, const dy = adjust: {
const h = metrics.cell_height;
if (metrics.original_cell_height) |original| {
if (h > original) {
break :adjust .{ original, (h - original) / 2 };
}
}
break :adjust .{ h, 0 };
};
var g = try cursor.renderGlyph(
alloc,
atlas,
@enumFromInt(cp),
width,
height,
metrics.cursor_height,
metrics.cursor_thickness,
);
// Keep the cursor centered in the cell if it's shorter.
g.offset_y += @intCast(dy);
// Cursors are drawn at their specified height
// and are centered vertically within the cell.
const cursor_height: i32 = @intCast(metrics.cursor_height);
const cell_height: i32 = @intCast(metrics.cell_height);
g.offset_y += @divTrunc(cell_height - cursor_height, 2);
break :cursor g;
},