kovidgoyal / kitty

Cross-platform, fast, feature-rich, GPU based terminal
https://sw.kovidgoyal.net/kitty/
GNU General Public License v3.0
22.38k stars 910 forks source link

Vertically mis-aligned text #2022

Closed roginfarrer closed 3 years ago

roginfarrer commented 4 years ago

Version: 0.14.6 OS: MacOS 10.14.4

Using Fira Code (v2), the text appears to be oddly aligned to the top instead of the center or baseline. This does not happen in iTerm. I was able to reproduce this on two different machines (but same configs).

I don't have anything special in my kitty.conf. Just setting the font-family to Fira Code.

Screenshots:

Screen Shot 2019-10-03 at 10 08 06 PM Screen Shot 2019-10-03 at 10 07 37 PM

Here is the vim statusbar in iTerm, where the text is aligned normally.

Screen Shot 2019-10-03 at 10 12 18 PM Screen Shot 2019-10-03 at 10 12 47 PM
kovidgoyal commented 4 years ago

Post the output of kitty --debug-config

roginfarrer commented 4 years ago

Result of kitty --debug-config

kitty 0.14.6 created by Kovid Goyal
Darwin Rogins-MBP.T-mobile.com 18.5.0 Darwin Kernel Version 18.5.0: Mon Mar 11 20:40:32 PDT 2019; root:xnu-4903.251.3~3/RELEASE_X86_64 x86_64
ProductName:    Mac OS X ProductVersion:    10.14.4 BuildVersion:   18E226
Loaded config files: /Users/rfarrer/.config/kitty/kitty.conf

Config options different from defaults:
background            Color(red=0, green=38, blue=53)
color0                Color(red=0, green=56, blue=77)
color1                Color(red=196, green=48, blue=97)
color10               Color(red=156, green=240, blue=135)
color11               Color(red=255, green=204, blue=27)
color12               Color(red=126, green=178, blue=221)
color13               Color(red=251, green=148, blue=255)
color14               Color(red=0, green=255, blue=255)
color15               Color(red=183, green=207, blue=249)
color2                Color(red=127, green=192, blue=110)
color3                Color(red=240, green=142, blue=72)
color4                Color(red=28, green=141, blue=178)
color5                Color(red=198, green=148, blue=255)
color6                Color(red=0, green=204, blue=204)
color7                Color(red=119, green=146, blue=158)
color8                Color(red=81, green=127, blue=141)
color9                Color(red=255, green=90, blue=103)
cursor_blink_interval 0.0
enabled_layouts       ['tall']
font_family           Fira Code Retina
font_size             18.0
foreground            Color(red=230, green=230, blue=220)
macos_option_as_alt   3
symbol_map            {(9211, 9214): 'Meslo LG L DZ for Powerline Regular', (11096, 11096): 'Meslo LG L DZ for Powerline Regular', (57856, 58025): 'Meslo LG L DZ for Powerline Regular', (57504, 57507): 'Meslo LG L DZ for Powerline Regular', (57520, 57535): 'Meslo LG L DZ for Powerline Regular', (57536, 57544): 'Meslo LG L DZ for Powerline Regular', (57548, 57551): 'Meslo LG L DZ for Powerline Regular', (57552, 57554): 'Meslo LG L DZ for Powerline Regular', (57556, 57556): 'Meslo LG L DZ for Powerline Regular', (59136, 59333): 'Meslo LG L DZ for Powerline Regular', (61440, 62176): 'Meslo LG L DZ for Powerline Regular', (9829, 9829): 'Meslo LG L DZ for Powerline Regular', (9889, 9889): 'Meslo LG L DZ for Powerline Regular', (62464, 62632): 'Meslo LG L DZ for Powerline Regular', (63100, 63100): 'Meslo LG L DZ for Powerline Regular', (57344, 57354): 'Meslo LG L DZ for Powerline Regular', (62208, 62227): 'Meslo LG L DZ for Powerline Regular', (58874, 58923): 'Meslo LG L DZ for Powerline Regular', (9984, 10175): 'Meslo LG L DZ for Powerline Regular'}
tab_bar_edge          1
tab_bar_style         separator
window_padding_width  6.0
Added shortcuts:
    alt+right KeyAction(func='resize_window', args=['wider', 1])
    alt+left KeyAction(func='resize_window', args=['narrower', 1])
    alt+down KeyAction(func='resize_window', args=['shorter', 1])
    alt+up KeyAction(func='resize_window', args=['taller', 1])
    shift+super+h KeyAction(func='neighboring_window', args=['left'])
    shift+super+j KeyAction(func='neighboring_window', args=['bottom'])
    shift+super+k KeyAction(func='neighboring_window', args=['top'])
    shift+super+l KeyAction(func='neighboring_window', args=['right'])
Changed shortcuts:
    shift+control+h KeyAction(func='move_window', args=['left'])
    shift+control+j KeyAction(func='move_window', args=['bottom'])
    shift+control+k KeyAction(func='move_window', args=['top'])
    shift+control+l KeyAction(func='move_window', args=['right'])
kovidgoyal commented 4 years ago

Dont use Fira Code Retina, just use Fira Code and you should be fine.

roginfarrer commented 4 years ago

I've tried both, Fira Code and Fira Code Retina, both have this problem.

kovidgoyal commented 4 years ago

I cannot reproduce with Fira Code, it basically looks likethe cell height calculation is off. Try using adjust_line_height in kitty.conf to compensate.

tsujp commented 4 years ago

I have(?) this issue(?) as well and I cannot bring it down to whether or not I just think it's vertically misaligned or I am imaging it, in another issue I posted a screenshot where it appears to be but if you just type xxxxxxxxxx and compare the block cursor it looks centred, if you instead type xxxxxxxxxxh (h on the end) it looks misaligned, I suspect this is more to do with how the xheight(?) of the font itself is set more than anything i.e. it's not actually misaligned but just looks like it. Here xxxx ... is just being used to pad away from PS1. It seems to me the bolder the weight the more xheight it takes up, perhaps try a bolder variant. The $ also has a short inferior tail, notice in the picture below that the bottom-side | of the $ does not touch the red, giving the illusion that the $ is higher than it is. This is Fira itself of course.

I tried adjusting adjust_cell_height with integer and float values ranging from -1.0 < x < 1.0 to -10.0 < x 10.0 and saw no change at all so I am unsure how that setting works.

I also found that the default settings Kitty has for other fonts don't play nice with Fira Code in terms of kerning and line-spacing, so here are the settings I used for Fira that make it look somewhat normal. Text is still very, very slightly fuzzy on an external screen (I know this because Sublime Text 3 is using Fira Code and the font there looks razor sharp but Kitty to the side is as mentioned very, very slightly fuzzy or dimmer looking (both are pure white #FFFFFF).

#: Fonts {{{
  # list supported fonts via `kitty list-fonts`

  font_family      Fira Code Medium
  bold_font        Fira Code Bold
  italic_font      auto
  bold_italic_font auto

  # font size (pts)
  font_size 12

  adjust_line_height -3 # make Fira look normal
  adjust_column_width -1 # make Fira look normal
  adjust_cell_height 0.5 # unsure if this is doing something

  disable_ligatures always
#: }}}

I don't know what is causing this, perhaps just a consequence of some weird rendering or makeup of the font. I am not an expert of even as educated as I'd like to be with fonts or font rendering so I'll leave anyone's guesses to themselves regarding that.

Here's a rather arbitrary and unscientific picture comparison, the red lines are parallel to the top and bottom of the block cursor in kitty, with the cyan lines being parallel to the x. Those purple rectangles on the extreme right represent the exact same distance, so things are indeed centred correctly.

img

kovidgoyal commented 4 years ago

The correct setting is adjust_line_height, I misspoke.

fenetikm commented 4 years ago

I am seeing exactly the same issue but with the FiraCode nerd font. Old version looks like this:

image

New version looks like this:

image

Note:

Definitely something funky with respect to the metric calculation. Probably also need a way to adjust the baseline.

kovidgoyal commented 4 years ago

Dont use patched fonts. Patching breaks them. Use fira code and install the nerd font separately, kitty will pick up the symbols from it automatically.

roginfarrer commented 4 years ago

FWIW, I also think this could be an issue with the font. I saw the same weird misalignment with JetBrains Mono at version 1.0.0. I upgraded to 1.0.3, and the alignment was fixed.

fenetikm commented 4 years ago

Thanks - yeah I have now tried using non-patched fonts with and without using symbol_map. Still similar issues. I note that rendering in iterm2 looks fine using either the patched version or the unpatched version. As you say it's most probably an issue with the font - potentially the interaction of Freetype and Fira Code when it comes to metrics calculation.

fenetikm commented 4 years ago

One thing that is probably the easiest to "point at" is the vertical bar symbols in Fira Code. Here is a snap from iTerm2 image and here it is from Kitty image

fenetikm commented 4 years ago

If I get some time, I will see if I can reduce this down to a test against Freetype directly removing Kitty from the equation.

fenetikm commented 4 years ago

errr, I take it back. I mean CoreText :)

ctrlcctrlv commented 4 years ago

I find that highly unlikely. Kitty will change the vertical alignment of text if it feels it has to. See also #2086. The "problem", to the extent that it's truly a problem and not simply just how Kitty works, is that Kitty cannot draw glyphs which overflow their cells. So, no overflow is ever possible. In #2086 we saw that a lot of things can affect whether or not Kitty feels it has to move the glyph to prevent an overflow, and that those things differ between CoreText and FreeType. However, the most important part of the equation will always be whether any part of the glyph vertically overflows its ascent line. Serious overflows are even resized by Kitty to force them into the cell. See #2294 and #352 for the horizontal case.

kovidgoyal commented 4 years ago

IIRC the CoreText backend does a lot less manual adjustment of glyph positions because CoreText is not as flexible/I am less interested. With FreeType kitty will do all sorts of adjusting to make the glyph fit well inside the cell. With CoreText all kitty does is pass the glyph data to CoreText alongwith glyph positioning that comes from harfbuzz and let CoreText handle it. If the resulting bitmap does not fit, it rescales font size and re-renders to force a fit. It is probable that this re-render is what causes misaligned glyphs. But I dont really know of a way to avoid it, as the alternative is chopped of glyphs.

fenetikm commented 4 years ago

Yes, I have been looking at the code as well as the code in iterm2. Essentially it looks like iTerm2 does some scaling and it also sets some different CoreText flags. I did a quick hack in the kitty code to somewhat mimic what iTerm2 does and it seems to look better at first glance. I'll have a look at the harfbuzz data too. I understand you don't have as much interest in CoreText but it's starting to really annoy me so I'll see if I can work something out whilst I still care :)

Regarding chopped off glyphs - do you have a corpus / list of glyphs that you would suggest testing against?

kovidgoyal commented 4 years ago

On Sun, Feb 09, 2020 at 06:29:46PM -0800, Michael Welford wrote:

Regarding chopped off glyphs - do you have a corpus / list of glyphs that you would suggest testing against?

It very much depends on the font. In general try wide capitals like H,M,W

JeanMertz commented 4 years ago

I came here in search of a similar problem. I'm using Operator Mono (ScreenSmart version, I haven't purchased the other families, so can't compare).

Given that the example config mentions using Operator Mono as an example, my impression was that this is not expected behaviour when using Kitty with this font, is that correct?

Screenshot 2020-03-24 at 23 16 35

My config:

font_family      Operator Mono SSm Light
bold_font        Operator Mono SSm Medium
italic_font      Operator Mono SSm Light Italic
bold_italic_font Operator Mono SSm Medium Italic

font_size 12.0

adjust_line_height  2

