Skip to content

Character overflow determined incorrectly in src/font_pango.c by #135 #145

@sidstuff

Description

@sidstuff

In src/font_pango.c, whether a character overflows is determined (on line 484) by glyph->width, which in turn is determined by lines 201–203

pango_layout_line_get_pixel_extents(line, &logical_rec, &rec);

glyph->width = (logical_rec.width > face->real_attr.width) ? 2 : cwidth;

But despite using font-name=JetBrainsMono Nerd Font Mono, which is monospaced, the arrow characters shown below have a logical_rec.width very slightly larger than face->real_attr.width. Thus they end up being displayed as shown on the left, when they should correctly be displayed as shown on the right (and were displayed correctly prior to #135).

Image 1

Even so, this issue only appears due to the rounding behavior of pango_layout_line_get_pixel_extents(). From the documentation

This function just calls pango_layout_line_get_extents() followed by two pango_extents_to_pixels() calls, rounding ink_rect and logical_rect such that the rounded rectangles fully contain the unrounded one (that is, passes them as first argument to pango_extents_to_pixels()).

Thus we can fix this by replacing the call to pango_layout_line_get_pixel_extents() with

pango_layout_line_get_extents(line, &logical_rec, &rec);
pango_extents_to_pixels(&rec, &logical_rec);

By passing &logical_rec as the second argument to pango_extents_to_pixels(), it is rounded to the nearest rectangle rather than being rounded up to one that overflows.

Now switching to font-name=JetBrainsMono Nerd Font, which is not strictly monospaced, we spot another issue.

Image 2

Some characters have their drawn width logical_rec.width smaller than the terminal's face->real_attr.width, but are actually drawn offset such that they do need to overflow. The solution is to correctly check whether the drawn character extends beyond a single fixed width.

Thus we need to modify the assignment of glyph->width to

glyph->width = (logical_rec.x + logical_rec.width > rec.x + face->real_attr.width) ? 2 : cwidth;

TL;DR

Some characters in popular Nerd Fonts are sized/offset such that #135 incorrectly determines whether or not they are to overflow.

This can be solved by replacing lines 201–203 in src/font_pango.c with

pango_layout_line_get_extents(line, &logical_rec, &rec);
pango_extents_to_pixels(&rec, &logical_rec);

glyph->width = (logical_rec.x + logical_rec.width > rec.x + face->real_attr.width) ? 2 : cwidth;

Since it's just a three line change, I haven't opened a PR myself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions