kovidgoyal / kitty

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

`text_composition_strategy legacy` is noticeably worse than pre-0.28 rendering #6209

Closed sharnoff closed 1 year ago

sharnoff commented 1 year ago

Describe the bug

Relating to Kitty 0.28 text_composition_strategy legacy:

  1. it's always subtly different from actual pre-0.28 rendering, and
  2. it looks much worse with transparent windows in front of light backgrounds.

To Reproduce Steps to reproduce the behavior:

  1. Use config as shown below
  2. Update to kitty 0.28
  3. Observe text (as shown in screenshots)

Screenshots

Note: Screenshots were taken in a kitty instance with full transparency — the background color is exclusively from blur (via my compositor) over my desktop background.

Post-0.28

Screenshot of the funky rendering

Screenshot of rendering on a darker background looking a-ok

Pre-0.28

Screenshot of text looking a-ok

Screenshot of rendering on a darker background looking a-ok

Note: With the darker background, there is also a slight change that post-0.28 rendering is slightly thicker - should hopefully be easy enough to see if you compare the two.

Environment details

Couldn't get Ctrl+Shift+F6 working, for some reason. Pasting the relevant pieces of my config file. kitty -v outputs kitty 0.28.1 created by Kovid Goyal. Happy to provide more details upon request.

### Fonts ###
font_family Ubuntu Mono
font_size   20.0

disable_ligatures always
text_composition_strategy legacy

### Color scheme ###
foreground #eaeaea
background #263238

# Terminal colors
#
# These are given first with the normal variety, and then with the
# bold variety.
#
# Black
color0 #000000
color8 #666666
# Red
color1 #d54e53
color9 #ff3334
# Green
color2  #b9ca4a
color10 #9ec400
# Yellow
color3  #e6c547
color11 #e6c547
# Blue
color4  #7aa6da
color12 #7aa6da
# Magenta
color5  #c397d8
color13 #b77ee0
# Cyan
color6  #70c0ba
color14 #54ced6
# White
color7 #eaeaea
color15 #ffffff

### Advanced options ###
background_opacity 0.0

# note: lines unrelated to rendering were omitted.

I think the font color in the screenshots is color4 (normal blue), but not 100% sure.

kovidgoyal commented 1 year ago

@m4rw3r ping.

dmitriy-geels commented 1 year ago

... rendering is slightly thicker ...

In my case, it's not just slightly: Fira Code symbols look bold, bold became indistinguishable, Fira Code Light looks like slightly bolder than regular version used to.

UPD: rendering looks fine in tabs, just as it's supposed to; same for selected text

Examples:

m4rw3r commented 1 year ago

@sharnoff The slight increase in font thickness is somewhat expected even with the legacy setting, since it simulates based on luminance and not full RGB. Not sure how to best "fix" it. But that bright-on-bright color-fringing is definitely wrong, I'll take a look at it.

@dmitriy-geels Can you provide a list of the relevant settings for the screenshots you provided? The light on dark example looks about right for a match to MacOS Terminal, but that selection looks off.

m4rw3r commented 1 year ago

Small update: Managed to reproduce the color-fringing (using #81a2be on top of #4a91b8), but the fringing does not seem to depend on any of the options besides foreground-color and transparency (and the background image/color from the compositor). So this is a case of gamma-incorrect blending in the compositor it seems. I managed to reproduce it using wlroots/sway.

A quick and dirty try with applying the sRGB curve a second time to the alpha "solves" it, partially: image

There are a few issues here:

I have no idea if there is a way to tell the compositor that we want gamma-correct blending, or if everything is blended in linear space.

@sharnoff Which compositor and window-manager are you using?

sharnoff commented 1 year ago

So this is a case of gamma-incorrect blending in the compositor it seems

Yikes. I don't have the background knowledge to tell either way; is it possible that incorrect is the norm?

Which compositor and window-manager are you using?

i3 + picom

We don't have a way of knowing if the compositor will perform gamma-incorrect blending, in which case the adjusted result will look bad.

[ ... ]

I have no idea if there is a way to tell the compositor that we want gamma-correct blending, or if everything is blended in linear space.

If it were me, I'd just add a config setting for this. Discoverability may be tricky, but at least it's guaranteed to work. Just my 2 cents.

I'm not sure if it is just my imagination or if the "100% transparency, inverse gamma" looks a bit bolder than the "no transparency, solid background"

Not your imagination. The "100% transparency inverse gamma" has slightly different edge colors. It's most apparent on the 'r' in both:

no transparency, solid background full transparency, inverse gamma
Screenshot Screenshot

Among other differences, the left edge of the 'r' is '#5b95b9' on the left, but '#6499ba' on the right.

kovidgoyal commented 1 year ago

@m4rw3r I doubt anything on Linux does gamma correct blending. Though I guess one should test the GNOME/KDE Wayland compositors as well.

As for knowing if its the final pass, checking the values of the various defines should do the trick. SIMPLE being defined always means its the final pass. Other wise when FOREGROUND is defined its the final pass.

m4rw3r commented 1 year ago

GNOME on Wayland has this issue: Screenshot from 2023-04-26 08-48-03

And MacOS seems to have the same problem, not sure if there is some kind of attribute we can set to indicate that we want gamma-correct blending:

image

wlroots has an issue for gamma incorrect blending of transparency, does not seem to be straightforward to solve in the compositor without GL extensions: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1703 (previously https://github.com/swaywm/wlroots/issues/1703 )

So it seems like a pretty safe bet that all the popular compositors perform gamma-incorrect blending of transparency.

To properly compensate for this without exaggerating the shapes we need to know the background color/luminance to avoid darker text looking too bold. We can possibly make an assumption that it is 50% grayscale but that can still cause color fringing:

image

Can possibly also be caused by the sRGB-approximation not being close enough for darker colors. I will have to test this a bit.

kovidgoyal commented 1 year ago

I dont think there is anyway for us to know the background color. Only the compositor can know that. The only correct way to fix this is have the compositor do gamma correct blending. However since in the real world that is not likely to happen, we are left with the option of picking some kludge or the other to make the common cases work well.

m4rw3r commented 1 year ago

I dont think there is anyway for us to know the background color. Only the compositor can know that.

That is what I figured too which is why I tried the 50% gray assumption, but that (unsurprisingly) causes minor color-fringing and jagged edges depending on the background.

I guess the priority here is to avoid color-fringing over any of the other potential issues (bolder text, incorrect transparent colors, background_opacity not being linear)? Because I can't seem to find any solution other than making an adjustment to the final value of the alpha-channel.

We should probably use a better function for the srgb-approximation too, should I add that as a separate PR?

kovidgoyal commented 1 year ago

On Thu, Apr 27, 2023 at 02:55:02AM -0700, Martin Wernstål wrote:

I dont think there is anyway for us to know the background color. Only the compositor can know that.

That is what I figured too which is why I tried the 50% gray assumption, but that (unsurprisingly) causes minor color-fringing and jagged edges depending on the background.

I guess the priority here is to avoid color-fringing over any of the other potential issues (bolder text, incorrect transparent colors, background_opacity not being linear)? Because I can't seem to find any solution other than making an adjustment to the final value of the alpha-channel.

Yes, color fringing will bother many more people than the rest of the issues. And I agree there isnt reallya good solution absent a way to tell compositors to linear blend.

We should probably use a better function for the srgb-approximation too, should I add that as a separate PR?

No need, a single PR is fine.

kovidgoyal commented 1 year ago

I improved @m4rw3r fix by only applying it to pixels that have actual text content. This means that the fix no longer makes background_opacity non-linear so its behavior is unchanged. Please test.

https://github.com/kovidgoyal/kitty/commit/e1ce6d08e03ca7ce7d4b2598835ee40f0991ec88