[css3-fonts] rethinking font load events

Rethinking the font load event that Tab proposed, I think it would be
better to create a separate event target for font loads.  Typical
patterns for load events in other Web API's rely on there being a
single target for one resource, typically an element.

Fonts are somewhat different since they are loaded as needed, based on
the styles used and the scripts contained in text.  The primary use of
load events for fonts is to determine when all loads have completed so
that other operations can be done (measuring text, fading in after the
loads complete, drawing to a canvas element, etc.).  There might be
some applications that need to know when specific fonts load but this
isn't the typical case.

So I think the right way to go is to have a separate event target for
font loads attached to the document object.  This would make it easier
to make the loading and error handling behavior closer to how other
types of load events are done in other API's.

This object would act as the event target for font-related events for
a given document:

partial interface Document {
  readonly attribute FontLoader fontloader;
};

[Constructor]
interface FontLoader : EventTarget {

  // "idle" or "loading"
  readonly attribute DOMString readyState;

  // event handler attributes

  // -- fires when readyState changes
  [TreatNonCallableAsNull] attribute Function? onreadystatechange;

  // -- fires when all font loads have completed or failed
  [TreatNonCallableAsNull] attribute Function? onallcomplete;

  // -- fires when a single font load completes
  [TreatNonCallableAsNull] attribute Function? onload;

  // -- fires when a single font load fails
  [TreatNonCallableAsNull] attribute Function? onerror;

  // async load
  void loadFont(DOMString font, optional DOMString text);

  // notify completion, even if no fonts load
  void notifyAfterCompletion();

};

The 'readyState' attribute switches between "idle" and "loading"
depending upon whether one or more fonts were loading at the time. 
The "readystatechange" event fires when state changes occur.  As
individual fonts are loaded (or errors occur), "load" or "error"
events fire.  These fire independent of whether the font used is local
(i.e. via src: local(xxx) ) or from a url.  When there are no more
pending loads, the "allcomplete" event fires.

The 'loadFont' method would allow for explicit async loading of fonts,
for use with API's like canvas where text drawing operations need to
happen after a specific set of fonts have been loaded.

Because the number of fonts loaded depends on the number of fonts used
for a given piece of text, in some cases whether fonts need to be
loaded or not may not be known.  The 'notifyAfterCompletion' method
indicates that after the current set of layout operations complete,
the "allcomplete" event fires when no font loads are pending, even if
no fonts actually needed to be loaded.

The "load" and "error" events would fire the event below:

[Constructor]
interface CSSFontFaceLoadEvent : EventTarget {
  readonly attribute CSSFontFaceRule fontface;
  readonly attribute DOMString error;
}

Bubbles: only in my champagne darling
Cancelable: no

Example: show content only after all font loads complete

  document.fontloader.onallcomplete = function() {
    var content = document.getElementById("content");
    content.style.visibility = "visible";
  }

Example: drawing in canvas with a downloadable font

  function drawStuff() {
    var ctx = document.getElementById("c").getContext("2d");

    ctx.fillStyle = "red";
    ctx.font = "50px MyDownloadableFont";
    ctx.fillText("Hello!", 100, 100);
  }

  window.onload = function() {
    document.fontloader.loadFont("100px MyDownloadableFont");
  }

  document.fontloader.onallcomplete = drawStuff;

Example: complicated layout operations, may or may not download fonts

  function doStuff() {

    // content/layout operations that may cause additional font loads

    document.fontloader.notifyAfterCompletion()
  }

  document.fontloader.onallcomplete = function() {

    // contents can now be measured using the metrics of
    // the downloadable font(s)

  }

Received on Thursday, 6 September 2012 14:11:21 UTC