-
Notifications
You must be signed in to change notification settings - Fork 1.9k
More even text kerning #7431
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
More even text kerning #7431
Conversation
Preview available at https://egui-pr-preview.github.io/pr/7431-fonts-cleanup |
a0e0232
to
aca06d0
Compare
Looks like the "42 years" button in the Code Example window is a pixel shorter, which is causing tests to fail. Not sure if that's a big deal or not. |
Let's make sure we test this with two different viewports on screens with different pixels_per_point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
I was curious if this would have a noticable effect on performance, and while cached performance indeed improves by 6% (nice!) uncached performance is now 3x slower 😅:

Profiling the benchmark shows that now way more time is spent calculating the ascent, so that seems to be a expensive operation:
So it probably makes sense to precalculate / cache the ascent values (like it was done previously).
Also gave this a try in rerun, didn't notice anything major but interestingly the help view text shifted down a row of pixels: Screen.Recording.2025-08-08.at.13.21.56.movI guess it's the same as the "42 years" in the egui demos, a rounding error. Also to me it looks more aligned now, so yay? |
The new code in this PR uses a lot of What we would like to do it is to only run But that brings us back to having a scale baked into The best place to fix this is probably deep down in |
We never need to clone it, and none of its methods took `self` as mutable, meaning it wasn't making use of the semantic difference between the two. This API is about to get reworked, and simplifying it is a first step.
Even testing this out *with* font fallback, which seems to be its intended purpose, this does exactly the same thing as y_offset_factor. It's likely that some subsequent change (perhaps emilk#2724) removed the code path that made it function differently.
By making `Font` a view type and indexing by font ID, we can avoid wrapping `FontImpl` and `TextureAtlas` in an `Arc<Mutex<...>>`.
2c3a56f
to
4325c8f
Compare
Not sure *what* I replaced this with, but it's unnecessary now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Performance looks good now, and as far as I can tell we haven't regressed on #382
…but the text sizes (or at least letter spacing) has changed a lot!
Is this expected?
How sure are we that the new sizes/spacing is more correct (e.g. more in line with what you would see in a browser)?
Before

After

I agree about the kerning, but honestly, to me the blur looks terrible, at least in these particular screenshots! I wouldn't easily say it's worth it (not using a HiDPI display). Especially those "Click me!" buttons look really bad. For me this seems to thwart the recent changes that improved text rendering so much. This is probably very subjective though, so if nobody agrees with me, it's probably fine :-P |
@vkahl you are right about the blur - fortunately this was fixed by bumping the text size from 12.5 to an even 13: |
Contains several cleanups in the font loading and rendering code. Some of them were ported from the Parley PR, some are new. A lot of them center around passing in state (like font size and DPI) instead of storing it.
FontsImpl
in anArc<Mutex<..>>
. We never need to clone it, and its only purpose seems to be allowing theFonts
type to make use of caching while still using a non-mutable&self
as a receiver. That doesn't seem to pull its own weight. We do now have to add actx.fonts_mut
method though.FontTweak::baseline_offset_factor
property. I cannot construct any scenario where it behaves differently thany_offset_factor
.Font
type non-scaled (independent of font size and pixels_per_point). Most of its methods don't depend on its scale, and for those that do, we can just pass the scale in. This reduces the number of fonts we need to cache at once.FontImpl
andTextureAtlas
in anArc<Mutex<..>>
as well. We do this by mapping each font face to an ID, and storing eachFontImpl
by ID. This means that types which reference a font face can just store the ID instead of anArc<FontImpl>
. We also now just pass in theTextureAtlas
to all methods that render into it. To facilitate the same API as we had previously,Font
is now a view type which stores references to the "fonts by ID" map, font family, and texture atlas. This means we can only materialize oneFont
at a time, but that should be okay.pixels_per_point
inFonts
andFontsImpl
. Instead, pass it into all methods that use it.ctx.fonts
(and the newctx.fonts_mut
) return a new view type (FontsView
) which does store the context's currentpixels_per_point
. This lets us get rid of the hack where we have to recreate the font atlas every frame if we have mixed-DPI viewports.