main: Support overline, SGR 53/55

Similar to the underline, incl. the *-thickness and *-offset options.
This commit is contained in:
Andrew Savchenko 2026-01-02 13:37:26 +11:00
parent 42e04c5c87
commit 33106514db
No known key found for this signature in database
GPG key ID: 5023209D10DBA986
7 changed files with 70 additions and 2 deletions

View file

@ -1078,6 +1078,12 @@ parse_section_main(struct context *ctx)
else if (streq(key, "strikeout-thickness"))
return value_to_pt_or_px(ctx, &conf->strikeout_thickness);
else if (streq(key, "overline-thickness"))
return value_to_pt_or_px(ctx, &conf->overline_thickness);
else if (streq(key, "overline-offset"))
return value_to_pt_or_px(ctx, &conf->overline_offset);
else if (streq(key, "dpi-aware"))
return value_to_bool(ctx, &conf->dpi_aware);
@ -3476,6 +3482,8 @@ config_load(struct config *conf, const char *conf_path,
.box_drawings_uses_font_glyphs = false,
.underline_thickness = {.pt = 0., .px = -1},
.strikeout_thickness = {.pt = 0., .px = -1},
.overline_thickness = {.pt = 0., .px = -1},
.overline_offset = {.pt = 0., .px = -1},
.dpi_aware = false,
.gamma_correct = false,
.uppercase_regex_insert = true,

View file

@ -273,6 +273,9 @@ struct config {
struct pt_or_px strikeout_thickness;
struct pt_or_px overline_thickness;
struct pt_or_px overline_offset;
bool box_drawings_uses_font_glyphs;
bool can_shape_grapheme;

3
csi.c
View file

@ -150,6 +150,9 @@ csi_sgr(struct terminal *term)
case 28: term->vt.attrs.conceal = false; break;
case 29: term->vt.attrs.strikethrough = false; break;
case 53: term->vt.attrs.overline = true; break;
case 55: term->vt.attrs.overline = false; break;
/* Regular foreground colors */
case 30:
case 31:

View file

@ -175,6 +175,10 @@ m*.
: Disable conceal
| 29
: Disable crossed-out
| 53
: Overline
| 55
: Disable overline
| 30-37
: Select foreground color (using *regularN* in *foot.ini*(5))
| 38

View file

@ -198,6 +198,29 @@ empty string to be set, but it must be quoted: *KEY=""*)
Default: _unset_
*overline-thickness*
Use a custom thickness (height) for overlines. The thickness is, by
default, in _points_.
To specify a thickness in _pixels_, append *px*:
*overline-thickness=1px*.
If left unset (the default), the font's underline thickness is used.
Default: _unset_
*overline-offset*
Vertical offset of the overline from the top of the cell. The offset is,
by default, in _points_.
To specify an offset in _pixels_, append *px*:
*overline-offset=2px*.
If left unset (the default), the overline is drawn at the absolute top
of the cell (offset = 0).
Default: _unset_ (0)
*gamma-correct-blending*
Boolean. When enabled, foot will do gamma-correct blending in
linear color space. This is how font glyphs are supposed to be

View file

@ -598,6 +598,27 @@ draw_strikeout(const struct terminal *term, pixman_image_t *pix,
cols * term->cell_width, thickness});
}
static void
draw_overline(const struct terminal *term, pixman_image_t *pix,
const struct fcft_font *font,
const pixman_color_t *color, int x, int y, int cols)
{
const int thickness = term->conf->overline_thickness.px >= 0
? term_pt_or_px_as_pixels(
term, &term->conf->overline_thickness)
: font->underline.thickness;
const int offset = term->conf->overline_offset.px >= 0
? term_pt_or_px_as_pixels(
term, &term->conf->overline_offset)
: 0;
pixman_image_fill_rectangles(
PIXMAN_OP_SRC, pix, color,
1, &(pixman_rectangle16_t){
x, y + offset, cols * term->cell_width, thickness});
}
static void
cursor_colors_for_cell(const struct terminal *term, const struct cell *cell,
const pixman_color_t *fg, const pixman_color_t *bg,
@ -1173,6 +1194,9 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (cell->attrs.strikethrough)
draw_strikeout(term, pix, font, &fg, x, y, cell_cols);
if (cell->attrs.overline)
draw_overline(term, pix, font, &fg, x, y, cell_cols);
if (unlikely(cell->attrs.url)) {
pixman_color_t url_color = color_hex_to_pixman(
term->conf->colors_dark.use_custom.url

View file

@ -57,8 +57,11 @@ struct attributes {
bool selected:1;
bool url:1;
uint32_t bg:24;
bool overline:1;
uint32_t reserved:31; /* Future attributes? */
};
static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large");
static_assert(sizeof(struct attributes) == 12, "VT attribute struct size mismatch");
/* Last valid Unicode code point is 0x0010FFFFul */
#define CELL_COMB_CHARS_LO 0x00200000ul
@ -69,7 +72,7 @@ struct cell {
char32_t wc;
struct attributes attrs;
};
static_assert(sizeof(struct cell) == 12, "bad size");
static_assert(sizeof(struct cell) == 16, "bad size");
struct scroll_region {
int start;