Thanks! :)
I've attached some minor additions for the documentation (thanks for
formatting my comments, I didn't find a boxy-comments plugin for vim).
And the third revision of the news post :) Comments welcome. Maybe I'll
make comparison screenshots for the new filter. Maybe when I stop being
lazy.
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index c0e5112..d224ec9 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3089,7 +3089,7 @@ FT_BEGIN_HEADER
/* gives equal weight to the three color primaries and does not */
/* exceed a sum of 0x100, see section @lcd_filtering. Then the */
/* only difference to gray linear blending is that subpixel-rendered */
- /* linear blending is done 3~times per pixel. */
+ /* linear blending is done 3~times per pixel: red foreground subpixel to red background subpixel and so on for green and blue. */
/* */
/* <InOut> */
/* slot :: A handle to the glyph slot containing the image to */
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 91facf9..b0da6f3 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -109,7 +109,7 @@ FT_BEGIN_HEADER
* one color channel. That is, red alpha blends the red channel of the
* text color with the red channel of the background pixel. The
* distribution of density values by the color-balanced filter assumes
- * alpha blending is done in linear space; only then color artifacts
+ * alpha blending is done in linear space; only then will color artifacts
* cancel out.
*/
FreeType 2.6.2 ships with three interesting details for users and developers of
rendering libraries that deal with text.
The default LCD filter for subpixel rendering has been changed
--------------------------------------------------------------
When you look at subpixel-rendered text, no matter if it's on some kind of
Unix, Windows or Mac OS X, you might notice that it's slightly colored. Using
subpixel rendering on LCD panels is a trade-off, you get three times higher
resolution in the direction of the pixel-substripe (usually horizontal RGB) in
exchange for color artifacts. That's why it's necessary to filter a
subpixel-rendered glyph to reduce those color artifacts, or color-fringing,
before putting it somewhere on the screen. The filter distributes the values of
a subpixel to it's neighbors, sacrificing some of that higher resolution and
making the resulting glyph image blurrier, but the positioning improvement
remains! The ideal filter for you depends on your screen (gamma curves!), the
capabilities of the used rendering system (linear alpha blending and gamma
correction!!!), your vision and your taste, probably in that order.
A filter should have two properties: it should be normalized, meaning the
values used in the filter should sum up to a figurative 1 (here: 0x100 or 256)
and it should be color-balanced, meaning that values for one subpixel are
equally distributed to all other subpixels of a pixel to drastically reduce
color-fringes.
Previously, FreeType's default LCD filter was neither normalized, nor
color-balanced. That was a deliberate choice because there is still no
rendering system on *nixes that does linear alpha blending and gamma correction
by default to render glyphs correctly. Going above a filter sum of 1 increased
contrast somewhat at the expense of slight distortions and increased
color-fringing, so this can be seen as a hack. You might have noticed that
thumbnails in various places on your computer that show text could be quite
colorful. Now you know why.
The new default filter is both normalized and color-balanced. It is indeed ever
so slightly blurrier than the previous default one, but also lacks its'
harshness and is less color-happy. The blurriness also means higher tolerance
for non-ideal gamma of screens (viewing angles!) and rendering sytems without
linear alpha blending. Note that color-fringing can only be really minimized
when the rendering system will do linear alpha blending of text.
The "light" filter that has accompanied the default one for so long stays
unchanged: it already is normalized and color-balanced. It is sharper than the
default one but less tolerant of uncalibrated screens and rendering systems
without linear alpha blending, producing more color-fringes.
(S)light hinting will invoke the native hinter if possible
----------------------------------------------------------
In the past, setting "slight" hinting via fontconfig or configuration GUIs
meant that native hints within a font were ignored and FreeType's autohinter
would analyze the font on the fly and automatically do what the font designer
would have to do at least semi-manually. Technically, the autohinter set to
(s)light snaps glyphs to the pixel grid only vertically, just like Microsoft's
DirectWrite/ClearType and Adobe's proprietary font engine. The result is a
compromise between design fidelity and sharpness that preserves inter-glyph
spacing, something very important for horizontal text like what you're reading
right now. The sharpness has usually been enhanced with "subpixel rendering"
(ClearType on Windows), exploiting the physical properties of modern but
low-resolution LCD panels.
This worked out well so far, Ubuntu has been using this setting for every font
for years now. Werner Lemberg added support for more and more scripts and even
spun off the code into ttfautohint, to help font designers ease the pain of
manual hinting.
This also meant that the native hinting machinery of the font drivers went
unused. Historically, this decision was sound because the native hinting
mechanics for Postscript (.pfa, .pfb), TrueType (.ttf) and OpenType/CFF (.otf)
were.. subpar for the longest time. The Postscript hinter still is, but with
Adobe's contributed and high-quality OpenType/CFF engine and recent advances of
the TrueType driver towards full ClearType support, things have changed.
Setting "slight" hinting usually leads to FT_LOAD_TARGET_LIGHT. This mode
implied the autohinter before and has now been changed to mean "Use native
vertical-grid-only-snapping if driver and font supports it and
vertical-grid-only autohinter otherwise". Right now, only the OpenType/CFF
driver is supported. In the future, this will hopefully include the TrueType
engine once full support for ClearType arrives.
This decision was driven by my personal whim, I wanted native
vertical-grid-fitting if the font driver and font support it and the autohinter
otherwise. I assume that native hints are made more carefully and take the
(autohinting) guesswork out of the process. Instead of introducing per-format
configuration in fontconfig and fighting GTK/GNOME that only support a single
global hinting setting, it was found to make more sense to change the
definition of light hinting in FreeType.
I also hope this change will make it easier for the non-Windows-and-Apple
ecosystem to switch over to slight hinting as the default. Current full/medium
native hinting, as is the default, tends to bring out the worst in many, many
fonts that haven't seen the same insane dedication to on-screen display and
hinting as e.g. the popular Microsoft fonts. And since ClearType is still not
fully supported, you usually get a very poor default experience. Slight gives a
much better one, as Ubuntu has proven over the years.
Stem darkening for the autohinter (disabled by default), also disabling stem
darkening for the OpenType/CFF driver
-------------------------------------------------------
[[freetype-autohinter-stem-darkening-demo1.png]]
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 GNOME 3's
default UI font Cantarell appear bolder and fuzzier than other fonts, at least
until this release. The autohinter can do the exact same thing now, it's just
disabled by default.
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. Text must be rendered with linear alpha
blending and gamma correction, which no toolkit or rendering library do by
default on X11, even though Qt5 and Skia (Google Chrome) can do it.
Background
---
First, to understand why they are required, you must understand that when
FreeType outputs a grayscale glyph image, it really outputs a coverage bitmap.
If a pixel is completely covered by a filled-in outline, the pixel is made 100%
black (0% brightness or.. simply black). If a pixel is only 50% covered, the
pixel is made 50% black (50% brightness or a middle shade of gray) and 0%
covered means 0% black (100% brightness or white). 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.
This is relevant because 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 a pixel value of about 186 results in 50% brightness --
128 ends up too dark on both bright and dark backgrounds. The net result is
that dark text looks burnt-out, pixely and blotchy on bright background, bright
text too frail on dark backgrounds and colored text (e.g. red) on colored
background (e.g. green) seems to have dark halos or "dirt" around it. The
situation is especially ugly for diagonal stems like in 'w' where the quality
of FreeType's anti-aliasing depends on the correct display of grays. 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 things 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[1]. 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
(ClearType and Mac OS X!) with as little color-fringing as possible[2].
[[BlendingExamples.png]]
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 gray 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 engine 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.
[[freetype-autohinter-stem-darkening-demo2.png]]
And that is the story behind this feature.
It is disabled by default because no library supports linear alpha blending and
gamma correction out of the box. Existing libraries will get the same glyphs
they have always gotten. Qt5 actually had gamma correction enabled for a short
while until someone complained that text was too light and unlike rendering in
other toolkits, so the maintainers disabled it for the XCB-backend[2]. Skia
(Chrome) can do gamma-correction, but turns it off for X11. I see the this
feature as a technology preview for playing around with until we get stem
darkening generic within FreeType. The plan is to provide it for all font
drivers and make it toggable per FT_Library just like FT_Library_SetLcdFilter.
Libraries that support linear alpha blending and gamma correction can then just
flip the switch and get appropriate glyphs no matter the font.
A notable side-effect of disabling all stem darkening by default is that
natively hinted .otf fonts will render remarkably similar to the autohinter and
are no longer heavy and fuzzy. Slight hinting will result in consistent font
rendering.
[1]: This process can cost performance. There is an approximation that does not
need to know about the background color. See https://bel.fi/alankila/lcd/ and
https://bel.fi/alankila/lcd/alpcor.html for details. There is a
proof-of-concept pixman hack for cairo.
[2]: http://lists.nongnu.org/archive/html/freetype-devel/2015-11/msg00020.html
[3]: https://bugreports.qt.io/browse/QTBUG-41590
_______________________________________________
Freetype-devel mailing list
Freetype-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/freetype-devel