Skip to content
aadhar.sh/lwe · font smoothing
Address
aadhar.shLearning with Errorssmoothing Online, AppleFontSmoothing, 0 to 3

smoothingOnline, AppleFontSmoothing, 0 to 3

Learning With Errors
pixels & stripes

Measured on macOS 27.2. The value sweep, the stem widths and the CSS checks come from AppKit, WebKit and Chrome renders on an Apple silicon Mac whose system setting is 0. The demos redraw text with this page's own rasterizer and a growth model fitted to those renders, so they show the mechanism the same way in every browser. As a control, the model's ink for 13 pt Helvetica lands within 3 percentage points of AppKit's in all four cases (1x and 2x, both polarities). The history and the Windows side are paraphrased from the linked sources.

aadharsh

first thing i run on any new mac: defaults -currentHost write -g AppleFontSmoothing -int 0. what is that actually changing, and what do 1, 2 and 3 do?

smoothing

It writes one integer into this Mac's global preferences. -g is the domain every app reads, and -currentHost files the value under this machine's hardware UUID in ~/Library/Preferences/ByHost/, where the old System Preferences checkbox kept it. AppKit reads the key when an app launches, so an app that's already open keeps its old text until you quit it.

The numbers date from Snow Leopard. That release cut the Appearance pane down to one checkbox, and a Terminal command became the only way back to the old menu: 1 for light, 2 for medium and 3 for strong LCD smoothing.

[src]
smoothing

So I swept them on macOS 27.2: Helvetica, the system font, Tahoma and Verdana, at 11, 13 and 16 pt, at 1x and 2x, as black-on-white and as white-on-black. In all 48 cases, 1, 2 and 3 drew byte-identical bitmaps, and only 0 differed. The key is a switch now. Any value above 0 means on.

turn the dial · redrawn live, fitted to macOS 27.2

This draws the text itself, with the growth model fitted to those renders, so it shows the macOS mechanism in any browser, Windows included. The row follows the dial. The magnifier beside it shows one square per pixel as the 0 render, turning orange where smoothing adds ink.

AppleFontSmoothing 2

aadharsh

ok so what is "on" doing to the letters?

smoothing

It fattens them. AppKit grows every outline a little before it fills it, so each stem widens on both edges. I measured the stem of a Helvetica l: at 13 pt on a 1x screen it's 1.14 px wide at 0 and 1.30 px with smoothing on.

The growth tracks pixels per em, about 0.0116 px per ppem, and stops at 0.6 px, which a 2x screen reaches near 26 pt. White text on black grows 2.75 times faster, 0.032 px per ppem, so the same 13 pt stem in dark mode lands at 1.55 px, 36% heavier than at 0. That asymmetry is why light-on-dark text gains the most when you set 0.

aadharsh

and subpixel vs greyscale antialiasing? i've seen both blamed for this

smoothing

Both answer one question per pixel: how much of it does the letter cover? Greyscale antialiasing turns that fraction into a shade, so a pixel half inside a stem becomes 50% grey. All three color channels get the same value, which lets the text sit on any background, under any blend or animation.

Subpixel rendering notices that an LCD pixel is three vertical stripes, red, green and blue, and asks the question three times per pixel. Edges can land on a third of a pixel, which triples horizontal resolution. The price is color: an edge that covers only the red stripe tints red, so a filter spreads each third into its neighbours until the fringe fades.

one letter, magnified · switch the fill

A 13 px Georgia letter, drawn three ways and blown up so each square is one pixel. Shift it sideways by part of a pixel and watch the edge shading move. Tick stripes to see what the panel actually lights.

aadharsh

subpixel sounds strictly better. why would apple remove it?

smoothing

Mojave turned it off in 2018, and the reason lives in the compositor. Greyscale coverage is one alpha value, so the GPU can blend a finished glyph onto anything. Subpixel coverage is three alphas, one per stripe, so the renderer has to know the exact color behind the glyph at the moment it rasterizes. A translucent, layer-backed, animated desktop hasn't decided that color yet.

An ex-macOS engineer listed the rest on Hacker News during the Mojave beta: the panel's stripe geometry threaded through every graphics layer, glyph caches multiplied by every subpixel offset, and artifacts whenever text switched between static and animated. Rotate the panel, or use an OLED without RGB stripes, and the three-stripe assumption breaks outright.

What survived is the thickening. Mojave's checkbox became "Use font smoothing when available" and drove only that, and Big Sur deleted the checkbox, which left the defaults key as the only switch.

[src]
aadharsh

how does windows handle the same problem?

smoothing

It made the opposite bet, twice. ClearType is subpixel rendering, and Windows Vista made it the system default. Windows fonts also lean on hinting: small programs inside the font that move outlines onto the pixel grid before rasterizing, so a stem that would cover 1.14 px snaps to one whole, dark column.

Joel Spolsky drew the split in 2007. Apple keeps each typeface's true shape and accepts some blur; Microsoft hammers letters onto pixel boundaries and accepts some distortion. Newer Windows frameworks soften both bets, since DirectWrite can place glyphs at fractions of a pixel and modern Windows UI text renders in greyscale.

This site's chrome copies Windows XP, which shipped with ClearType off: its default was greyscale smoothing, the same as Windows 2000, because plenty of desks still had CRTs.

[src]
one stem, six pixels · drag it across the grid

One vertical stem, as wide as a 13 pt Helvetica l on a 1x screen. The top two rows render it the macOS way, greyscale and unhinted; the second adds the 0.15 px that smoothing grows at that size. The bottom two snap it to the grid first, the way hinted fonts on Windows do, and the last adds ClearType's stripes and filter.

aadharsh

which gets to my actual complaint. why does a mac look so much worse than windows on the same external monitor?

smoothing

Because macOS prices every one of those choices for about 220 PPI, and the common 24- and 27-inch monitors sit between 92 and 109. A 27-inch 1440p panel is 109 PPI, so macOS draws it at 1x. There the 13 pt stem is 1.14 px wide, and with no hinting it straddles two columns as two greys. No stripes sharpen its edges. Then smoothing adds 0.15 px of grey on top, or 0.41 px in dark mode. Windows on the same panel snaps the stem to one column and resolves its edges in thirds.

A 27-inch 4K panel has a different problem. Its exact 2x mode looks like 1920x1080, which most owners find too large, so they pick "looks like 2560x1440". macOS draws that at 5120x2880 and then shrinks the whole frame by 0.75 to fit 3840 pixels, so every glyph gets filtered a second time after it was drawn. The external panels that look like a MacBook are the ones where 2x lands exactly on native: 5K at 27 inches and 6K at 32.

pick a monitor · see what macOS does to it

Pick a panel and a display mode. The numbers come from the panel's geometry and from how macOS runs a HiDPI mode: it draws at twice the "looks like" size, then resamples to the panel's native pixels.

aadharsh

so is 0 the right call?

smoothing

On a 1x monitor I think so. It strips 13% of extra width from black-on-white stems and 36% from white-on-black, and the text stays soft but gets lighter and more even. It can't restore subpixel rendering or hinting, so no setting makes 109 PPI on a Mac look like ClearType. On a Retina screen it comes down to taste: 0.3 px on a 2.3 px stem reads as weight, and the stems are wide enough that their grey edges barely show.

Web pages get the same switch per element. In Safari and Chrome on a Mac, -webkit-font-smoothing: antialiased asks for the 0 rendering. The other direction is closed. With the system at 0, I measured subpixel-antialiased drawing the same pixels as antialiased in both Chrome and WebKit, so CSS can switch the thickening off and has no way to switch it back on.

[src]
aadharsh

does turning it off help performance at all?

smoothing

Barely, and only once per glyph. The thickening happens when a glyph is rasterized, before it lands in the glyph cache. I timed AppKit drawing a 33-character Helvetica line 3,000 times, each run seven times. At 3,000 different sizes, so every glyph rasterized fresh, 0 took 380 to 397 ms and smoothing on took 464 to 473 ms, about 20% more. Two separate runs at 0 differed by only 17 ms, so the gap is real.

Drawing the same 13 pt line 3,000 times took 41 to 44 ms either way, because every glyph after the first came from the cache. That's the everyday case: a page of text reuses the same letters at the same few sizes, so smoothing costs about a microsecond per glyph the first time and nothing after. Set 0 for how text looks. Nothing will feel faster.

aadharsh

and is 0 the same as turning antialiasing off?

smoothing

No. 0 keeps antialiasing and drops only the thickening. I drew one 13 pt Helvetica line three ways and counted its distinct grey levels: 224 at smoothing 0, 229 with smoothing on, and 2 with antialiasing switched off in the graphics context, which leaves pure black and white. With antialiasing off the smoothing value stops mattering, since 0 and 1 drew identical 1-bit pixels.

The old Appearance pane did have a real antialiasing switch, "Turn off text smoothing for font sizes N and smaller", stored as AppleAntiAliasingThreshold. On 27.2 it changed nothing I could measure: set to 14, it left 13 pt text antialiased in an offscreen render. The letter demo above shows what that switch used to do. Pick 1-bit and the curves turn into stairs.

end of conversation
This is a recorded conversation. Every demo above redraws live.