Closed Bug 1633397 Opened 4 years ago Closed 4 years ago

Text has inconsistent font weight on Mac

Categories

(Core :: Graphics: WebRender, defect, P3)

defect

Tracking

()

RESOLVED FIXED
mozilla78
Tracking Status
firefox78 --- fixed

People

(Reporter: jrmuizel, Assigned: jfkthame)

References

(Blocks 1 open bug)

Details

Attachments

(6 files)

Attached image inconsistent.png

See the attachment. Firefox is the text above, Chrome is text below.
Especially the "e" in "Make", the "a and i" in "easier", the second two "e"s in "developers" etc.

It seems like it works fine with non-WebRender

Flags: needinfo?(lsalzman)
Blocks: wr-mac
Priority: -- → P3
Severity: -- → normal

Looking at the last screenshot, it seems like between the Firefox WR and non-WR (Skia) case, the pixel footprints are more or less the same, but the gamma curves for the grayscale antialiasing are somehow different. My initial guess is that this isn't the weighting, but how we're not assigning the right gamma to this situation somehow.

My Mac machine is not in terribly good shape right now, so someone else might have to try to investigate this one... But some initial questions you might be able to find some answers to that would help me guess better, Jeff:

  1. For WR, around https://searchfox.org/mozilla-central/source/gfx/wr/webrender/src/platform/macos/font.rs#625 what are the values of smooth, antialias, and glyph_type?

  2. For Skia case, at https://searchfox.org/mozilla-central/source/gfx/skia/skia/src/ports/SkFontHost_mac.cpp#2430 we need to know what it's trying to do here between the mask format and smooth behavior...

Flags: needinfo?(lsalzman) → needinfo?(jmuizelaar)

This is perhaps a poor testcase for comparing font rendering, because it loads a single normal-weight face of Segoe UI but then the test text is in a <strong> element, which means it has font-weight:bolder and gets rendered with synthetic bolding. So we're not seeing the "true" rendering of the glyphs, we're seeing a "double-struck" rendering (in Firefox, at least; I'm not sure what Chrome does with it). We don't expect synthetic-bold to necessarily look the same across all browsers or platforms, as different back-ends implement it in quite different ways.

FWIW, comparing WR and non-WR rendering of attachment 9143630 [details] on my MacBookPro (current Nightly), I can't see any difference -- even taking screenshots and greatly enlarging them, the result looks identical. So it's unclear to me whether there is an issue to be addressed here.

It's true that the Firefox rendering is significantly different from either Chrome or Safari, which are also quite different from each other; this is a known (non-)issue: different browsers have very different implementations of "synthetic bold", and exact interoperability is not expected. (In this particular case, I'm inclined to say Firefox is the best of the three, but this is arguably debatable depending on one's tastes and priorities.)

The main point this illustrates is that authors who care about good font rendering should avoid using synthetic bold.

Some more notes here based on ongoing investigation: the inconsistent weight seen in the WebRender output looks like it is related to pixel-snapping of glyph positions resulting in the "double-strike" synthetic-bold effect sometimes failing, presumably because the two strikes end up snapping to the same position.

The weird thing is that this happens with a "full" version of the Segoe UI font locally installed; but does not happen if the font is loaded as a webfont resource. And it doesn't happen if the (locally-installed) font is subsetted such that it contains only the ASCII character set. It's still unclear exactly what it is in the "complete" font that triggers the bad behavior. E.g. I've seen the problem reproduce with a subset that has 2061 glyphs, but when subsetted further to 2051 glyphs the problem went away. Yet other fonts with a larger number of glyphs don't show the same problem.

Here's a substantially reduced testcase, using a subsetted font derived from DejaVu Sans (so confirming, incidentally, that the issue was not specific to Microsoft's Segoe UI).

To reproduce, download and expand the zip file, and install the two .ttf fonts via Font Book. (The test fonts here are named "dejavu-asciilower" and "dejavu-asciilower-nko0", so unlikely to conflict with already-installed fonts.)

"dejavu-asciilower" is a copy of DejaVu Sans with all hints stripped out and with the character set reduced to just lowercase ASCII letters, plus <space>.

"dejavu-asciilower-nko0" is exactly the same, except that its character set also includes U+07C0 NKO DIGIT ZERO.

Now open testcase.html in Firefox. This file displays a-z in three fonts, each with regular weight and with synthetic-bolding applied: (1) the installed "dejavu-asciilower" font; (2) the installed "dejavu-asciilower-nko0" font; and (3) the "dejavu-asciilower-nko0.ttf" font loaded as a @font-face resource.

With webrender disabled, all the text stays steady and moves smoothly as we animate left-margin back and forth.

But with webrender enabled, the synthetic-bold rendering of the installed "dejavu-asciilower-nko0" font "jiggles" or "shimmers", apparently due to glyph positioning getting inappropriately pixel-snapped. This only happens with the version of the font that includes U+07C0 (although that character is not actually used at all), and only when using the installed copy of the font; when using it as a @font-face resource, the rendering stays as steady as ever.

AFAICT this seems to be an issue within Core Text, when we pass an array of glyph IDs (all the same) and positions (with 1-pixel offsets) to CTFontDrawGlyphs to generate a rasterized bitmap for a synthetic-bold glyph. Sometimes, depending on the fractional-pixel x position and the character coverage of the font, it may misposition the rendering.

The problem doesn't occur if we render the exact same glyphs and positions to the context using individual single-glyph calls to CTFontDrawGlyphs.

This is probably a bug we can report to Apple, if we create a standalone testcase, but in the meantime we can work around it in WebRender by making multiple CTFontDrawGlyphs calls. As this is just about synthetic-bold, which shouldn't be commonly used, the performance implications aren't especially serious.

Assignee: nobody → jfkthame
Status: NEW → ASSIGNED
Pushed by jkew@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/fd7f3a8bba92
Make separate Core Text calls for each strike when applying synthetic-bold, to avoid unreliable subpixel positioning. r=jrmuizel
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla78
Flags: needinfo?(jmuizelaar)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: