Re: [css-font-loading] load, check and testing for character coverage

On Mon, May 25, 2015 at 12:44 AM, John Daggett <jdaggett@mozilla.com> wrote:
> Tab Atkins wrote:
>> If it returns "true", you can go ahead and start rendering.  If it
>> returns "false", you need to .load() that string and wait for it to
>> finish.
>
> Is this the only use case for check()? That's a question that's really
> important to answer here. I think both Cameron and I are unsure whether
> this is the only use case you see for the check() method. If
> conditionally calling load() is the only use case, the logic for check()
> should be the same as load(), which it's not if check() is doing "error
> checking" in addition to testing load state.

This, right here, is the faulty assumption.  It is *not* necessarily
true that, in this case, we should have .check() use the exact same
logic as .load().  As I've repeatedly tried to argue, it's valuable to
know when you've clearly done something wrong, which is the case when
none of the fonts in your font list are recognized by the system.
There are ZERO cases (when the string argument isn't used) where "we
don't know what any of these fonts are" is a normal and expected
behavior; they're *all* error cases where you've either typo'd or
changed which fonts you're using without changing every point of use.

We are not doing a service to the author if we make that error case go
"well, I don't know what any of these are, so sure, you don't need to
load anything if you use this, because you'll just get a system
fallback" and return true from .check().  We are actively harming
them, by making an error-case silently pass through.

I originally had it thus return false, but y'all's arguments have
convinced me that this isn't useful either (when people *are* using it
as a precursor to .load(), it'll just cause them to call .load() and
they'll still get bad behavior).  It's clear now that throwing is the
correct behavior.  It'll alert the author to the problem, either by
crashing the code (hopefully found during testing!) or alerting them
via a try/catch they'd set up.

>> The third case is that the search for matching font faces
>> returns nothing, indicating that some of your sample characters
>> can't be rendered by *any* of the fonts in the list.  This is an
>> error condition; either you misspelled your font names, or you're
>> planning on using some characters that nothing can render.  Either
>> way, we definitely shouldn't return "true" (using that font string
>> won't render like you expected), and probably shouldn't return
>> "false" either (.load() won't do anything).  This is why, near the
>> end of the f2f, I suggested throwing in this case instead.
>
> It's not correct to say that it's an "error". Fontlists may or may not
> cover the range of characters used. Look at the localization links at
> the bottom of the Facebook landing page (www.facebook.com) for which the
> fontlist is always 'arial, helvetica, lucida grande, sans-serif'.  For
> some of the items in the list, system font fallback will occur. That's
> not an "error", that's the nature of fontlists in CSS.
>
> The check() method is there simply to allow users to determine whether
> all fonts that might need to be loaded have actually been loaded. So if
> Facebook associated a particular font with their brand, in the case of
> the Facebook localization links, you'd have:
>
>   var localizations = ["English (US)", "日本語", "Português (Brasil)",
>     "中文(简体)", "Tiếng Việt", "Español", "Bahasa Indonesia", "한국어",
>     "Français (France)", "Deutsch"];
>
>   var fontlist = "fb font, arial, helvetica, lucida grande, sans-serif";
>   localizations.forEach(function(str) {
>     if (document.fonts.check(fontlist, str)) {
>       // draw the localization string with the fontlist
>     } else {
>       // draw ui to indicate waiting for a font load
>       document.fonts.load(fontlist, str).then(function() {
>         // draw the localization string with the fontlist
>       });
>     }
>   }
>
> Authors shouldn't be required to do some form of analysis on the
> fontlist and possible contents to determine whether this will result in
> errors or throws.

This is a reasonable argument.  So we have two cases:

: "find the matching font faces" algo can't find *any* of your font faces
:: This is an error case. Either the author typo'd a font name, or
they changed their font names and didn't update all the old usage
sites. No possible legitimate usage.

: "find the matching font faces" algo finds fonts, but filters them
all out for not being able to render the "sample text"
:: This is acceptable, it just means that the text will get rendered
with an (unspecified) fallback font. No load is required.

I'm fine with making the algo a little smarter, and treating these two
cases differently.  This'll capture the desired error behavior (by
throwing) and your desired example behavior (by returning true).  I
just committed a change to handle this.  Please review and let me know
what you think. ^_^

~TJ

Received on Thursday, 28 May 2015 00:35:26 UTC