-
Notifications
You must be signed in to change notification settings - Fork 158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
common: render text buffers with opaque background #1631
Conversation
After a roundabout discussion[1] with wlroots devs, it's become apparent that subpixel text rendering (a.k.a. "ClearType") does not work properly when rendering over a transparent background, as labwc currently does. Basically it comes down to the fact that the color of semi-transparent pixels (which is adjusted redder or bluer to compensate for RGB subpixel alignment) depends somewhat on background color. When rendering over transparency, the text engine doesn't know the intended background color and can't adjust the pixel colors correctly. With Pango/Cairo, the end result can range from grayscale rendering (no subpixel rendering at all) to wrong/oversaturated colors (for example, bright pink pixels when rendering white text on blue background). This change solves the issue by first filling the text buffer with an opaque background color before rendering the text over it. Currently, this is easy since the background is always a solid color. It may be a little more complex (but doable) if we implement gradients in future. Note that GTK 4 (and to some degree, recent versions of Microsoft Windows) avoid this issue by disabling subpixel rendering altogether. I would much prefer that labwc NOT do this -- it results in noticeably blurrier text on non-retina LCD screens, which are still common. [1] https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3822
Nice find! I noticed the strange coloration with sub-pixel rendering (which seems worse with Vulkan), but never would have figured this was related to transparent backgrounds. |
Very nice find indeed! LGTM, didn't test. Edit:
Lets deal with that when we actually do support gradients. We might also want to auto scale the gradients based on the output they are currently rendered on. So maybe we can just render the pango text directly on the gradient buffer. Edit 2: See |
For what it's worth, most of the discussion on the wlroots issue (before Félix weighed in) ended up being irrelevant. My original theories were wrong, and the pixel/color formats themselves are fine. The issue is really just that Pango/Cairo does not behave properly (and in some cases actually produces out-of-range RGB values, which is a bug) when doing subpixel rendering over transparency. The behavior could be improved (e.g. limit the RGB values to be no greater than the alpha value -- I tried that as a post-processing step, and it helped) but the result would still be less than ideal. The subpixel rendering really needs to be done over an opaque background to work correctly. That's my understanding, anyway. |
Well it was interesting nevertheless. Even though I will likely have forgotten everything within two weeks again.
Should we add the cairo issue within the comment? Anyway, feel free to go for the rebase and merge if you are happy with the PR. You have invested way more time in debugging and testing the solution / workaround than all of us and are thus the most qualified person to judge it. |
Just tested this on my laptop, and the difference is immediately visible. I always assumed the color artifacts were caused by resampling issues with fractional scaling. |
Thanks. Fantastic work. This adds a limitation to how we composite SSD, but that's a discussion for a different day. For what it's worth, I'm increasingly thinking that that we ought to consider assembling multiple "parts" in one cairo-surface anyway. This needs to experimentation, speed-testing and a strategy. For example, I think we ought to consider just creating one surface for the whole titlebar (incl. corners). |
After a roundabout discussion[1] with wlroots devs, it's become apparent that subpixel text rendering (a.k.a. "ClearType") does not work properly when rendering over a transparent background, as labwc currently does.
Basically it comes down to the fact that the color of semi-transparent pixels (which is adjusted redder or bluer to compensate for RGB subpixel alignment) depends somewhat on background color. When rendering over transparency, the text engine doesn't know the intended background color and can't adjust the pixel colors correctly.
With Pango/Cairo, the end result can range from grayscale rendering (no subpixel rendering at all) to wrong/oversaturated colors (for example, bright pink pixels when rendering white text on blue background).
This change solves the issue by first filling the text buffer with an opaque background color before rendering the text over it. Currently, this is easy since the background is always a solid color. It may be a little more complex (but doable) if we implement gradients in future.
Note that GTK 4 (and to some degree, recent versions of Microsoft Windows) avoid this issue by disabling subpixel rendering altogether. I would much prefer that labwc NOT do this -- it results in noticeably blurrier text on non-retina LCD screens, which are still common.
[1] https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3822
Screenshots (zoom in to see detail):
White on blue,
WLR_RENDERER=vulkan
, before/after:Black on white,
WLR_RENDERER=pixman
, before/after: