Hey list,
I figured I should write about the new changes before they hit the unsuspecting
world in a future release. Here's a first draft I just wrote. Please comment.
It is supposed to go on the main news page of freetype.org (Werner? :)). I'll
also try to spread it to LWN.net, Phoronix and heise.de once it's in shape for
publication.
Stem darkening for the autohinter
=================================
FreeType's master branch has merged a new feature that users, developers and
packagers should know about. With commit
b6fd5bc06c4434a832328c4682544c436484265e, stem darkening has been implemented
in the autohinter.
[[http://postimg.org/image/id3qr94av/full/]]
Stem darkening emboldens glyphs at smaller sizes to make them more readable on
common low-DPI screens. If this sounds familiar to you, that's because Adobe's
CFF engine has been doing it since it's been contributed in 2013. You might
have noticed that OpenType/CFF fonts (commonly suffixed .otf) like GNOME3's
default UI font Cantarell appear bolder and fuzzier than other fonts. The
autohinter will do the exact same thing now.
But why would you do this if small glyphs have been fairly readable already? It
turns out that font rendering in the Linux ecosystem has been done wrong since
scalable fonts were introduced to it.
When FreeType outputs a grayscale glyph image, it really outputs a coverage map. If a pixel is completely covered by a filled-in outline, the pixel is made 100% black. If a pixel is only 50% covered, the pixel is made 50% black (read: some middle shade of gray or 50% brightness). On high-DPI screens like on smartphones and tablets, the pixels are so small that their chance of being completely covered and therefore completely black are fairly good. On the low-DPI screens most of us are sadly stuck with, the situation is different. The pixels are too large for most of the details of a glyph and shades of gray are the norm rather than the exception. All our screens have a second problem: they are not linear. 1 + 1 is not 2. Twice the value does not result in twice the brightness. When a pixel is only 50% covered, the coverage map says 50% black, and this translates to a pixel value of 128 when you use 8 bits per channel (0-255). However, this does not translate to 50%
brightness for that pixel on our sRGB and gamma 2.2 screens. Due to their non-linearity, they dwell longer in the darks and only pixel value of about 186 results in 50% brightness -- 128 ends up too dark! The net result is that the fonts on our desktops have been looking burnt-out, pixely and blotchy for 20 years or something. On high-DPI screens where smaller, fully black pixels reign supreme, this doesn't matter, but on our low-DPI screens with all the gray shades, it does. 0% and 100% brightness are the same thing in linear and non-linear space, just all the shades in-between aren't.
The correct way of rendering a glyph image on a surface is to alpha blend it
onto the surface in linear space and then apply gamma correction to translate
the linear coverage map to something that is correct for our screens. No
toolkit in the Linux ecosystem does it by default, even though Qt5 and Skia can
and will do it on other platforms. Windows and Mac OS X do it natively. This
procedure is especially important if glyphs should be subpixel-rendered (think
ClearType and Mac OS X) with as little color-fringing as possible.
[[http://postimg.org/image/3z1cvvxih/full/]]
We want to get to "Gamma 1.8, darkened". Note how it's the cleanest rendering
of all.
Back to stem darkening. Assume we render fonts correctly. Gamma correction essentially lightens fonts since
shades of grey are shifted to higher pixel values (= higher brightness) to match the original intention to
the reality of our screens. The side-effect is that glyphs that were rendered incorrectly but fairly readable
suddenly "thin out". Correctly rendered but hard-to-read text doesn't do anyone a favor. So Mac OS
X and Adobe's proprietary font rendering library implement a counter-measure: stem darkening at smaller sizes
where shades of gray dominate. By emboldening a glyph slightly in relation to its' pixel size, individual
pixels get higher coverage of filled-in outlines and are therefore "blacker". This increases
contrast and prevents "thinning out" of glyphs. Text remains readable at smaller sizes.
[[http://postimg.org/image/6vx7wxvhv/full/]]
And that is the story behind this feature.
Now, with the new autohinter, your fonts will actually render much "worse" than
before. Just like OpenType/CFF fonts. I already mentioned the reason: No toolkit in the
Linux ecosystem does linear alpha blending and gamma correction of text by default, but
stem darkening absolutely *requires* it.
I see the "new" autohinter as a call to implement and/or enable linear alpha
blending and gamma correction in all rendering libraries. Before, only .otf fonts were
darkened but those aren't that common. So most people probably never saw incorrect stem
darkening in action. With my recent push to establish the autohinter as the default in
GNOME3 and in upstream fontconfig, more people will probably be exposed to it in the near
future. I hope that maintainers of rendering libraries take note.
I plan on decoupling stem darkening from the autohinter as hinting and stem
darkening should be orthogonal. The TrueType driver should also benefit from
stem darkening. This future work, though.
I don't want this
---
Like with the CFF engine's stem darkening, there is no way to turn it off from
fontconfig. Refer to
http://freetype.org/freetype2/docs/reference/ft2-cff_driver.html#no-stem-darkening
to turn it off at run-time. You can also patch FreeType as the maintainer on
Debian did.
_______________________________________________
Freetype-devel mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/freetype-devel
.