-
Notifications
You must be signed in to change notification settings - Fork 34
Description
I'm interested in contributing to alacritty & crossfont to provide an option to disable anti-aliasing for glyph rendering (at runtime, using the alacritty config). I'm primarily interested in contributing for the macOS backend (though I could be convinced re: Windows and freetype). I'm filing here in the crossfont tracker for the crossfont specific changes (because they're not trivial), but also happy to discuss the alacritty side of things on the related alacritty/alacritty#957.
Motivating Scenario
I like to use Monaco 10 as a terminal font on macOS, because the font is pre-installed on every machine, is decent enough for coding, and, importantly, is very clear even at such a small point size because it's perfectly pixel-hinted:
However, with anti-aliasing turned on, it (and other fonts of the same size) are hopelessly blurry:
The screenshots above don't even do the effect justice (github scaled the un-anti-aliased one, ruining the acuity, and the anti-aliased one looks way worse on a physical OLED display because of sub-pixel layouts).
Technical Considerations
I have a proof of concept (not yet in a PR-quality state) with alacritty/crossfont looking pretty reasonable:
However, it's not just a matter of cg_context.set_should_antialias(false);. The current logic for the glyph metrics (using CTFontGetBoundingRectsForGlyphs gives the bbox for the anti-aliased glyph, which I've found can be multiple pixels out from the hinted glyph.
Here's an example from Monaco (screenshot of fontforge displaying the pixel hints):
The bbox returned by CoreText is:
CGRect { origin: CGPoint { x: 1.1083984375, y: 0.0 }, size: CGSize { width: 4.1650390625, height: 7.578125 } }
but the correct origin without anti-aliasing should actually be x=0, i.e. it's not just a rounding error. The entire vertical stroke gets cropped out with the current logic.
This seems to be WAI from the font and OS perspective. i.e. it's not that the font designer has made a mistake by specifying hints >1 pixel away from the paths. And it's just a limitation of the particular CTFontGetBoundingRectsForGlyphs being used that there's no way to specify you want the bitmap rendering when requesting the bounding box.
The solution is to use a generous buffer for rendering and then post-process if you really need the metrics. This seems to be what other terminal emulators are doing. I wasn't even sure why crossfont tries so hard to render the minimal bbox given the other assumptions in crossfont about monospaced fonts - clients like alacritty will surely just be pushing the bitmap into atlas cells eventually.
The other consideration is how to pass the configuration down from the client app to crossfont. I figure injecting an Options struct into the Rasterizer (either in new or after initialization), with platform-specific contents, would be the way to go, rather than the weird NSUserDefaults side channel currently used for AppleFontSmoothing. Happy to take advice here - there are also specifics like whether it should just be a boolean or whether it should have something like the lcd, lcdv, gray, none enum from the alacritty issue.
Justification Discussion
This is something that was part of @jwilm's original proposal for alacritty/alacritty#957, and even before then had an alacritty PR https://github.com/alacritty/alacritty/pull/560/files.
Since then, in reading various other issues on the alacritty tracker, it does seem like @chrisduerr and @kchibisov aren't super keen for font customization features, typically suggesting they'd be better off implemented at the OS or fontconfig level. A related change is removing the use_thin_strokes alacritty configuration in favour of respecting the AppleFontSmoothing value from NSUserDefaults.
I'm advocating for having a config on the basis of:
- Having anti-aliasing on or not is an aesthetic preference, similar to choosing a font size or face. Therefore it's something that makes sense to be user configurable at runtime.
- For similar reasons, I don't think it makes sense to claim it's something that should just be configured at the platform-level - whether a particular font looks good without anti-aliasing is really dependent on the font and the context, and therefore I think it should be an alacritty-specific config. i.e. I think it's perfectly reasonable that a user might want other apps on the same platform to use/not-use anti-aliasing, even for the same font. That said, fontconfig probably does a good enough job that it's not really an issue for the freetype backend.
- Other terminal emulators (including Apple's Terminal.app) do support explicit configuration of anti-aliasing. Yes, I realize arguments like these don't usually hold much sway with alacritty maintainers!
So, I think it's reasonable to add to crossfont and then alacritty. But if you don't, I'm also okay to just keep running my own patch/fork.
Let me know if you want the PR, and/or have any suggestions on the technical aspects.



