Re: [font-load-events] comments on new promises-based draft

Tab Atkins wrote:

>> For each of the code examples below, the initial state is that of a
>> page containing a single stylesheet with a single @font-face rule
>> and no other declarations:
> 
> All of these are actually answered in the spec, though some of them
> are of the "the spec says nothing because you *do* nothing" variety.

No, sorry, it doesn't.  The spec is currently in a "read the tea
leaves" state, with a mixture of facts and partial descriptions of
behavior.  That's fine, it's a working draft, par for the course.  But
"all of these are actually answered" and "fully spelled out" aren't
accurate.

As a general comment I think the comments of ms2ger on an earlier
draft I put together apply equally to the current draft [1]:

# Sixth, the prose lacks requirements–it contains only statements of
# facts, and no normative conformance requirement statements (as
# described by Hixie [2]).

Since you're adding requirements here to CSS OM methods, you need to
spell those out, similar to what's described for individual methods
(e.g. load, check, ready, etc.). What steps must be executed when a
new @font-face rule is added?  What steps must be executed when an
@font-face rule is deleted?  And similar steps for when a new FontFace
is constructed, when it's added to a FontFaceSet and when it's removed
from a FontFaceSet.

Take the wording again in section 4.1:

# The set entries for a document’s font source must be initially
# populated with all the CSS-connected FontFace objects from all of
# the CSS @font-face rules in the document’s stylesheets, in document
# order. This ordering must be maintained regardless of how the
# FontFace object is added; if a script manually removes and then
# re-adds one of them, it returns to its appropriate document-order
# position in the initial segment of the set entries. All
# non-CSS-connected FontFace objects must be sorted after the
# CSS-connected ones, in insertion order.

The term "initially populated" doesn't cover rules added via
insertRule. There's no description of the effect of deleteRule on the
elements of FontFaceSet. The expression "this ordering must be
maintained" is a fact, not a set of normative requirements explaining
how this is achieved.  You're obviously overriding the add method of
the Set class [3], so you need to spell out the steps for
FontFaceSet.prototype.add.

Another key point missing is the connection between the ordering
within the FontFaceSet and load order when matching composite fonts:

http://dev.w3.org/csswg/css-fonts/#font-style-matching

# When the matched face is a composite face, user agents must use the
# procedure above on each of the faces in the composite face in
# reverse order of @font-face rule definition.

You need a statement like:

  Any set of FontFace objects within a FontFaceSet could be
  represented as a set of equivalent @font-face rules defined in
  identical order. For font matching, FontFace objects in the
  FontFaceSet must be matched in the same way the equivalent
  @font-face rules would be matched.

This avoids having to explicitly define matching behavior, which you
really, really don't want to get involved in. ;)

Besides being underdefined, I don't quite understand the motivation
behind the peculiar ordering you've defined for the FontFaceSet
object.  The FontFaceSet object you've described on the list is
essentially a composite of two sets, one for @font-face rules that's
maintained in document order and a separate set for FontFace objects
constructed via script that's maintained in insertion order, with one
following the other.  This has the subtle side-effect that the
ordering of fonts within a composite font won't be consistent between
those defined via @font-face rules and those defined partially with
script-constructed FontFace objects.

  // load order: zzz.ttf ==> yyy.ttf ==> xxx.ttf
  document.styleSheets[0].insertRule("@font-face { font-family: foo; src: url(xxx.ttf); }");
  document.styleSheets[0].insertRule("@font-face { font-family: foo; src: url(yyy.ttf); }");
  document.styleSheets[0].insertRule("@font-face { font-family: foo; src: url(zzz.ttf); }");

  // load order: yyy.ttf ==> zzz.ttf ==> xxx.ttf
  document.styleSheets[0].insertRule("@font-face { font-family: foo; src: url(xxx.ttf); }");
  document.fonts.add(new FontFace("foo", "url(yyy.ttf)"));
  document.styleSheets[0].insertRule("@font-face { font-family: foo; src: url(zzz.ttf); }");

I think operations like this should be equivalent, i.e. adding via the
CSS OM vs. adding via FontFaceSet shouldn't result in different load
behavior.

I think the tough problem here is to figure out a way to represent the
concept of a FontFaceSet in a way that dovetails with the existing CSS
OM model.

My suggestion for a better definition of FontFaceSet:

- FontFaceSet order is simply insertion order, independent of source
- add/delete throws for FontFace objects created via the CSS OM
- clear removes only non-CSS-connected FontFace objects
- additional insertBefore(value, item) method which inserts before a
  given item or at the end if item is null
- insertRule("@font-face ...", index) adds a new FontFace after the
  FontFace associated with rule index
- deleteRule(index) removes the FontFace associated with rule index

Defining the set this way is still funky but I think it's "less weird"
since you don't get into situations where the FontFaceSet and the CSS
OM are completely out of sync.  For worker threads you'll have
something clean and simple.

By the way, you should take a look at the section markers in the
WebIDL spec [4], they are simple and unobtrusive and don't litter the page
with noisy symbols as bikeshed-authored specs do now.  If you don't have
time to work on the change, I'll try and do it next week.

Cheers,

John Daggett

[1] http://lists.w3.org/Archives/Public/www-style/2012Nov/0305.html
[2] http://ln.hixie.ch/?start=1140242962&count=1
[3] http://people.mozilla.org/~jorendorff/es6-draft.html#sec-23.2
[4] http://dev.w3.org/2006/webapi/WebIDL/

Received on Thursday, 12 September 2013 04:41:41 UTC