mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-06 07:15:30 -04:00
render: styled underlines
This was originally contributed by @kraftwerk28 in https://codeberg.org/dnkl/foot/pulls/1099 Here, we re-use the rendering logic only, as attribute tracking has been completely rewritten.
This commit is contained in:
parent
a45ccfaed0
commit
8e2402605e
1 changed files with 118 additions and 1 deletions
119
render.c
119
render.c
|
|
@ -384,6 +384,120 @@ draw_underline(const struct terminal *term, pixman_image_t *pix,
|
||||||
x, y + y_ofs, cols * term->cell_width, thickness});
|
x, y + y_ofs, cols * term->cell_width, thickness});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_styled_underline(const struct terminal *term, pixman_image_t *pix,
|
||||||
|
const struct fcft_font *font,
|
||||||
|
const pixman_color_t *color,
|
||||||
|
enum curly_style style, int x, int y, int cols)
|
||||||
|
{
|
||||||
|
xassert(style != CURLY_NONE);
|
||||||
|
|
||||||
|
const int thickness = font->underline.thickness;
|
||||||
|
|
||||||
|
int y_ofs;
|
||||||
|
|
||||||
|
/* Make sure the line isn't positioned below the cell */
|
||||||
|
switch (style) {
|
||||||
|
case CURLY_DOUBLE:
|
||||||
|
case CURLY_CURLY:
|
||||||
|
y_ofs = min(underline_offset(term, font),
|
||||||
|
term->cell_height - thickness * 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
y_ofs = min(underline_offset(term, font),
|
||||||
|
term->cell_height - thickness);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int ceil_w = cols * term->cell_width;
|
||||||
|
|
||||||
|
switch (style) {
|
||||||
|
case CURLY_DOUBLE: {
|
||||||
|
const pixman_rectangle16_t rects[] = {
|
||||||
|
{x, y + y_ofs, ceil_w, thickness},
|
||||||
|
{x, y + y_ofs + thickness * 2, ceil_w, thickness}};
|
||||||
|
pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, color, 2, rects);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CURLY_DASHED: {
|
||||||
|
const int ceil_w = cols * term->cell_width;
|
||||||
|
const int dash_w = ceil_w / 3 + (ceil_w % 3 > 0);
|
||||||
|
const pixman_rectangle16_t rects[] = {
|
||||||
|
{x, y + y_ofs, dash_w, thickness},
|
||||||
|
{x + dash_w * 2, y + y_ofs, dash_w, thickness},
|
||||||
|
};
|
||||||
|
pixman_image_fill_rectangles(
|
||||||
|
PIXMAN_OP_SRC, pix, color, 2, rects);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CURLY_DOTTED: {
|
||||||
|
const int ceil_w = cols * term->cell_width;
|
||||||
|
const int nrects = min(ceil_w / thickness / 2, 16);
|
||||||
|
pixman_rectangle16_t rects[16] = {0};
|
||||||
|
|
||||||
|
for (int i = 0; i < nrects; i++) {
|
||||||
|
rects[i] = (pixman_rectangle16_t){
|
||||||
|
x + i * thickness * 2, y + y_ofs, thickness, thickness};
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, color, nrects, rects);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CURLY_CURLY: {
|
||||||
|
const int top = y + y_ofs;
|
||||||
|
const int bot = top + thickness * 3;
|
||||||
|
const int half_x = x + ceil_w / 2.0, full_x = x + ceil_w;
|
||||||
|
|
||||||
|
const double bt_2 = (bot - top) * (bot - top);
|
||||||
|
const double th_2 = thickness * thickness;
|
||||||
|
const double hx_2 = ceil_w * ceil_w / 4.0;
|
||||||
|
const int th = round(sqrt(th_2 + (th_2 * bt_2 / hx_2)) / 2.);
|
||||||
|
|
||||||
|
#define I(x) pixman_int_to_fixed(x)
|
||||||
|
const pixman_trapezoid_t traps[] = {
|
||||||
|
#if 0 /* characters sit within the "dips" of the curlies */
|
||||||
|
{
|
||||||
|
I(top), I(bot),
|
||||||
|
{{I(x), I(top + th)}, {I(half_x), I(bot + th)}},
|
||||||
|
{{I(x), I(top - th)}, {I(half_x), I(bot - th)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
I(top), I(bot),
|
||||||
|
{{I(half_x), I(bot - th)}, {I(full_x), I(top - th)}},
|
||||||
|
{{I(half_x), I(bot + th)}, {I(full_x), I(top + th)}},
|
||||||
|
}
|
||||||
|
#else /* characters sit on top of the curlies */
|
||||||
|
{
|
||||||
|
I(top), I(bot),
|
||||||
|
{{I(x), I(bot - th)}, {I(half_x), I(top - th)}},
|
||||||
|
{{I(x), I(bot + th)}, {I(half_x), I(top + th)}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
I(top), I(bot),
|
||||||
|
{{I(half_x), I(top + th)}, {I(full_x), I(bot + th)}},
|
||||||
|
{{I(half_x), I(top - th)}, {I(full_x), I(bot - th)}},
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
pixman_image_t *fill = pixman_image_create_solid_fill(color);
|
||||||
|
pixman_composite_trapezoids(
|
||||||
|
PIXMAN_OP_OVER, fill, pix, PIXMAN_a8, 0, 0, 0, 0,
|
||||||
|
sizeof(traps) / sizeof(traps[0]), traps);
|
||||||
|
|
||||||
|
pixman_image_unref(fill);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
draw_underline(term, pix, font, color, x, y, cols);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_strikeout(const struct terminal *term, pixman_image_t *pix,
|
draw_strikeout(const struct terminal *term, pixman_image_t *pix,
|
||||||
const struct fcft_font *font,
|
const struct fcft_font *font,
|
||||||
|
|
@ -849,6 +963,7 @@ render_cell(struct terminal *term, pixman_image_t *pix, pixman_region32_t *damag
|
||||||
/* Underline */
|
/* Underline */
|
||||||
if (cell->attrs.underline) {
|
if (cell->attrs.underline) {
|
||||||
pixman_color_t underline_color = fg;
|
pixman_color_t underline_color = fg;
|
||||||
|
enum curly_style underline_style = CURLY_SINGLE;
|
||||||
|
|
||||||
/* Check if cell has a styled underline. This lookup is fairly
|
/* Check if cell has a styled underline. This lookup is fairly
|
||||||
expensive... */
|
expensive... */
|
||||||
|
|
@ -876,12 +991,14 @@ render_cell(struct terminal *term, pixman_image_t *pix, pixman_region32_t *damag
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
underline_style = range->curly.style;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_underline(term, pix, font, &underline_color, x, y, cell_cols);
|
draw_styled_underline(
|
||||||
|
term, pix, font, &underline_color, underline_style, x, y, cell_cols);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue