Closed Bug 728436 Opened 10 years ago Closed 9 years ago

synthetic bolding is too thick horizontally

Categories

(Core :: Graphics: Text, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla22

People

(Reporter: zpao, Assigned: jfkthame)

References

()

Details

(Keywords: regression)

Attachments

(9 files, 1 obsolete file)

Attached image screenshot
(that's a terrible bug title...)

It seems like we're doing some artificial work to make fonts bolder than they need to be. I've never noticed it for small text, but it's very noticeable at larger sizes. It might not have anything to do with boldness, but both of my examples are bold.

I don't have any regression-range, but I've noticed this for a while... maybe sometime in the 4 cycle? Maybe it's always been like that and I didn't notice...

In the attached screenshot is Chrome side by side with Nightly (2012-02-17). The issue is more obvious in the top set of windows (the "o" is particularly bad), though the sharp edges of Futura's "A" and "N" in the bottom set of windows is pretty telltale.
What's the actual markup here?

What OS are you seeing this on?
On the blog.zpao.com page, if I disable the 'letter-spacing: -3px;' on the h1 through Firebug, then the text looks reasonably good (Safari and Gecko 3.6 are still better, crisper though). It looks like a double painting or something. I've no clue so far what is happening with the other page.
OK, so this looks like specifically the Futura font involved here, with font-weight:bold, right?  At least on Mac for me.

Are we doing a synthetic bold or something?
Looking in Fontbook, Futura has the following faces: Medium, Medium Italic, Condensed Medium, Condensed ExtraBold.

So I would assume we are in fact ending up having to synthesize the bold in this case, and for this particular font we end up synthesizing something bolder than other browsers I have here...
You're seeing the (deliberate) result of bug 674909. In particular, see comment #37 there.

We used to do synthetic bold by double-striking the text with a one-pixel offset; it looks like Safari is doing something pretty similar to that. If you compare an example like
  data:text/html,<div style="font: 12px futura;">THIS IS FUTURA <b>SYNTHETIC BOLD</b>
in Firefox and Safari (on OS X), the results look pretty similar.

However, this approach means that the degree of "apparent boldness" is inversely proportional to the font size, so that at large sizes, its visual impact disappears: compare
  data:text/html,<div style="font: 72px futura;">THIS IS FUTURA <b>SYNTHETIC BOLD</b>
in Firefox and Safari (on OS X), and note how in Safari, the fact that part of the text is "bolder" is barely perceptible. So we now have a "multi-strike" implementation, where we do additional offset strikes as the size increases. While our synthetic bold here can be a bit ugly, I believe it's a better solution than the constant one-pixel version that becomes visually insignificant.

And at very small sizes, I think our implementation is also better: compare
  data:text/html,<div style="font: 8px futura;">THIS IS FUTURA <b>SYNTHETIC BOLD</b>
and note how in Safari, it looks as though letter-spacing has also been applied, because the constant increase of 1px it applies to all the glyph advances - I assume - is too much, relative to the actual size involved.

From a designer's POV, synthetic bold is (virtually) _never_ a good thing; I'd strongly recommend that you avoid it. If you're using Futura, which only provides a single (visually fairly bold) weight, don't add "bolder" styling to it - it'll look much better at its designed weight. If you _do_ add <b> or equivalent, we'll apply synthetic bold to try and make your intent visible to the reader, but it'll look poor.

And if you want to use, say, Futura if it's available, but fall back to Arial if it's not, and you want to apply bold to the Arial fallback case (because its Regular design is much lighter than Futura Medium, what then? I think the solution is to use @font-face to declare the Futura face and explicitly state that it is to be considered "bold" already; then you can safely use font-weight:bold in your CSS (or <b> in your HTML), and we won't do _further_ bolding of the Futura, though we will use Arial Bold if we end up using the fallback family:
  @font-face {
    font-family: futura;
    font-weight: bold;
    src: local(Futura Medium);
  }
(untested, but I assume this would work).
This is caused by the change we made to synthetic bolding, to fake bold text at large sizes the current code draws characters multiple times whichs distorts the underlying shape of glyphs rather dramatically.  It does make the "bold" glyph more distinct but at the cost of ugly distortions like this.  Webkit does a simple 1px shift which will look fine at regular text sizes but at large sizes the difference between regular/bold will be imperceptible.

The underlying problem is that the webpage should be using a font with a bold face:

@font-face{
  font-family:Museo Slab;
  src:url("/fonts/Museo_Slab_500.otf")
}

@font-face{
  font-family:Museo Slab;
  font-style:italic;
  src:url("/fonts/Museo_Slab_500italic.otf")
}

/* no bold face! */

See the underlying change made in bug 674909.
Depends on: 674909
Summary: (bold?) fonts are too thick horizontally → synthetic bolding is too thick horizontally
I think this is a WONTFIX, as per explanation in comments 5 and 6. I agree the synthetic bold isn't very pretty for large fonts, but (IMO) it's better than failing to render boldness as a visible contrast. Short of getting inside the font rasterizer to modify what it's doing (not really an option on all platforms), I think we're doing about the best that can be expected. I don't think we should invest a lot of resources in trying to make synthetic bold look prettier; people who care about "pretty" just shouldn't use it.

(An alternative approach to synthetic bolding, which does generally look better, is to paint the glyphs with a stroke as well as a fill, using a stroke width that's appropriately proportional to the font size, and increase the glyph spacing accordingly. However, AFAIK the only way to do this through our cairo backend, at least, would be to convert the glyphs using cairo_glyph_path() and then stroke and fill the resulting paths, rather than using the platform font rasterizer. I doubt this would work all that well - besides performance considerations, we'd lose the standard platform hinting and antialiasing of glyphs.)

To ensure good-looking type on their pages, designers should either use font families with true bold faces; avoid requesting bold styling when using single-weight families; or declare that the single available weight *is* bold, so that we don't apply further synthetic bolding to it.
(In reply to Jonathan Kew (:jfkthame) from comment #7)
> I think this is a WONTFIX, as per explanation in comments 5 and 6. I agree
> the synthetic bold isn't very pretty for large fonts, but (IMO) it's better
> than failing to render boldness as a visible contrast.

Fair enough. I never even considered synthetic bolding. Thanks for clearing all of that up - I'll try to make sure I use fonts with true bold.
(In reply to Jonathan Kew (:jfkthame) from comment #7)
> I think this is a WONTFIX, as per explanation in comments 5 and 6. I agree
> the synthetic bold isn't very pretty for large fonts, but (IMO) it's better
> than failing to render boldness as a visible contrast.

I actually disagree about making this WONTFIX, I think the fix for bug 674909 added too much smearing in a lot of cases, noticeably degrading rendering in a number of cases.  I think the 1px offset bolding that was used prior to bug 674909 was enough in most cases and we should be smearing the synthetic bold case just enough to distinguish it from the regular case.

Example:
http://people.mozilla.org/~jdaggett/tests/css3regions-ed.html
(W3C CSS spec using only regular face of Droid Serif)

In the attached screenshot, note how much the counter of the 'A' is closed down in "Abstract".
Keywords: regression
We could try reducing the effect slightly, and see if we can find a better compromise between insufficient contrast and excessive smearing, but it'll always be a tradeoff. IMO, the old 1px offset was fine at small text sizes (e.g. the typical 16px), but was a bit weak at titling sizes - and of course it became virtually imperceptible at really large sizes.

In your screenshot, for example, I'd agree that "Abstract" looks OK in Safari, but IMO the "CSS Regions..." title isn't sufficiently bold there (it looks more like a semibold), and our rendering of it is better.

So - yes, maybe we can tweak it a bit, but be sure to evaluate across a _wide_ range of sizes and faces; and no matter what we do, it'll never really be "good" boldface. Type-conscious authors and designers should avoid synthetic bold, period.
Since I've been noticing this again recently, I thought I'd update what it looks like Webkit is doing. It looks like they don't smear at all but instead do the stroke & fill strategy as Jonathan outlined in comment 7. This scaling isn't being done with a fixed amount, but is done proportionally. While I agree that at much smaller sizes, our synthetic bolding is more obvious, it honestly doesn't look good the larger you go.

And while I agree that designers shouldn't rely on synthetic bolding, I've noticed an increase in the use of @font-face where there's no bold face included (typekit, Google fonts). I'm willing to venture that many of these designers/developers are using Chrome and aren't looking closely at Firefox (or even considering synthetic bolding exists / would be an issue). So if stroking isn't an option, I'd like to see us scale back (maybe scale the smear amount geometrically?)
This just reduces the slope of the 'boldness graph' (while maintaining the existing 1px offset at font size 16px), so that we don't apply such an extreme effect to very large sizes. We could do more complex things, such as a curve based on the square root of the font size, but I don't think it's worth the cost of a more complex calculation here.
Attachment #707539 - Flags: review?(jdaggett)
Review ping...?
Testcase showing synthetic bolding for various fonts at a variety of sizes
Comment on attachment 707539 [details] [diff] [review]
make synthetic bolding less severe at large sizes

To my eye, it still looks like too much smearing, in many cases we're still distorting glyph shapes too much.  We should only be smearing enough to distinguish from the underlying face, otherwise we risk closing down delicate counters and obiliterating subtle serifs.  The ideal is somewhere between this patch and Safari.
Attachment #707539 - Flags: review?(jdaggett)
Use the previous value for the smear up until 46px, then use size/46.  

Based on testing this still produces enough contrast to distinguish the bolded face from the underlying face across various fonts without as much distortion.
Attachment #717751 - Flags: feedback?(jfkthame)
Comment on attachment 717751 [details] [diff] [review]
patch, alternate variation of less bolding

Review of attachment 717751 [details] [diff] [review]:
-----------------------------------------------------------------

At some sizes, I feel the result of this version isn't really "bold enough" - it's still visibly distinct from regular, but it looks more like a "semibold" than a "bold". But at those (larger) sizes, designers should be using fonts properly so that they won't be hitting this. So if the result sometimes looks a bit ugly... too bad. As far as that's concerned, if you prefer a lighter version - fine, whatever. But see below.

::: gfx/thebes/gfxFont.h
@@ +1495,4 @@
>      gfxFloat GetSyntheticBoldOffset() {
> +        gfxFloat adjSize = GetAdjustedSize();
> +
> +        // 1.0px for sizes up to 46.0px, then scaled by size

What bothers me more in this version is that the fixed 1-pixel result below the threshold means that at small text sizes (e.g. 10px or so, or even smaller on a Retina display, where text down to about 6px is still quite readable), we end up with excessively loose glyph spacing, as we'll be adding a full pixel to all the advance widths even when the widths themselves are only a few pixels.
Attachment #717751 - Flags: feedback?(jfkthame) → feedback-
Here's another alternate, which is similar to yours at larger sizes, but distorts spacing less for tiny fonts.
Attachment #707539 - Attachment is obsolete: true
Assignee: nobody → jfkthame
Attachment #717827 - Flags: review?(jdaggett)
Comment on attachment 717827 [details] [diff] [review]
make synthetic bolding less severe at large sizes

ok, that looks reasonable
Attachment #717827 - Flags: review?(jdaggett) → review+
https://hg.mozilla.org/integration/mozilla-inbound/rev/32b80ae899a1
Component: Layout: Text → Graphics: Text
Target Milestone: --- → mozilla22
https://hg.mozilla.org/mozilla-central/rev/32b80ae899a1
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.