diff --git a/CHANGELOG.md b/CHANGELOG.md index 537e7d88..05133296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,10 @@ Ps r` (https://codeberg.org/dnkl/foot/issues/91). * `$COLORTERM` is now set to `truecolor` at startup, to indicate support for 24-bit RGB colors. +* Experimental support for rendering double-width glyphs with a + character width of 1. Must be explicitly enabled with + `tweak.allow-overflowing-double-width-glyphs` + (https://codeberg.org/dnkl/foot/issues/116). ### Deprecated diff --git a/config.c b/config.c index 83a0ef4d..56e5af12 100644 --- a/config.c +++ b/config.c @@ -1358,7 +1358,10 @@ parse_section_tweak( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - if (strcmp(key, "render-timer") == 0) { + if (strcmp(key, "allow-overflowing-double-width-glyphs") == 0) + conf->tweak.allow_overflowing_double_width_glyphs = str_to_bool(value); + + else if (strcmp(key, "render-timer") == 0) { if (strcmp(value, "none") == 0) { conf->tweak.render_timer_osd = false; conf->tweak.render_timer_log = false; @@ -1792,6 +1795,7 @@ config_load(struct config *conf, const char *conf_path, bool errors_are_fatal) .hold_at_exit = false, .tweak = { + .allow_overflowing_double_width_glyphs = false, .delayed_render_lower_ns = 500000, /* 0.5ms */ .delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */ .max_shm_pool_size = 512 * 1024 * 1024, diff --git a/config.h b/config.h index fac5ea89..2368e53c 100644 --- a/config.h +++ b/config.h @@ -144,6 +144,7 @@ struct config { bool hold_at_exit; struct { + bool allow_overflowing_double_width_glyphs; bool render_timer_osd; bool render_timer_log; uint64_t delayed_render_lower_ns; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 9f8c6cbb..87a81a4e 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -440,6 +440,23 @@ foot. When reporting bugs, please mention if, and to what, you have changed any of these options. +*allow-overflowing-double-width-glyphs* + + When enabled, double width glyphs with a character width of 1 are + allowed to overflow into the 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". + + Another use case are legacy emoji characters like *WHITE FROWNING + FACE*. + + Note: this feature uses _heuristics_ to determine *which* glyphs + should be allowed to overflow. + + Default: _false_. + *render-timer* Enables a frame rendering timer, that prints the time it takes to render each frame, in microseconds, either on-screen, to stderr, diff --git a/render.c b/render.c index 08caabc7..ea21b808 100644 --- a/render.c +++ b/render.c @@ -433,6 +433,31 @@ render_cell(struct terminal *term, pixman_image_t *pix, const int cols_left = term->cols - col; int cell_cols = glyph != NULL ? max(1, min(glyph->cols, cols_left)) : 1; + /* + * 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 + */ + if (term->conf->tweak.allow_overflowing_double_width_glyphs && + glyph != NULL && + glyph->cols == 1 && + glyph->width >= term->cell_width * 15 / 10 && + glyph->width < 3 * term->cell_width) + { + cell_cols = min(2, cols_left); + } + pixman_region32_t clip; pixman_region32_init_rect( &clip, x, y,