Search code examples
google-chrometext-renderingdirectwrite

Chrome 37 DirectWrite fixed text rendering, but special characters still appear grainy


Chrome 37 fixed its font rendering issues by supporting DirectWrite on Windows. As a result, text renders much better, as seen in a screenshot of my web app:

Comparison between old and new font rendering

However, note that the stars on the right remain ugly. The stars are ☆ WHITE STAR (U+2606).

I also have ✓ CHECK MARK (U+2713) on my page, and it appears grainy and pixelated: Grainy check mark

When zooming in to 125%, the stars jump from a grainy outline to a smoother shape. The checkmark becomes smooth at 200% page zoom.

The symbols appear fine in Firefox, although the stars look bad in IE11 like in Chrome.

Since Chrome fixed font rendering as seen with the text above, why do the stars and checkmarks appear grainy still? How can I fix this to make them look like they do in Firefox?


Solution

  • There are several ways to use DirectWrite. You can let it decide when to switch to hinted characters (which depends on what the font tells it) or you can force vectors all the way, but this requires a bit more implementation code, i.e. a custom renderer. So simply "using" DirectWrite is not the end of story.

    I don't know how Chorme does it vs IE, but I suspect the stars and checkmark are being rendered in the "old school" way, being hinted, which is why you start to see them smooth after a sufficiently big size, when then hinting turns off.

    Hinting is heavily dependent on the font. The newer Microsoft fonts are less heavily hinted than the old ones. The white star doesn't have widespread font support. Of the newer MS fonts, only Segoe UI Symbol supports it. From the older ones, only Arial Unicode seems to support it. The same font support observation applies to the checkmark glyph.

    In your example, the two glyphs are probably coming from some crap/free font on your machine (possibly something that ships with Chrome as fallback font.) If I force the font to Segoe UI Symbol, the star looks pretty good to me, certainly not much worse than the text, when rendered with Chrome 37:

    <p style="font-family:'Segoe UI Symbol'; font-size:12px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Segoe UI Symbol'; font-size:18px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Segoe UI Symbol'; font-size:24px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Segoe UI Symbol'; font-size:30px">&#x2713; This is a &#x2606; paragraph.</p>
    

    Segoe UI Rendered in Chrome 37

    Actually the checkmark looks pretty good in Arial Unicode too. Only the star is a bit thin/wonky. But it's not the same as the one you've shown, so yours is not even coming from Arial Unicode.

    <p style="font-family:'Arial Unicode MS'; font-size:12px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Arial Unicode MS'; font-size:18px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Arial Unicode MS'; font-size:24px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Arial Unicode MS'; font-size:30px">&#x2713; This is a &#x2606; paragraph.</p>
    

    Arial MS Unicode

    On my box, if I pick a font that doesn't have the checkmark and white star glyphs, e.g.

    <p style="font-family:'Gabriola'; font-size:30px">&#x2713; This is a &#x2606; paragraph.</p>
    

    then Chorme falls back to Arial Unicode for those two glyphs:

    substitution with Gabriola

    But I'm guessing you don't even have Arial Unicode installed. According to Wikipedia's page on that font, it only comes with MS Office, not with any base Windows operating system. Segoe UI Symbol should be available on base Windows 7 though. I'm guessing Chrome just picks the first font, in alphabetical order, that contains the glyph if it's missing from the font specifically requested. On my box, IE11 behaves differently on that last line; it serves the missing check-mark and white-star glyphs from the MS Mincho font, so the output looks like this:

    IE11 subst

    Interestingly enough, even though MS Mincho seems to be widely available according to that MS page I linked previously, fileformat.info doesn't mention it. And if I force Google Chrome to use this MS Mincho font, I surely get the crappy output you get at smaller sizes:

    <p style="font-family:'MS Mincho'; font-size:12px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'MS Mincho'; font-size:18px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'MS Mincho'; font-size:24px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'MS Mincho'; font-size:30px">&#x2713; This is a &#x2606; paragraph.</p>
    

    Mincho in Chrome

    So this seems to be what Chrome defaults to on your box for those missing glyphs. At small sizes MS Mincho actually looks a little better, but not by much, in IE11: enter image description here

    On Firefox on the other hand, the missing glyphs (in Gabriola) get served from Segoe UI Symbol, which is why they look good:

    enter image description here

    If you actually force Firefox to use the crappy MS Mincho font, it looks just as bad as IE11:

    enter image description here

    Apparently the pixelated look at small sizes of MS Mincho (and its brother MS Gothic) is somehow by design. I don't know enough about CJK fonts to have any opinion on that myself... Suffice to say they are unfortunately installed by default on a wide variety of Windows(es).

    Even more strange is that the much newer replacement that MS devised for MS Mincho and MS Gothic, which is called Meiryo, also has these two glyphs, but it's not selected in IE11, even though it is alphabetically before MS Mincho and MS Gothic ('MS' part of the name.) Here's what Meiryo looks like:

    <p style="font-family:'Meiryo'; font-size:12px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Meiryo'; font-size:18px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Meiryo'; font-size:24px">&#x2713; This is a &#x2606; paragraph.</p>
    <p style="font-family:'Meiryo'; font-size:30px">&#x2713; This is a &#x2606; paragraph.</p>
    

    enter image description here

    Firefox has a pretty complex font fallback algorithm, in which the fallback fonts lists depends on the range of the glyphs. It's given starting around line 700 in gfxWindowsPlatform.cpp. For the 2xxx glyph range, Firefox is coded to prefer Segoe UI Symbol over Arial Unicode. Chromium probably has something similar, although I suspect less elaborate.

    What's also interesting (and strange at the same time) is that DirectWrite itself implements a font fallback at least for the simple DrawText case, but its fallback (at least for Gabriola) is also Segoe UI Symbol! So IE11 and Chrome must be doing something custom to get it worse looking than DirectWrite does it out of the box. Here's a screenshot of the DirectWrite SDK sample app modified by simply changing the test string:

    enter image description here

    If you want to serve your own fonts, which is really the only way to ensure consistent looks if you can't control what fonts are installed on the clients, then you should look at a tutorial like this one. For inconsistency reasons like the above, some experts like Lonely Planet's Ian Feather recommend switching to SVG for icons like those. YMMV as the saying goes...