[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[ft-devel] Writing about the new stem darkening autohinter
From: |
Nikolaus Waxweiler |
Subject: |
[ft-devel] Writing about the new stem darkening autohinter |
Date: |
Fri, 6 Nov 2015 21:45:28 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 |
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.
- [ft-devel] Writing about the new stem darkening autohinter,
Nikolaus Waxweiler <=