daa84 / neovim-gtk

gtk ui for neovim
GNU General Public License v3.0
718 stars 57 forks source link

Incorrect line height with nerd fonts #193

Open ProgramFan opened 5 years ago

ProgramFan commented 5 years ago

Describe the bug neovim-gtk produces large line height with nerd font DejaVuSansMono Nerd Font Mono on Fedora 29. The line height is about 4 pixels larger than that the same configuration in gnome-terminal and makes the status line looking bad.

After digging into the source code, I found nvim-gtk calculate line height in this way at https://github.com/daa84/neovim-gtk/blob/6a7804c6e797142724548b09109cf2883cd6f08c/src/render/context.rs#L119:

line_height: f64::from(font_metrics.get_ascent() + font_metrics.get_descent())
                / f64::from(pango::SCALE)
+ f64::from(line_space),

With fonts like the nerd font family, some glyphs have larger ascents than the usual characters, thus makes the line height larger.

After going through the vte code, I found that it deals with cell width in a different way. Actually, vte pre-calculates cell height by pre-rendering a line of ascii visible chars and estimating the logical box. The logic is like the following code:

        // The vte (core of gnome-terminal) way to calculate cell height
        char single_width_chars[] = ""
            "  ! \" # $ % & ' ( ) * + , - . / "
            "0 1 2 3 4 5 6 7 8 9 "
            ": ; < = > ? @ "
            "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
            "[ \\ ] ^ _ ` "
            "a b c d e f g h i j k l m n o p q r s t u v w x y z "
            "{ | } ~ "
            "";
        PangoContext *context;
        PangoLayout *layout;
        PangoRectangle logical_box;
        context = pango_context_new();
        layout = pange_layout_new(context);
        pango_layout_set_text(layout, single_width_chars, -1);
        pango_layout_set_font_description(layout, font_desc);
        pango_layout_get_extents(layout, NULL, &logical_box);
        pango_layout_free(layout);
        pange_context_free(context);
        line_height = f64::from(logical_box.height) / f64::from(pango::SCALE);
        line_height += f64::from(line_space);

Can neovim-gtk implement the same logic? Unfornately I am not familiar with rust.

Technical information (please complete the following information):

daa84 commented 5 years ago

You can try workaround with GuiLinespace command with -4 argument.

ProgramFan commented 5 years ago

Thanks. I tried but it only distorts the line further. Then I think this is more than calculating the line height. VTE uses such a strange way to calculate cell height and cell width. There must be a deep reason.