servo / font-kit

A cross-platform font loading library written in Rust
Apache License 2.0
678 stars 100 forks source link

Anti-aliased glyphs sometimes get pixels clipped off during rasterization on MacOS #194

Open vorporeal opened 2 years ago

vorporeal commented 2 years ago

We use font-kit for font rendering in our MacOS app (https://github.com/warpdotdev/Warp), and I noticed that characters sometimes are rendered without the top row of pixels. For example, when using Courier New, 13pt, with greyscale AA, the top row of pixels for "l" and "f" are missing.

I hacked around it by adding vec2i(1, 1) to the size of the computed raster bounds and subtracting vec2i(1, 1) from the origin of the computed raster bounds. This causes glyphs to draw in the same location, but without any clipping.

I don't know (at a deeper level) why the clipping occurs, nor why it only affects some glyphs. I chose not to attempt an upstream fix at the moment due to this lack of understanding, and not being sure whether this is an issue specific to font-kit on MacOS or whether a fix would need to also touch other supported platforms.

Screenshot of "l" with clipping:

warp-with-clipping

Screenshot of "l" with my patch applied:

warp-no-clipping

In the above screenshots, the 1px box is placed in the same position relative to the glyph body/baseline. You can see how the second screenshot includes an extra row of pixels at the top that are missing from the first screenshot. The same clipping issue can also be seen on the "f" at the right side of each screenshot.

I'm not sure if I've observed clipping on the sides of glyphs; unclear whether the adjustment only needs to be applied for rows (y-component) or is also required for columns (x-component).