-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Tracking issue: Improve text antialiasing #2639
Comments
I'd be keen to try using https://github.com/pop-os/cosmic-text in |
Hello from downstream MFEKglif project. Our goal is to solve this, along with #1016, #2179 and other issues related by using the Skia backend we commissioned from @lucasmerlin. We will then rasterize/shape once and store whole strings/words in the atlas, not letters. |
I will just コピペ what I wrote to Discord here as an update, now that I've read all the text layout code in egui, and all of egui_skia, and all of egui_sdl2_event… Links: #2179, https://www.unicode.org/L2/L2002/02279-muller.htm . |
I personally implemented swash driven font rendering with font hinting. |
This is great, but it is unclear what the images above are demonstrating. To my poor old eyes, the top image and the left image look clearer and more aliased than their alternatives. |
@Resonanz
In the example in my images, you can see that the “Arthur” string is sharper. |
Thanks @atynagano for explaining. Thanks also to @parasyte for the detailed explanation of this really important issue. |
We've decided to switch to Cosmic Text for text rendering, which uses Swash: |
|
This is a follow up to #2490.
Related to:
Background and rationale
To improve text legibility, font rasterization currently aligns each glyph to the pixel grid on the display. This is done in two places: First as part of text layout, the glyph cursor itself is rounded to the pixel grid (providing uniform kerning). And second during tessellation (reducing any linear filtering artifacts). Rounding in the tessellator is also important for font caching within the texture atlas, but only when the texture atlas is intended to be rasterized 1:1 with the display (more on that below).
The net effect is that glyphs are rasterized crisply (very little blurring apart from basic grayscale antialiasing performed by
ab_glyph
).There are a few drawbacks to the current design:
Proposed solutions
More than one solution exists. There isn't one that will fix all of the issues, but a combination can have great results. In all cases, the goal is to remove the pixel grid rounding in both layout and tessellation.
1. Subpixel rendering
First, we should consider subpixel rendering. This effectively triples the horizontal resolution on displays with horizontal subpixels, and nearly doubles both dimensions of resolution for displays with pentile or similar subpixel layouts. It can have exceptional results (see FreeType, ClearType, et al.)
The primary advantage of subpixel rendering is that it is not limited to text. It can easily be used on the entire GUI where everything is simply rendered at a higher resolution than the native display. This also means that subpixel rendering can be done in egui itself without deferring to a font rasterization library.
The biggest disadvantage is that it requires knowledge of subpixel layout on the physical display. And that each physical subpixel layout needs its own rendering model (though models can be shared when subpixel ordering is the only difference. E.g., RGB vs BGR).
2. Supersampling
SSAA is another technique for antialiasing where the rasterization is performed at a much higher resolution than the display, and then scaled down to fit.
While supersampling can be done on the entire frame, like subpixel rendering, it is not ideal because it can cause a loss of contrast at pixel edges. Using this technique only for the fonts also has the advantage that it limits the performance impact required by multi-sampling and also lessens the need for more texture memory. It also shares the advantage that it can be done without deferring to a font rasterization library, since it is just a matter of using the library to rasterize larger glyphs that are then rescaled to the appropriate size for display. A consequence of this is that rounding glyph positions to the pixel grid is no longer useful for font caching, since the font cache has a much higher resolution than the display anyway.
The disadvantage is that it is still not free, since it requires more texture memory for the higher resolution rasterization and more GPU bandwidth for sampling the high-resolution texture multiple times for each pixel ultimately put on the display. And without hinting, the "most important" pixels of the glyphs are not guaranteed to align with the pixel grid, resulting in some unnecessary blurring of text.
3. Font hinting
Some fonts contain metadata for the rasterizer to help sharpen the edges of glyphs in relation to the pixel grid. Hinting can also be done in an automated way with vector fonts. FreeType supports both.
An ideal implementation will improve legibility of small fonts by increasing contrast on the pixel grid without artificially distorting either the glyph shapes or the spacing between them. Hinting can be combined with subpixel rendering to improve the shapes and spacing.
The biggest disadvantage of hinting is that it acts a lot like the pixel grid rounding done per-glyph in egui. It can change the shape of glyphs, especially when rasterizing small fonts. Another disadvantage is that it must be done entirely within the font rasterization library. Hinting is not supported by
ab_glyph
: alexheretic/ab-glyph#60 (comment) The feature would either have to be contributed upstream orab_glyph
replaced with another rasterizer that supports hinting.4. Signed Distance Field rasterization
SDFs have some interesting and unique advantages over other antialiasing methods. This is kind of reimagining a vector font as a grid (field) of gaussian functions representing the distance from a pixel on the display to the edge of the glyph. As a result, it has properties of both the original vector font and the raster image.
The biggest disadvantage is that it has to be done in the font rasterization library.
Some example crates that use this technique are
sdf_glyph_renderer
andfontsdf
. Outside of Rust, there is GLyphy written in C++ and GLES2, andsdf-glyph-foundry
written in C++ for mapbox.5. Alternative font rasterizing libraries
There are a few to choose from. egui currently uses
ab_glyph
.swash
supports subpixel rendering and various hinting strategies. Also supports color emoji (see Color Emoji support #2551)swash
is that it is used in thelapce
editor, and it has excellent font rendering.pathfinder
has been a work in progress for a very long time and supports subpixel rendering and "slight hinting".I also evaluated
fontdue
, which appears to have some of the necessary pieces for subpixel rendering but not hinting (that I could find, anyway).The text was updated successfully, but these errors were encountered: