Re: Text anti-aliasing on the Mac

>On 03/10/12 1:25 PM, Tab Atkins Jr. wrote:

>> According to the implementor that did the Chrome 22 change, you're
>> wrong, John.  The glyph dilation occurs as a result of OXS's
>> auto-hinting.  Here's his exact words:

>>> This is not true. The OSX rasterization is not actually any
>>> heavier, they actually do auto-hint the outlines to dilate them.
>>> This is auto-hinting. You can't obtain the auto-hinted outlines,
>>> but those dilated outlines are what is being rasterized. Saying
>>> otherwise is completely disingenuous. Basically, when you ask
>>> for lcd smoothed text from CoreGraphics, you get fake bold.

>I'd like a bit more detail to confirm what 'auto-hint the outlines'
>means in this context. Is Apple actually writing on-the-fly TrueType
>instruction set code, or are they applying some kind of algorithmic
>emboldening or smear to the outlines? The latter isn't what we normally
>think of as hinting, although both involve outline distortion relative
>to the raster grid.

>JH

I'll try to explain what is happening as best I can in one place.

The current public CoreGraphics API allows for drawing either
unsmoothed text (chunky black and white), regular smoothed text
(antialiased), and lcd smoothed.

When you draw unsmoothed things are quite simple. There isn't any
adjustment and everything is nice and simple. Also, no one uses it
since it looks ugly, but maybe some day we'll all have 1200dpi screens
and we'll go back to it.

When asking CoreGraphics to draw regular smoothed (antialiased) text
it does some very light (practically unnoticeable) auto-hinting. If it
does apply the font instructions for hinting the outlines, it appears
to do so in the font's native units. I believe that DirectWrite does
the same mostly because there are some fonts out there which create
whole glyphs from pieces of others using hinting instructions. It then
draws an alpha mask from this outline and blits the fill color to the
target context using this mask. When it does this blit it does so in
linear color space, ignoring any color space on the context.

When asking CoreGraphics to draw lcd smoothed text, CoreGraphics first
checks the AppleFontSmoothing property for the current process. If it
is 0 it just goes down the regular smoothed (antialiased) path
described above. If it is 1-3 it first does the same auto-hinting the
regular smoothed (antialiased) would have done. However, it then takes
the value of AppleFontSmoothing and uses it to pick parameters for
percentage outline dilation; 1 means a small percentage, 3 means a
larger percentage, with 2 being somewhere in between. It then dilates
the outline (essentially creating a fake bold) based on these
percentages. It then creates a mask and does some lcd filtering,
resulting in an three channel alpha mask. It then blits the fill color
to the target context using this mask. When it does this blit it does
so with a gamma of 2.0, ignoring any color space on the context an
whether the system is set to 1.8 or 2.2.

The constant percentage dilation of outlines of lcd smoothed text is
essentially auto-hinting, though rather heavy handed. The CoreGraphics
public API provides no means to draw regular (antialiased) text to
match any lcd antialiased text or vice-versa (there is no API to
request lcd text without dilation). I assume that the dilation was
added originally because many fonts seemed too thin when rendered
sub-pixel. Part of this is due to lcd filtering (which somewhat blurs
the mask), part due to optical sizing (people tend to sit further from
their monitor than from a piece of paper). In any event, this dilation
should have been reduced as the font size increased, but that doesn't
seem to be happening. We can argue about whether to call it hinting or
not, since it isn't trying to align to the pixel grid. However, it is
there in order to cover more of the pixels to make up for lcd
filtering at small sizes. So I'm arguing that this is a form of
subpixel auto-hinting. Whatever it is called, it isn't drawing
directly from the font's outlines.

Chromium doesn't currently have three channel alpha, so it can't
properly display partially transparent text if it is lcd smoothed (we
don't keep the alpha value for each sub-pixel independently, so there
is no way to blend properly). As a result, most transparent text
forces off lcd smoothing in Chromium. Currently on Mac, changing from
opacity:99.9% to opacity:100% results in a 'pop', as not only did the
font go from regular smoothed to lcd smoothed, it also changed weight.
At opacity:99.9% the glyphs were un-dilated, and opacity:100% they
were dilated. In order to prevent this, a change to create A8 from LCD
was made so that when regular smoothed was needed (and the system
could draw lcd smoothed) to create the regular smoothed from the lcd
smoothed. This fixed a lot of long standing issues. In addition to
transparency, css animations also cause such a transition. Another
situation is where Chromium goes to regular smoothed (antialiased)
when the text size is above some limit, 48 pixels I think. So changing
text size around this limit causes the text to 'pop' as well.

On the other hand, a lot of people are relying on
-webkit-font-smoothing:antialiased to avoid the dilation, not because
of any 'pop', but in cases where Chromium or Safari could have drawn
lcd smoothed text and the designer simply saw the heavy text and
wanted to make it 'better'. I can understand why they want to turn it
off, I don't really like the dilation either (I normally set
AppleFontSmoothing on my Mac to 1 so I can get lcd with minimal
dilation). On the other hand it seems silly that asking for regular
antialiased should change the weight of the text. Also, these web
developers really are after preventing the dilation; they would prefer
that the text still be lcd smoothed. After some digging I believe the
(unofficial) position of Safari on this is that -webkit-font-smoothing
should only have meaning on Mac and that other platforms should ignore
it, in which case I would prefer it had been called
-apple-font-smoothing.

I proposed using text-rendering:geometricPrecision to disable hinting,
since Webkit and Gecko unofficially provide text-rendering on all
elements as a css property. Almost everyone is currently treating
geometricPrecision in the same as they treat optimizeLegibility. I
would prefer that everyone treated it like they currently treat
optimizeLegibility, but also draw as close as possible to the font's
original outlines (commonly known as turning off hinting, but there
seems to be some diasagreement on what 'hinting' means). But there are
those reluctant to make this sort of change and propose creating
something new to turn off dilation on Mac. Also, I get the feeling
that the groups responsible for css see text-rendering as something of
a black sheep and would prefer it went away. I've also proposed just
keeping webkit-font-smoothing:antialiased the way it was in Chromium,
while still allowing everything else to take the new way (A8 matching
LCD), by detecting webkit-font-smoothing:antialiased and asking Skia
to draw without hinting. However there are another set of people who
think we should come up with something other than
webkit-font-smoothing:antialiased for this because the it doesn't seem
that saying 'antialiased' should change the outlines. This would be
easier if it were just called apple-font-smoothing since it's just
exposing a CoreGraphics API. In addition it seems that other platforms
should not be respecting this since it is supposed to be Mac specific.

In addition there has been a recent emergence of 'icon webfonts'. In
order to display as intended they need to be able to specify to the
user agent that no subpixel filtering should be applied (basically,
ask for regular antialiased text) and that no outline processing
happen that isn't explicitly described by the font (mostly meaning
that the glyphs are drawn from unmodified outlines).

So I believe the request here is to find a solution user agents can
implement so that designers can state that they don't want anyone
mucking with their outlines. Suggested proposals include, but are not
limited to:

1. Agree that text-rendering:geometricPrecision means rasterizing
glyphs from unmodified outlines. This states intent and is forward
looking, it also helps those with 'icon fonts'.

2. Agree that -webkit-font-smoothing should have been called
-apple-font-smoothing or even -coregraphics-font-smoothing, state
such, and only ever honor the request when using CoreGraphics to
rasterize. This leaves things more the way they have been, but makes
it clear that the property is very, very implementation specific. Note
that MDN provides better documentation for -webkit-font-smoothing than
Safari does (none).

3. Find some other, possibly new, css property which allows web
designers to request that text be drawn un-adaulterated.

Hopefully this clarifies the state of things.

Received on Thursday, 4 October 2012 12:13:28 UTC