render: optionally enable heuristics that deal with private usage area chars

Try to detect double-width *glyphs* for single-width *characters*, and
allow them to overflow into the next cell.

This is only done for single-width chars with a glyph width that is at
least 1.5 cells wide, but at most 3 cells.

The feature is gated by the new
‘tweak.allow-overflowing-double-width-glyphs’, and is disabled by
default.

Closes #116
This commit is contained in:
Daniel Eklöf 2020-09-03 17:37:44 +02:00
parent bb8d9378c9
commit b71016c25d
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 52 additions and 1 deletions

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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,

View file

@ -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,