- From: John Daggett <jdaggett@mozilla.com>
- Date: Tue, 6 Jan 2015 10:27:28 +0900
- To: www-style list <www-style@w3.org>
- Message-ID: <CALYZoVNCXBYXVwsrmdoeLK-K5vd4v+aT61XnKG8v7b8jFz5N3g@mail.gmail.com>
Hi Lea, As Jonathan has already pointed out, the problem with the Gill Sans family on Windows is an issue with the way the DirectWrite API synthesizes font family groupings. It's an issue tied to historical baggage with Windows font API's. Firefox and IE both use hacks to workaround the issue. Chrome, which recently switched to DirectWrite, hasn't implemented a workaround but there is an issue logged. [*] I've included more about the history of this problem below. As to the larger issue of how font weights are matched, CSS has always defined a simple prioritization scheme for font matching, going back to CSS1. A family is selected from the fontlist and a face is selected from the faces available for that family, using the width, slant and weight attributes of faces in that order. Other priorization schemes such as the ones you suggest are possible but, no matter what, choosing a font outside the one an author intended to use is an imperfect art. The attributes assigned a specific face are the choice of the type designer, there's no absolute emperical scale here. One type designer's medium is another's demi-bold. ;) > The font matching algorithm outlined in [1] results in cases of very > odd matching when it comes to missing font weights and it should be > changed. For example, if the requested font weight is 100 (extra > light) and only 900 is available (which is black) or vice versa, this > one will be used instead of falling back to the next family in the > font stack. When the difference between desired and available weights > is so dramatic, falling back would be a more appropriate choice in > most cases. A font family represents a set of faces constructed with a similar design aesthetic. Faces generally differ in a known way based on the width, slant and weight attributes assigned them. However, there's no way for user agents to reliably assess whether a separate family is "closer" to a particular set of attributes or not. In general, it rarely is, although you can always construct combinations of families containing sparse numbers of faces for which it might be (e.g. the Gill Sans case under DirectWrite on Windows). But that's not a good basis for general font matching rules. > In addition, even when the difference between available and requested > weights is smaller, the current algorithm can still result in > suboptimal matching (i.e. picking weights that are not the closest > possible to the requested weight). When choosing the font weight, if the desired weight is not available, in general a lighter font is chosen for weights less than normal and a heavier weight is chosen for weights above normal (see the algorithm for the specific mappings). For desired weights other than normal this makes it so that a weight *other* than normal is chosen. If the "optimal" choice is defined as simply the closest weight to the desired weight, text spans with differing weights will more frequently end up displayed using the same face. Example: p { font-weight: normal } span { font-weight: 300 } <p>This is a <span>subtle</span> distinction in my opinion</p> The current font matching algorithm will select a lighter face if any lighter face is available. Using the face with the closest weight distance may or may not depending upon the specific faces available. Regards, John Daggett Mozilla Japan [*] https://code.google.com/p/chromium/issues/detail?id=408093 Background on the DirectWrite Gill Sans problem ============================== ================= The problem with the Gill Sans family on Windows is actually a problem with how the DirectWrite API on Windows swizzles around and creates synthetic font family groupings. Prior to DirectWrite, Windows applications used GDI which restricted font families to four basic faces, Regular, Bold, Italic and Bold Italic. Due to this restriction, font vendors sometimes shipped fonts which the style name included in the family name. Some commonly used Microsoft application suites bundled a pair of fonts with a family name of "Gill Sans Ultra Bold", along with some other fonts labeled with a family name of "Gill Sans MT". Under GDI these are only accessible using family names of "Gill Sans Ultra Bold" and "Gill Sans MT". In an attempt to create larger font families such as those that exist naturally under OSX, DirectWrite tries to fold in fonts that use this sort of pattern into larger families. The gory details are in the "WPF font selection model" white paper [1] which details this process. Look through the section labeled "Font Differentiation" starting on page 6. The net result of this process is that DirectWrite will take a font with a font family name of "Gill Sans Ultra Bold", strip out the "Ultra Bold" weight name and group these fonts into a family labeled "Gill Sans". But this produces a family only containing ultra bold faces! Since OSX ships with a normal set of Gill Sans faces, authors who like this family often include it in their fontlists (Hi Bert!). But under DirectWrite on Windows this produces the results you've noted. Chrome recently switched to using DirectWrite and that's why your seeing the problem now. Users have already logged this as an issue [*]. When Firefox switched to using DirectWrite in 2010 we came across this issue and we worked with the IE team to implement an explicit hack to work around this problem [2]. The result is that Firefox DirectWrite font handling code explicitly pushes these Gill Sans ultra bold faces into the Gill Sans MT family [3]. Pure ick but that's life in the world of fonts sometimes. Chrome hasn't implemented this hack. [1] http://blogs.msdn.com/b/text/archive/2007/04/23/wpf-font-selection-model.aspx [2] https://bugzilla.mozilla.org/show_bug.cgi?id=551313 [3] http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxDWriteFontList.cpp#998 On Mon, Dec 29, 2014 at 3:12 AM, Lea Verou <lea@verou.me> wrote: > The font matching algorithm outlined in [1] results in cases of very odd > matching when it comes to missing font weights and it should be changed. > For example, if the requested font weight is 100 (extra light) and only 900 > is available (which is black) or vice versa, this one will be used instead > of falling back to the next family in the font stack. When the difference > between desired and available weights is so dramatic, falling back would be > a more appropriate choice in most cases. > > This issue was brought to my attention when a colleague sent me [2], > asking why the different behavior between Firefox & Chrome. Upon further > investigation, it appeared that he only had UltraBold for Gill Sans and > Chrome used that for all weights to avoid falling back to Gill Sans MT. One > would expect that Chrome’s behavior is the buggy one here, but according to > the existing algorithm [2], Chrome is perfectly correct and Firefox is > buggy! > > In addition, even when the difference between available and requested > weights is smaller, the current algorithm can still result in suboptimal > matching (i.e. picking weights that are not the closest possible to the > requested weight). Observe the following examples: > > Desired | Available | Matched | Better option > --------+---------------+---------------+---------------- > 100 | 900 | 900 (+800) | Fall back! > 900 | 100 | 100 (-800) | Fall back! > 400 | 100, 600 | 100 (-300) | 600 (+200) > 500 | 300, 900 | 900 (+400) | 300 (-200) > 600 | 500, 900 | 900 (+300) | 500 (-100) > 300 | 100, 400 | 100 (-300) | 400 (+100) > > I believe it would be better to alternately try to match weights with an > offset of -100, +100, -200, +200, ... up to a certain maximum (by absolute > value) offset to avoid the issue shown in [2] (200 or 300 looks like a good > candidate). I’ve written a simple JS function [3] so you can test this out > with different parameters (the possible combinations of missing weights are > more than you might think: as many as 9*2^8=2304). > Not only this algorithm always results in matching the closest possible > weight (results perfectly match the “Better option” column above), but it > avoids having to special case 400 and 500 like the existing one. > > Currently it prioritizes lighter fonts over bolder fonts when two weights > exist with the same distance, but that’s an arbitrary choice. Since it’s > arbitrary, we could easily start from the positive offset if the weight is > divisible by 200, which results in matching 500 when the desired weight is > 400 and 400 when the desired weight is 500, just like the existing special > casing which checks 500 first for 400, and 500 first for 400. > > Thoughts? > > [1]: http://dev.w3.org/csswg/css-fonts/#font-matching-algorithm > [2]: (URL: cssfontstack.com/Gill-Sans, OS: Windows 8) > http://lea.verou.me/images/font-matching.png > [3]: https://gist.github.com/LeaVerou/adbc2e4750ad809b6aef > > Lea Verou ✿ http://lea.verou.me ✿ @leaverou > > > > > > > >
Received on Tuesday, 6 January 2015 01:27:56 UTC