Skip to content
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

Dark text on light background is hard to read on non-HiDPI displays #2254

Open
2 tasks done
CryZe opened this issue Feb 15, 2024 · 9 comments
Open
2 tasks done

Dark text on light background is hard to read on non-HiDPI displays #2254

CryZe opened this issue Feb 15, 2024 · 9 comments
Labels
bug Something isn't working help wanted Extra attention is needed question Further information is requested rendering text wgpu
Milestone

Comments

@CryZe
Copy link

CryZe commented Feb 15, 2024

Is there an existing issue for this?

  • I have searched the existing issues.

Is this issue related to iced?

  • My hardware is compatible and my graphics drivers are up-to-date.

What happened?

I've been checking out iced because 0.12 came out today. But immediately the text stood out as very wrongly rendered. Initially I thought the hinting just isn't very good, but comparing Paint (on the top) to Iced (at the bottom), the problem is much rather an issue with the "apparent font weight":
image

This immediately stood out to me as an issue with sRGB linear vs. gamma corrected, so I pulled out RenderDoc where at first glance the textures seem to use the correct color space. Extracting the glyph cache by itself, we actually get a proper rendering of the glyphs, confirming that up until this point everything is done correctly:
image

This strongly implied that the shader is causing the problems, and it probably needs to do a sRGB linear to gamma corrected conversion, and lo and behold, the text is now properly rendered:
image

My quick fix amounted to the following in glyphon:

fn linear_to_srgb(x: f32) -> f32 {
    if x <= 0.00031308 {
        return 12.92 * x;
    } else {
        return 1.055 * pow(x,(1.0 / 2.4) ) - 0.055;
    }
}
return vec4<f32>(in_frag.color.rgb, in_frag.color.a * linear_to_srgb(textureSampleLevel(mask_atlas_texture, atlas_sampler, in_frag.uv, 0.0).x));

Almost certainly too hacky (although the same hack already exists), but it should give a good starting point for investigation where the color space mess up happens and what the correct fix may be.

I believe the main problem here is that what iced and glyphon are doing is technically the correct color space handling, but no other application interprets the alpha channel of glyphs this way, so while technically being more correct, it ends up looking very washed out and inconsistent with other applications.

The tiny-skia backend does NOT have this problem, solidifying that it's at least a bug in one of the two backends.

image

Interestingly both Paint and tiny-skia are still clearer, but that may just be the hacky sRGB conversion function.

What is the expected behavior?

See above

Version

crates.io release

Operating System

Windows

Do you have any log output?

No response

@CryZe CryZe added the bug Something isn't working label Feb 15, 2024
@hecrj
Copy link
Member

hecrj commented Feb 15, 2024

I believe the main problem here is that what iced and glyphon are doing is technically the correct color space handling, but no other application interprets the alpha channel of glyphs this way, so while technically being more correct, it ends up looking very washed out and inconsistent with other applications.

Indeed! This is not just a color space issue, but also an alpha blending issue.

Most GUI toolkits operate (e.g. perform alpha blending) on sRGB colors while assuming they are linear. See Web color is still broken.

iced tries to do the correct thing by default. If you want "broken colors", you can enable the web-colors feature.

web-colors disabled

image

web-colors enabled

image

@CryZe
Copy link
Author

CryZe commented Feb 15, 2024

I'm well aware of those color space issues and I actually really like that you even have a toggle for it. And in fact I did mention that what you do is for sure much more correct than what other applications are doing. I think the question still somewhat remains if it should affect the font rendering to this (negative) degree. Like I believe even without "web colors" it should probably behave this way for blending the fonts.

I think the reason why the wrongly blended text looks better is because for low resolutions (i.e. normally sized text on non HiDPI screens), the higher contrast makes the glyphs look a lot more legible than doing the correct blending.

@hecrj
Copy link
Member

hecrj commented Feb 15, 2024

Like I believe even without "web colors" it should probably behave this way for blending the fonts.

I'm happy to consider our options here, as long as we know what we are doing.

Gamma correcting an alpha channel seems quite strange. It does improve the final alpha blending result, but it feels like we are just smashing things. How is brighter text on a dark background affected? Is there any previous work on this?

In order to produce the web-colors result only for text, we would not be able to rely on hardware color conversions. We would have to declare every texture as linear RGB and manually do all of the sRGB conversions in the shaders, except for the text one. Or maybe declare a dedicated render pass for every text layer... equally undesirable.

@hecrj hecrj changed the title Alpha rendering of text is messed up Dark text on light background is hard to read on non-HiDPI displays Feb 15, 2024
@hecrj hecrj added question Further information is requested help wanted Extra attention is needed wgpu bug Something isn't working and removed bug Something isn't working labels Feb 15, 2024
@hecrj
Copy link
Member

hecrj commented Feb 15, 2024

We could also consider enabling the web-colors feature by default, since it's in the end what will be expected from most users.

It is quite unfortunate that we have to adopt a broken rendering technique just because it's become the norm, though.

@TheDecryptor
Copy link

TheDecryptor commented Feb 16, 2024

Is there an option of doing something like stem darkening? Freetype experimented with it (as explained here in an article from 8 years ago) as a way to offset the "washed-out" look.

@hecrj
Copy link
Member

hecrj commented Feb 16, 2024

@TheDecryptor Yes! I remember that paper! I think it would certainly be an interesting feature for glyphon when using ColorMode::Accurate.

cc @grovesNL

@hecrj hecrj added this to the 1.0 milestone Feb 16, 2024
@grovesNL
Copy link

Yeah that could be useful for sure, I'd like to understand the state-of-the-art for this better before we decide on stem darkening though. If I remember correctly some approaches for this problem don't work well with display scaling (especially macOS versions in the last decade or so) but don't have a reference handy right now.

@yump
Copy link

yump commented Feb 16, 2024

IANA text rendering expert, but I remember someone in Gnome saying RGBA blending can't do the right thing with subpixel AA on both dark and light backgrounds, and per-channel opacity is needed.

Freetype's Harmony renderer has an interesting first-principles approach to AA, where subpixel rendering is seen as a correction for hardware's misaligned color planes, instead of some kind of "triple resolution" hack. It could be implemented directly at some performance cost by rendering color channels separately and swizzling at the end. That handles vertical and triangular subpixel arrangements just as easily as horizontal, although I don't think it's quite right for RGBW which could have color-dependent offsets.

It is quite unfortunate that we have to adopt a broken rendering technique just because it's become the norm, though.

Perhaps text and graphics should be treated separately? The font designer was probably looking dark-on-light output rendered with that broken technique when tuning the small sizes, so in some sense it is ultimately correct. The text renderer could attempt to adapt the appearance of incorrectly-blended dark-on-light to whatever the actual output target is.

And then color emojis are a whole 'nother kettle of fish.

@hecrj
Copy link
Member

hecrj commented Feb 16, 2024

Perhaps text and graphics should be treated separately? The font designer was probably looking dark-on-light output rendered with that broken technique when tuning the small sizes, so in some sense it is ultimately correct. The text renderer could attempt to adapt the appearance of incorrectly-blended dark-on-light to whatever the actual output target is.

Yes. As I said in my previous comment, we could do it but it seems it would cost us performance and composability when it comes to our rendering primitives. But I'm not a graphics wizard, so maybe there is a way!

And honestly, adding a bunch of complexity to our renderer architecture so we can basically accomodate a broken rendering technique sounds quite painful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed question Further information is requested rendering text wgpu
Projects
None yet
Development

No branches or pull requests

5 participants