I've been playing with adjust_line_height, but can't seem to nudge the font to move to the vertical centre (it's slightly closer to the top right now).

fenetikm commented 4 years ago

My understanding is that adjust_line_height doesn't affect where the glyph is positioned in the cell - sadly the only way to cater for all the whackiness going on with respect to font metrics is by introducing a couple more options like adjust_glyph_position_y, adjust_glyph_position_x and adjust_glyph_scale. I'll take a stab at this eventually unless someone gets in first.

ScrumpyJack commented 4 years ago

More examples.

Here I'm using "DroidSansMono Nerd Font"

Screenshot 2020-05-23 at 23 27 06
karb94 commented 3 years ago

Same problem here. I think it happens with several fonts but with Fira Code (the one in the screenshots below) is particularly obvious. This happens with all versions of kitty for me.

kitty.conf:

font_size 16
font_family      Fira Code

kitty: Screenshot 2020-06-22 at 14 03 02

Alacritty: Screenshot 2020-06-22 at 14 32 11

Terminal (ignore the colors): Screenshot 2020-06-22 at 14 29 15

fenetikm commented 3 years ago

See the PR above - this should allow some options so you can tweak exactly what it looks like / where the glyphs are positioned inside the cell.

The problem seems to be the sizing and position of the glyphs inside the cell so no manner of cell transformations (as opposed to glyph) would have helped.

fenetikm commented 3 years ago

So with the above PR, the settings that I am using are (note that I use a different font for the italic):

font_family Fira Code Regular
italic_font Hack Italic
bold_font Fira Code Medium
bold_italic_font Hack Bold Italic

macos_adjust_glyph_scale 0.05
macos_adjust_glyph_y -4.0
macos_adjust_glyph_x -1.0
macos_thicken_font 0.55

font_size 15.0

adjust_column_width 95%
adjust_line_height 95%
VincentCordobes commented 3 years ago

I have the issue on macos with Fira Code 5.2 and kitty 0.19.1 Is it a kitty issue or a font one ?

Screenshot 2020-10-06 at 22 00 30

diegoquiroz commented 3 years ago

Any updates on this? Kitty is the only emulator where this happens

Camouflager commented 3 years ago

Looks like baseline calculation in cell metrics is quite off. https://github.com/kovidgoyal/kitty/blob/6179cfc6703af1b0682fdd14829280b8a228c167/kitty/core_text.m#L340-L345 Using CoreText's method the cell height can be quite bigger than ascent + descent. I managed to solve this issue (or at least make it look much better) by doing something like this

*baseline = (unsigned int)(*cell_height - self->descent);
kovidgoyal commented 3 years ago

On Tue, Apr 20, 2021 at 06:11:24AM -0700, Camouflager wrote:

Looks like baseline calculation in cell metrics is quite off. https://github.com/kovidgoyal/kitty/blob/6179cfc6703af1b0682fdd14829280b8a228c167/kitty/core_text.m#L340-L345 Using CoreText's method the cell height can be quite bigger than ascent + descent. I managed to solve this issue (or at least make it look much better) by doing something like this

*baseline = (unsigned int)(*cell_height - self->descent);

That will just work for your particular case. As is the case with most Apple software, there is no good API to calculate this. If you have a general purpose solution that is better than the existing code, I am all ears.

Camouflager commented 3 years ago

That will just work for your particular case. As is the case with most Apple software, there is no good API to calculate this. If you have a general purpose solution that is better than the existing code, I am all ears.

Good point. I'll just post my workaround here for what it's worth

diff --git a/kitty/core_text.m b/kitty/core_text.m
index b3065f6..c5c02af 100644
--- a/kitty/core_text.m
+++ b/kitty/core_text.m
@@ -332,10 +332,7 @@
         }
     }
     *cell_width = MAX(1u, width);
-    *underline_position = (unsigned int)floor(self->ascent - self->underline_position + 0.5);
     *underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
-    *baseline = (unsigned int)self->ascent;
-    *strikethrough_position = (unsigned int)floor(*baseline * 0.65);
     *strikethrough_thickness = *underline_thickness;
     // float line_height = MAX(1, floor(self->ascent + self->descent + MAX(0, self->leading) + 0.5));
     // Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
@@ -356,6 +353,9 @@
     CGFloat line_height = origin1.y - origin2.y;
     CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);
     *cell_height = MAX(4u, (unsigned int)ceilf(line_height));
+    *baseline = (unsigned int)(*cell_height - self->descent);
+    *strikethrough_position = (unsigned int)floor(*baseline * 0.65);
+    *underline_position = (unsigned int)floor(*cell_height - self->descent - self->underline_position + 0.5);
 #undef count
 }
ctrlcctrlv commented 3 years ago

Hello friends.

I was playing around with RenderDoc this evening while working on MFEKglif, and discovered that one of its images provides a perfect way for users to understand how Kitty works.

As has been stated many times, kitty cannot draw outside the bounds of a cell. But why? Because the cells are a mesh in the form of a triangle fan. When you are looking at a Kitty window, you're not looking at a cohesive window, but actually, an array of quads making up a 3D mesh:

You see…

kitty

Your graphics card sees…

Mesh

kitty_over

Quads

grid1

Pipeline

image

As you can see from the quads, we draw one quad at a time. Here are our sprites for the frame above:

kitty_tex

You might notice some of these sprites seem to cover more than one quad, but they do not. They're ligatures, drawn in pieces. That works because they're an exact multiple of the width of one quad, and don't overflow.

So…case closed. @kovidgoyal is obviously right—to change Kitty to be able to overflow would mean a fundamental change to its very core. That's too time consuming for such a small marginal benefit like being able to overflow, so we aren't able to.

Hope this helped someone visualize kitty. I enjoyed playing with RenderDoc to bring it to you.

kovidgoyal commented 3 years ago

I finally found an API to query CoreText for the adjusted baseline position. Pushed a fix based on that. Please test. In particular, also check if the underline position is correct, I am not sure whether it should be calculated as round(float_baseline + float_offset) or round(round(float_baseline) + float_offset)

And you can have kitty output detailed debugging info on all the various types of font metrics by running it with --debug-rendering

fenetikm commented 3 years ago

I tried it out - didn't seem to fix the problem with Fira Code for me, this is what I am seeing:

image

vs (old version of Fira code)

image

Output from --debug-rendering:

Cell height calculation:
        line height from line origins: 44.000000
        line bounds: origin-y: -9.230804 height: 44.307861
        line bounds-no-leading: origin-y: -9.230804 height: 44.307861
        bounds metrics: ascent: 35.077057       line metrics: ascent: 27.692413 descent: 9.230804 leading: 0.000000
        font metrics: ascent: 27.692413 descent: 9.230804 leading: 0.000000 underline_position: -1.153846
        cell_height: 44 baseline: 35 underline_position: 36
kovidgoyal commented 3 years ago

And what metrics are printed out with --debug-rendering?

fenetikm commented 3 years ago

Not sure you saw it but I posted it above just as you wrote that comment.

Cell height calculation:
        line height from line origins: 44.000000
        line bounds: origin-y: -9.230804 height: 44.307861
        line bounds-no-leading: origin-y: -9.230804 height: 44.307861
        bounds metrics: ascent: 35.077057       line metrics: ascent: 27.692413 descent: 9.230804 leading: 0.000000
        font metrics: ascent: 27.692413 descent: 9.230804 leading: 0.000000 underline_position: -1.153846
        cell_height: 44 baseline: 35 underline_position: 36
kovidgoyal commented 3 years ago

Looks correct to me. CoreText has added seven pixels to the line height specified by the font, giving a line height of 44 pixels. And it renders the baseline at 35 pixels, whereas the font metrics would want it at 27.6 pixels from the top. So CoreText would render the baseline at ~ 80% of cell height, which is what kitty is doing in your screen shot as well.

The metrics from the font would give a line height of 37 pixels and baseline of 28 pixels or ~ 75% of cell height. I could have kitty use those metric instead, but then its rendering would not match that of CoreText, which Apple users assure me is an extremely desirable thing.

fenetikm commented 3 years ago

Riiiight - I am following you now.

I guess it might be nice to try seeing what it looks like using the font metrics or alternatively rendering the glyph in the centre (3.5px from the top) - but I'll give that a go in my own time if you can't be bothered.

Thanks for the update 👍

ctrlcctrlv commented 8 months ago

This issue leads to particularly poor display of Vietnamese text.

image

kovidgoyal commented 8 months ago

That's a different issue, there isnt vertical space in the cell for the diacritics which is causing the glyphs to be pushed down.