<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type"
content="text/css">
<meta http-equiv="Content-Script-Type"
content="text/javascript">
<meta name="description"
content="FreeType Documentation">
<link rel="icon"
href="image/favicon_-90.ico">
<link rel="shortcut icon"
href="image/favicon_-90.ico">
<link rel="stylesheet"
type="text/css"
href="css/freetype2_-90.css">
<script type="text/javascript"
src="../../js/jquery-1.11.0.min.js">
</script>
<script type="text/javascript"
src="../../js/jquery.ba-resize.min.js">
</script>
<script type="text/javascript"
src="../../js/freetype2.js">
</script>
<title>On slight hinting, proper text rendering, stem darkening and
LCD filters</title>
</head>
<body>
<div id="top"
class="bar">
<h1><a href="http://freetype.org/index.html">FreeType</a> LCD Support</h1>
</div>
<div id="wrapper">
<div class="colmask leftmenu">
<div class="colright">
<div class="col1wrap">
<div class="col1">
<!-- ************************************************** -->
<div id="slight-hinting">
<h2>On Slight Hinting, Proper Text Rendering, Stem Darkening
and LCD Filters</h2>
<div class="date">2015-11-30, contributed by Nikolaus
Waxweiler (with corrections from Graham Asher), updated
2015-12-08</div>
<p><em>This article was originally written for the 2.6.2
release of FreeType and explains the technical
background of several features. The information was
deemed useful enough to be added to the documentation
and has therefore been retitled.</em></p>
<p>FreeType 2.6.2 ships with three interesting details for
users and developers of rendering libraries that deal with
text.</p>
<ul>
<li>
<a href="#slight-hinting-invokes-the-native-hinter-if-possible">(S)light
hinting invokes the native hinter if possible</a>
</li>
<li>
<a href="#experimental-stem-darkening-for-the-auto-hinter">Experimental:
Stem darkening for the auto-hinter</a>
<ul>
<li><a href="#background">Background</a></li>
<li><a href="#back-to-stem-darkening">Back to stem
darkening</a></li>
</ul>
</li>
<li>
<a href="#disabled-stem-darkening-for-the-autohinter-and-adobes-cff-otf-engine">Disabled
stem darkening for the autohinter and Adobe’s CFF
(<code>.otf</code>) engine</a>
</li>
<li><a href="#the-default-lcd-filter-for-subpixel-rendering-has-been-changed">The
default LCD filter for subpixel rendering has been
changed</a>
</li>
</ul>
<h3 id="slight-hinting-invokes-the-native-hinter-if-possible">(S)light
hinting invokes the native hinter if possible</h3>
<p>In the past, setting ‘slight’ hinting via FontConfig or
configuration GUIs meant that native hints within a font
were ignored; FreeType’s auto-hinter would analyze the
font on the fly and automatically do what the font
designer would have to do at least semi-manually.
Technically, the auto-hinter set to (s)light snaps glyphs
to the pixel grid only vertically, just like Adobe’s
proprietary font engine and in a certain way also
Microsoft’s ClearType/DirectWrite. The result is a
compromise between design fidelity and sharpness that
preserves inter-glyph spacing, something very important
for horizontal text such as what you are 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.</p>
<p>This worked out well so far, Ubuntu has been using this
setting for every font for years now. Werner Lemberg is
adding support for more and more scripts and has also spun
off the code
into <a href="http://www.freetype.org/ttfautohint/">ttfautohint</a>,
to help font designers ease the pain of manual
hinting.</p>
<p>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
(<code>.pfa</code>, <code>.pfb</code>), TrueType
(<code>.ttf</code>) and OpenType/CFF (<code>.otf</code>)
were subpar for the longest time. The PostScript hinter
still is, but with Adobe’s high-quality OpenType/CFF
engine contributed to FreeType and recent advances of the
TrueType driver towards full ClearType support, things
have changed.</p>
<p>Setting ‘slight’ hinting usually leads
to <code>FT_LOAD_TARGET_LIGHT</code>. This mode implied
the auto-hinter before and has now been changed to mean
“Use native vertical-grid-only-snapping if driver and font
supports it and vertical-grid-only auto-hinter 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.
Technically, ClearType fonts can and will snap to the
vertical <em>and</em> the horizontal
grid <a href="http://www.beatstamm.com/typography/RTRCh4.htm#Sec12">depending
on several details</a>, but the net result is going in the
direction we want.</p>
<p>This decision was driven by my personal whim; I wanted
native vertical grid-fitting if the font driver and font
supports it, and the auto-hinter otherwise. I assume that
native hints are made more carefully and take the
(auto-hinting) guesswork out of the process. Instead of
introducing per-format configuration in FontConfig and
fighting <a href="http://www.gtk.org/">GTK</a>/<a href="https://www.gnome.org/">GNOME</a>
that only support a single global hinting setting, it was
found to make more sense to change the definition of light
hinting in FreeType.</p>
<p>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 many
popular Microsoft fonts, for example. And since ClearType
is still not fully supported, you usually get a very poor
default experience. Slight hinting gives a much better
one, as Ubuntu has proven over the years.</p>
<h3 id="experimental-stem-darkening-for-the-auto-hinter">Experimental:
Stem darkening for the auto-hinter</h3>
<p><a href="image/freetype-262-autohinter-stem-darkening-demo1.png">
<img src="image/freetype-262-autohinter-stem-darkening-demo1-thumbnail.png"
alt="Demonstration and comparison of the
emboldening autohinter."></a></p>
<p>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 was contributed in 2013. You
might have noticed that OpenType/CFF fonts (commonly
suffixed <code>.otf</code>) like GNOME 3’s default UI
font <a href="https://en.wikipedia.org/wiki/Cantarell_%28typeface%29">Cantarell</a>
appear bolder and fuzzier than other fonts, at least until
this release. The auto-hinter can do the exact same thing
now, it is just disabled by default.</p>
<p>But why would you do this if small glyphs are already
fairly readable? It turns out that font rendering in the
Linux ecosystem has been 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 does by default on
<a href="http://www.x.org/">X11</a>, even
though <a href="http://www.qt.io/">Qt5</a>
and <a href="https://skia.org/">Skia</a> (as used by
Google Chrome and other browsers) can do it.</p>
<h4 id="background">Background</h4>
<p>First, to understand why they are required, you must know
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, which is 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 the chance of being completely
covered and therefore completely black is fairly good. On
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.</p>
<p>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 on colored background (for example, red on
green) seems to have dark halos or ‘dirt’ around it. The
situation is especially ugly for diagonal stems like in
glyph ‘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 are not.</p>
<p>The correct way of rendering a glyph image on a surface
is
to <a href="https://en.wikipedia.org/wiki/Alpha_compositing">alpha
blend</a> it onto the surface in linear space and then
apply <a href="https://en.wikipedia.org/wiki/Gamma_correction">gamma
correction</a> to translate the linear coverage map to
something that is correct for our screens.<sup>1</sup> 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) <a href="http://lists.nongnu.org/archive/html/freetype-devel/2015-11/msg00020.html">with
as few color fringes as possible</a>.</p>
<p><sup>1</sup> This process can cost performance. There is
an approximation that does not need to know about the
background color.
See <a href="https://bel.fi/alankila/lcd/">https://bel.fi/alankila/lcd/</a>
and <a href="https://bel.fi/alankila/lcd/alpcor.html">https://bel.fi/alankila/lcd/alpcor.html</a>
for details. There is a proof-of-concept pixman hack for
cairo.</p>
<h4 id="back-to-stem-darkening">Back to stem darkening</h4>
<p>Assume we render fonts correctly. Gamma correction
essentially lightens fonts since shades of gray are
shifted to higher pixel values (corresponding to 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.</p>
<p><a href="image/BlendingExamples.png">
<img src="image/BlendingExamples-thumbnail.png"
alt="Comparison of different ways of
blending."></a></p>
<p>“Gamma 1.0” shows what happens when you take a grayscale
coverage bitmap from FreeType and blend it onto a surface
in linear space. Black-on-white is heavier than
white-on-black and red-on-green has dark halos or dirt
around it. Note that this picture is unrealistic in the
sense that no rendering system on X11 does linear alpha
blending, so imagine something worse. “Gamma 1.8” is the
result of linear alpha blending and gamma correction. It
is much better, but text thins out, making it harder to
read. Adding stem darkening gets us to “Gamma 1.8,
darkened”. Note how it is the cleanest rendering of all.
“Gamma 1.0, darkened”, meaning linear alpha blending
without gamma correction but with stem darkening,
exaggerates the effects of “Gamma 1.0”. Stem darkening
should only be enabled when doing gamma correction, so
ideally it should always be done.</p>
<p><a href="image/freetype-262-autohinter-stem-darkening-demo2.png">
<img src="image/freetype-262-autohinter-stem-darkening-demo2-thumbnail.png"
alt="Waterfall comparison of non-emboldening and
emboldening autohinter."></a></p>
<p>The autohinter has a new toggleable stem darkening
property that works like the stem darkener in Adobe’s CFF
engine. Note how it makes text slightly bolder with the
default parameters, down to small pixel sizes. Gamma
correction is active to demonstrate the thinning out of
text especially at smaller pixel sizes with lots of gray
pixels.</p>
<p>And that is the story behind this feature.</p>
<h3 id="disabled-stem-darkening-for-the-autohinter-and-adobes-cff-otf-engine">Disabled
stem darkening for the autohinter and Adobe’s CFF
(<code>.otf</code>) engine</h3>
<p>No library supports linear alpha blending and gamma
correction out of the box on X11. Turning on stem
darkening leads to heavy and fuzzy looking glyphs as in
“Gamma 1.0, darkened” above, so it’s better to disable
it.</p>
<p>Qt5 actually had gamma correction enabled for a short
time while until someone complained that text was too
light and unlike rendering in other toolkits, so the
maintainers disabled it for
the <a href="https://bugreports.qt.io/browse/QTBUG-41590">XCB-backend</a>.
Skia (Chrome) can do gamma-correction, but turns it off
for X11.</p>
<p>I see autohinter stem darkening 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 toggleable
per <code>FT_Library</code> just like
<code>FT_Library_SetLcdFilter</code>. Libraries that
support linear alpha blending and gamma correction can
then just flip the switch and get appropriate glyphs no
matter the font.</p>
<p>A notable side-effect of disabling all stem darkening by
default is that natively hinted <code>.otf</code> fonts
will render remarkably similar to the auto-hinter and are
no longer heavy and fuzzy. Slight hinting will result in
consistent font rendering.</p>
<h3 id="the-default-lcd-filter-for-subpixel-rendering-has-been-changed">The
default LCD filter for subpixel rendering has been
changed</h3>
<p><a href="image/freetype-262-new-old-filter.png">
<img src="image/freetype-262-new-old-filter-thumbnail.png"
alt="Comparison of the old and new
filter."></a></p>
<p>When you look at subpixel-rendered text, no matter
whether it is on some kind of Unix, Windows, or Mac
OS X, you might notice that it is 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, also called color fringes. For this
reason it is necessary to filter a subpixel-rendered glyph
to reduce those color fringes before putting it somewhere
on the screen. The filter distributes the values of a
subpixel to its neighbors, sacrificing some of the 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 rendering system (linear alpha
blending and gamma correction), your vision and your
taste, probably in that order.</p>
<p>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 sacrifice some of the higher resolution to
drastically reduce color fringes.</p>
<p>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
Unix-like operating systems 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.</p>
<p>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 screen gamma (viewing
angles) and rendering systems without linear alpha
blending. Note that color fringes can only be really
minimized when the rendering system will do linear alpha
blending of text.</p>
<p>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.</p>
</div>
<!-- ************************************************** -->
<div class="updated">
<p>Last update: 12-Feb-2016</p>
</div>
</div>
</div>
<!-- ************************************************** -->
<div class="col2">
</div>
</div>
</div>
<!-- ************************************************** -->
<div id="TOC">
<ul>
<li class="funding">
<p><a href="https://pledgie.com/campaigns/24434">
<img alt="Click here to lend your support to the FreeType project and make a donation at pledgie.com!"
src="https://pledgie.com/campaigns/24434.png?skin_name=chrome"
border="0"
align="middle">
</a></p>
<p><a href="https://flattr.com/submit/auto?fid=mq2xxp&url=https%3A%2F%2Fwww.freetype.org"
target="_blank">
<img class="with-border"
src="https://button.flattr.com/flattr-badge-large.png"
alt="Flattr this"
title="Flattr this"
border="0"
align="middle">
</a></p>
</li>
<li class="primary">
<a href="http://freetype.org/index.html">Home</a>
</li>
<li class="primary">
<a href="http://freetype.org/index.html#news">News</a>
</li>
<li class="primary">
<a href="index.html">Overview</a>
</li>
<li class="primary">
<a href="documentation.html">Documentation</a>
</li>
<li class="primary">
<a href="http://freetype.org/developer.html">Development</a>
</li>
<li class="primary">
<a href="http://freetype.org/contact.html"
class="emphasis">Contact</a>
</li>
<li>
<!-- separate primary from secondary entries -->
</li>
<li class="secondary">
<a href="#slight-hinting" class="current">On Slight
Hinting, …</a>
</li>
</ul>
</div>
</div> <!-- id="wrapper" -->
<div id="TOC-bottom">
</div>
</body>
</html>