mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-08 10:06:22 -05:00
Merge branch 'allow-bleeding-glyphs'
This commit is contained in:
commit
a18959f2df
6 changed files with 71 additions and 75 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -33,6 +33,9 @@
|
|||
|
||||
* `locked-title=no|yes` to `foot.ini`
|
||||
(https://codeberg.org/dnkl/foot/issues/386).
|
||||
* `tweak.overflowing-glyphs` option, which can be enabled to fix rendering
|
||||
issues with glyphs of any width that appear cut-off
|
||||
(https://codeberg.org/dnkl/foot/issues/592).
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
@ -45,6 +48,12 @@
|
|||
|
||||
### Deprecated
|
||||
### Removed
|
||||
|
||||
* The `tweak.allow-overflowing-double-width-glyphs` and
|
||||
`tweak.pua-double-width` options (which have been superseded by
|
||||
`tweak.overflowing-glyphs`).
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
* Glyph offset not being taken into account when applying
|
||||
|
|
@ -69,6 +78,8 @@
|
|||
### Security
|
||||
### Contributors
|
||||
|
||||
* [clktmr](https://codeberg.org/clktmr)
|
||||
|
||||
|
||||
## 1.8.1
|
||||
|
||||
|
|
|
|||
17
config.c
17
config.c
|
|
@ -2213,16 +2213,10 @@ parse_section_tweak(
|
|||
return false;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "allow-overflowing-double-width-glyphs") == 0) {
|
||||
conf->tweak.allow_overflowing_double_width_glyphs = str_to_bool(value);
|
||||
if (!conf->tweak.allow_overflowing_double_width_glyphs)
|
||||
LOG_WARN("tweak: disabled overflowing double-width glyphs");
|
||||
}
|
||||
|
||||
else if (strcmp(key, "pua-double-width") == 0) {
|
||||
conf->tweak.pua_double_width = str_to_bool(value);
|
||||
if (conf->tweak.pua_double_width)
|
||||
LOG_WARN("tweak: PUA double width glyphs enabled");
|
||||
else if (strcmp(key, "overflowing-glyphs") == 0) {
|
||||
conf->tweak.overflowing_glyphs = str_to_bool(value);
|
||||
if (!conf->tweak.overflowing_glyphs)
|
||||
LOG_WARN("tweak: disabled overflowing glyphs");
|
||||
}
|
||||
|
||||
else if (strcmp(key, "damage-whole-window") == 0) {
|
||||
|
|
@ -2833,7 +2827,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
|
||||
.tweak = {
|
||||
.fcft_filter = FCFT_SCALING_FILTER_LANCZOS3,
|
||||
.allow_overflowing_double_width_glyphs = true,
|
||||
.overflowing_glyphs = true,
|
||||
.grapheme_shaping = false,
|
||||
.grapheme_width_method = GRAPHEME_WIDTH_DOUBLE,
|
||||
.delayed_render_lower_ns = 500000, /* 0.5ms */
|
||||
|
|
@ -2844,7 +2838,6 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.damage_whole_window = false,
|
||||
.box_drawing_base_thickness = 0.04,
|
||||
.box_drawing_solid_shades = true,
|
||||
.pua_double_width = false,
|
||||
},
|
||||
|
||||
.notifications = tll_init(),
|
||||
|
|
|
|||
3
config.h
3
config.h
|
|
@ -245,7 +245,7 @@ struct config {
|
|||
|
||||
struct {
|
||||
enum fcft_scaling_filter fcft_filter;
|
||||
bool allow_overflowing_double_width_glyphs;
|
||||
bool overflowing_glyphs;
|
||||
bool grapheme_shaping;
|
||||
enum {GRAPHEME_WIDTH_WCSWIDTH, GRAPHEME_WIDTH_DOUBLE} grapheme_width_method;
|
||||
bool render_timer_osd;
|
||||
|
|
@ -256,7 +256,6 @@ struct config {
|
|||
off_t max_shm_pool_size;
|
||||
float box_drawing_base_thickness;
|
||||
bool box_drawing_solid_shades;
|
||||
bool pua_double_width;
|
||||
} tweak;
|
||||
|
||||
user_notifications_t notifications;
|
||||
|
|
|
|||
|
|
@ -847,34 +847,24 @@ any of these options.
|
|||
|
||||
Default: _lanczos3_.
|
||||
|
||||
*allow-overflowing-double-width-glyphs*
|
||||
Boolean. When enabled, double width glyphs with a character width
|
||||
of 1 are allowed to overflow into the neighbouring cell.
|
||||
*overflowing-glyphs*
|
||||
Boolean. When enabled, glyphs wider than their cell(s) are allowed
|
||||
to render into one additional neighbouring cell.
|
||||
|
||||
One use case for this is fonts "icon" characters in the Unicode
|
||||
private usage area, e.g. Nerd Fonts, or Powerline Fonts. Without
|
||||
this option, such glyphs will appear "cut off".
|
||||
One use case for this are fonts with wide italic characters that
|
||||
"bend" into the next cell. Without this option, such glyphs will
|
||||
appear "cut off".
|
||||
|
||||
Another use case are legacy emoji characters like *WHITE FROWNING
|
||||
FACE*.
|
||||
Another use case are fonts with "icon" characters in the Unicode
|
||||
private usage area, e.g. Nerd Fonts, or Powerline Fonts and legacy
|
||||
emoji characters like *WHITE FROWNING FACE*.
|
||||
|
||||
Note: this feature uses _heuristics_ to determine *which* glyphs
|
||||
should be allowed to overflow.
|
||||
|
||||
See also: *pua-double-width*
|
||||
Note: might impact performance depending on the font used.
|
||||
Especially small font sizes can cause many overflowing glyphs
|
||||
because of subpixel rendering.
|
||||
|
||||
Default: _yes_.
|
||||
|
||||
*pua-double-width*
|
||||
Boolean. When enabled, Unicode code points from the private usage
|
||||
area (PUA) are always considered to be double width, regardless of
|
||||
the actual glyph width.
|
||||
|
||||
Ignored if *allow-overflowing-double-width-glyphs* has been
|
||||
disabled.
|
||||
|
||||
Default: _no_.
|
||||
|
||||
*render-timer*
|
||||
Enables a frame rendering timer, that prints the time it takes to
|
||||
render each frame, in microseconds, either on-screen, to stderr,
|
||||
|
|
|
|||
78
render.c
78
render.c
|
|
@ -437,6 +437,20 @@ draw_cursor(const struct terminal *term, const struct cell *cell,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_cell_prepass(struct terminal *term, struct row *row, int col)
|
||||
{
|
||||
for (; col < term->cols - 1; col++) {
|
||||
if (row->cells[col].attrs.confined ||
|
||||
(row->cells[col].attrs.clean == row->cells[col + 1].attrs.clean)) {
|
||||
break;
|
||||
}
|
||||
|
||||
row->cells[col].attrs.clean = 0;
|
||||
row->cells[col + 1].attrs.clean = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
render_cell(struct terminal *term, pixman_image_t *pix,
|
||||
struct row *row, int col, int row_no, bool has_cursor)
|
||||
|
|
@ -446,6 +460,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
return 0;
|
||||
|
||||
cell->attrs.clean = 1;
|
||||
cell->attrs.confined = true;
|
||||
|
||||
int width = term->cell_width;
|
||||
int height = term->cell_height;
|
||||
|
|
@ -597,51 +612,32 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
cell_cols = max(1, min(cell_cols, cols_left));
|
||||
|
||||
/*
|
||||
* Hack!
|
||||
*
|
||||
* Deal with double-width glyphs for which wcwidth() returns
|
||||
* 1. Typically Unicode private usage area characters,
|
||||
* e.g. powerline, or nerd hack fonts.
|
||||
*
|
||||
* Users can enable a tweak option that lets this glyphs
|
||||
* overflow/bleed into the neighbouring cell.
|
||||
*
|
||||
* We only apply this workaround if:
|
||||
* - the user has explicitly enabled this feature
|
||||
* - the *character* width is 1
|
||||
* - the *glyph* width is at least 1.5 cells
|
||||
* - the *glyph* width is less than 3 cells
|
||||
* - *this* column isn’t the last column
|
||||
* - *this* cells is followed by an empty cell, or a space
|
||||
* Determine cells that will bleed into their right neighbor and remember
|
||||
* them for cleanup in the next frame.
|
||||
*/
|
||||
if (term->conf->tweak.allow_overflowing_double_width_glyphs &&
|
||||
glyph_count > 0 &&
|
||||
cell_cols == 1 &&
|
||||
col < term->cols - 1 &&
|
||||
((glyphs[0]->x + glyphs[0]->width >= term->cell_width * 15 / 10 &&
|
||||
glyphs[0]->x + glyphs[0]->width < 3 * term->cell_width) ||
|
||||
(term->conf->tweak.pua_double_width &&
|
||||
((base >= 0x00e000 && base <= 0x00f8ff) ||
|
||||
(base >= 0x0f0000 && base <= 0x0ffffd) ||
|
||||
(base >= 0x100000 && base <= 0x10fffd)))) &&
|
||||
(row->cells[col + 1].wc == 0 || row->cells[col + 1].wc == L' '))
|
||||
int render_width = cell_cols * width;
|
||||
if (term->conf->tweak.overflowing_glyphs &&
|
||||
glyph_count > 0)
|
||||
{
|
||||
cell_cols = 2;
|
||||
int glyph_width = 0, advance = 0;
|
||||
for (size_t i = 0; i < glyph_count; i++) {
|
||||
glyph_width = max(glyph_width,
|
||||
advance + glyphs[i]->x + glyphs[i]->width);
|
||||
advance += glyphs[i]->advance.x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the cell we’re overflowing into gets re-rendered, to
|
||||
* ensure it is erased if *this* cell is erased. Note that we
|
||||
* do *not* mark the row as dirty - we don’t need to re-render
|
||||
* the cell if nothing else on the row has changed.
|
||||
*/
|
||||
row->cells[col].attrs.clean = 0;
|
||||
row->cells[col + 1].attrs.clean = 0;
|
||||
if (glyph_width > render_width) {
|
||||
render_width = min(glyph_width, render_width + width);
|
||||
|
||||
for (int i = 0; i < cell_cols; i++)
|
||||
row->cells[col + i].attrs.confined = false;
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_t clip;
|
||||
pixman_region32_init_rect(
|
||||
&clip, x, y,
|
||||
cell_cols * term->cell_width, term->cell_height);
|
||||
render_width, term->cell_height);
|
||||
pixman_image_set_clip_region32(pix, &clip);
|
||||
|
||||
/* Background */
|
||||
|
|
@ -771,6 +767,10 @@ static void
|
|||
render_row(struct terminal *term, pixman_image_t *pix, struct row *row,
|
||||
int row_no, int cursor_col)
|
||||
{
|
||||
if (term->conf->tweak.overflowing_glyphs)
|
||||
for (int col = term->cols - 1; col >= 0; col--)
|
||||
render_cell_prepass(term, row, col);
|
||||
|
||||
for (int col = term->cols - 1; col >= 0; col--)
|
||||
render_cell(term, pix, row, col, row_no, cursor_col == col);
|
||||
}
|
||||
|
|
@ -1192,8 +1192,10 @@ render_sixel(struct terminal *term, pixman_image_t *pix,
|
|||
(last_col_needs_erase && last_col))
|
||||
{
|
||||
render_cell(term, pix, row, col, term_row_no, cursor_col == col);
|
||||
} else
|
||||
} else {
|
||||
cell->attrs.clean = 1;
|
||||
cell->attrs.confined = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,12 @@ struct attributes {
|
|||
uint32_t fg:24;
|
||||
|
||||
bool clean:1;
|
||||
bool confined:1;
|
||||
bool have_fg:1;
|
||||
bool have_bg:1;
|
||||
uint32_t selected:2;
|
||||
bool url:1;
|
||||
uint32_t reserved:2;
|
||||
uint32_t reserved:1;
|
||||
uint32_t bg:24;
|
||||
};
|
||||
static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue