Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
This CSS module describes events and interfaces used for dynamically loading font resources. The contents of this specification were previously contained in the CSS3 Fonts module.
This is a public copy of the editors' draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don't cite this document other than as work in progress.
The (archived) public mailing list www-style@w3.org (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “css-font-load-events-3” in the subject, preferably like this: “[css-font-load-events-3] …summary of comment…”
This document was produced by the CSS Working Group (part of the Style Activity).
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
Wait until last call...
Since fonts defined via @font-face rules are loaded on
demand, pages may need to know precisely when fonts have completed
downloading before measuring text elements on the page or to show some
form of interim user interface state.
document interfaceTo allow font loading to be tracked explicitly within content the
following event target is added to the document of the page:
partial interface Document {
readonly attribute FontLoader fontloader;
};
FontLoader Interfacedictionary CSSFontFaceLoadEventInit : EventInit {
CSSFontFaceRule fontface = null;
DOMError error = null;
};
dictionary LoadFontParameters {
DOMString font;
DOMString text = " ";
FontsReadyCallback success;
FontsReadyCallback error;
};
[Constructor(DOMString type, optional CSSFontFaceLoadEventInit eventInitDict)]
interface CSSFontFaceLoadEvent : Event {
readonly attribute CSSFontFaceRule fontface;
readonly attribute DOMError? error = null;
}
callback FontsReadyCallback = void ();
interface FontLoader : EventTarget {
// -- events for when loading state changes
attribute EventHandler onloading;
attribute EventHandler onloadingdone;
// -- events for each individual font load
attribute EventHandler onloadstart;
attribute EventHandler onload;
attribute EventHandler onerror;
// check and start load if appropriate
// and fire callback when all loads complete
void loadFont(LoadFontParameters params);
// return whether all fonts in the fontlist are loaded
// (does not initiate load if not available)
boolean checkFont(DOMString font, optional DOMString text = " ");
// async notify upon completion, pending layout changes
void notifyWhenFontsReady(FontsReadyCallback fontsReadyCallback);
// loading state, true while one or more fonts loading, false otherwise
readonly attribute boolean loading;
};
Because font families defined with @font-face rules are
loaded only when they are used, content sometimes needs to understand when
the loading of fonts occurs. Authors can use the events and methods
defined here to allow greater control over actions that are dependent upon
the availability of specific fonts.
The term font load is used below to indicate
when the loading of content for a given @font-face rule
completes. An @font-face rule may list multiple alternate
resources within the ‘src’ descriptor,
including references to local fonts, but the term font load only refers to
the loading of the finally selected resource for a given rule, not to the
loading of each individual resource.
Given that the FontLoader object is defined to be attached to the document, how will canvas worker threads load fonts?
Some FontLoader methods, in particular loadFont, seem like a good fit for DOMFuture, a spec that hopefully will be ready within the next month or so. Should FontLoader be based on that or at least some parts of that? Do we need to decide this now?
Font load events are grouped into two general categories, events
associated with a group of fonts loading (loading, loading) or
finer-grained events associated with each individual font loaded (loadstart, load, error).
The following are the event handlers (and their corresponding event
handler event types) that must be supported by FontLoader
objects as IDL attributes:
| Event handler | Event handler event type |
|---|---|
onloading
| loading
|
onloadingdone
| loadingdone
|
onloadstart
| loadstart
|
onload
| load
|
onerror
| error
|
To fire a font load event named
e at a FontLoader target means to fire a
simple event named e using the
CSSFontFaceLoadEvent interface that also meets these
conditions:
fontface attribute is initialized to
the given font face rule.
error attribute is initialized to the
given error, if one occurred during the font load.
When the user agent determines that one or more fonts defined via
@font-face rules in a document doc need to be
loaded, it must run the following steps:
fontloader attribute of doc.
loading attribute of font
loader to true.
"loading" at
font loader with fontface set to
the first @font-face rule.
@font-face rule, it must fire a font load event named "loadstart" at
font loader with fontface set to
the given @font-face rule.
These steps imply that if fonts are loaded concurrently, the loading event will fire just once, while the loadstart event will be fired once for each
@font-face rule whose load is initiated. User agents must
only set the error attribute of a font load
event to a non-null value in the cases noted in this section.
The term “font load” covers any of the resources listed in the ‘src’ descriptor, including local fonts. When multiple resources are listed, the “font load” is the first resource in the list to successfully load or the error that occurs on the last resource for which a load is attempted.
When the user agent completes each font load for a document doc, it must run the following steps:
fontloader attribute of doc.
"load" at font
loader with fontface set to the
@font-face rule for which the font data was loaded.
"error" at font loader with fontface set to the @font-face rule
for which the error occurred. If the font data can't be loaded error is set to one of the standard
DOMError types (e.g. NotFoundError,
NetworkError). If the font data was downloaded but invalid,
then error is set to
"InvalidFontDataError". If several resources are listed in
the src descriptor, the error that caused the last font
resource in the list to fail must be used.
When the user agent completes the final font load for document doc, after all pending layout operations that might affect font selection have completed and no font loads are pending, it must run the following steps:
fontloader attribute of doc.
loading attribute of font
loader to false.
"loadingdone" at
font loader with fontface set to
the @font-face rule of the last font loaded.
For example, if three fonts are loaded at the same time, a "loading" event followed by three "loadstart" events and three "load" or "error"
events, followed by a "loadingdone" event will
occur.
Errors will go "unreported" when using the general category
of font load events (i.e. "loading" and "loadingdone"). This seems fine but need to confirm
this.
The methods loadFont and checkFont must determine whether all fonts in the
given font list have been loaded and are available. If all fonts are
available, checkFont must return true, false
if one or more fonts are not available. In the case of loadFont, if any fonts are downloadable fonts and
have not already been loaded, the user agent must initiate the load of
each of these fonts.
The loadFont(params) method must use these steps:
font member of
params, using the CSS value syntax of the
‘font’ property.
@font-face
rules, the use of ‘unicode-range’ means
that this may be more than just a single font face.
unicode-range’ values that don't intersect the
range of character values in the text member
of params and set this to be the font
load list.
success member
of params. If an error occurred with any one
of the fonts in the font load list or if the list is empty,
call the callback specified by the error
member of params.
Callbacks for loadFont fire in addition to
the callbacks that fire due to font event handlers.
The checkFont(font,
text) method must use these steps:
font parameter,
using the CSS value syntax of the ‘font’
property.
false.
@font-face
rules, the use of ‘unicode-range’ means
that this may be more than just a single font face.
unicode-range’ values that don't intersect the
range of character values in the text
parameter and set this to be the font load list.
false.
true.
Otherwise, return false.
The font parameter of checkFont and the font
member of params parameter of loadFont both specify the list of fonts to load.
These values must be parsed using the same syntax as values for the CSS
‘font’ property, the same way the font attribute of the
CanvasRenderingContext2D is interpreted. [HTML5] This yields a list of font
families along with font style attributes.
Because the number of fonts loaded depends on the how many fonts are
used for a given piece of text, in some cases whether fonts need to be
loaded or not may not be known. The notifyWhenFontsReady method provides a way for
authors to avoid having to keep track of which fonts have or haven't been
loaded before examining content affected by which font is used.
The notifyWhenFontsReady(fontsReadyCallback)
method must use these steps:
fontloader attribute of doc.
fontsReadyCallback
parameter to the notify callback list of the font
loader and return.
"loadingdone" event fires, call
each of the callbacks in the notify pending list and clear out
the notify pending list.
Authors should note here that the callback only fires once, the method
needs to be called again when further font loads might occur. This method
is similar to the callback function of the "loadingdone" event handler, except that in this
case the callback will always get called, even when no
font loads occur because the fonts in question are already loaded. It's a
simple, easy way to sync code to font loads without the need to keep track
of what fonts are needed and precisely when they load.
Note that the user agent may need to iterate over multiple font loads before the notify callback is called. This can occur with font fallback situations, where one font in the fontlist is loaded but doesn't contain a particular glyph and other fonts in the fontlist need to be loaded. The notify callback only fires after layout operations complete and no additional font loads are necessary.
To show content only after all font loads complete:
document.fontloader.onloadingdone = function() {
var content = document.getElementById("content");
content.style.visibility = "visible";
}
Drawing text in a canvas with a downloadable font, explicitly initiating the font download and drawing upon completion:
function drawStuff() {
var ctx = document.getElementById("c").getContext("2d");
ctx.fillStyle = "red";
ctx.font = "50px MyDownloadableFont";
ctx.fillText("Hello!", 100, 100);
}
document.fontloader.loadFont({font: "50px MyDownloadableFont",
success: drawStuff,
error: handleError});
A rich text editing application may need to measure text elements after editing operations have taken place. Since style changes may or may not require additional fonts to be downloaded, or the fonts may already have been downloaded, the measurement procedures need to occur after those font loads complete:
function measureTextElements() {
// contents can now be measured using the metrics of
// the downloadable font(s)
}
function doEditing() {
// content/layout operations that may cause additional font loads
document.fontloader.notifyWhenFontsReady(measureTextElements);
}
Unlike the per-font load events, the "loadingdone" event only fires after all font
related loads have completed and text has been laid out
without causing additional font loads:
@font-face {
font-family: latin-serif;
src: url(latinserif.woff) format("woff"); /* contains no kanji/kana */
}
@font-face {
font-family: jpn-mincho;
src: url(mincho.woff) format("woff");
}
body { font-family: latin-serif, jpn-mincho; }
<p>納豆はいかがでしょうか</p>
In this situation, the user agent first downloads ‘latinserif.woff’ and then tries to use this to draw
the Japanese text. But because no Japanese glyphs are present in that
font, fallback occurs and the font ‘mincho.woff’ is downloaded. Only after the second font
is downloaded and the Japanese text laid out does the "loadingdone" event fire.
Major changes include:
Several members of the Google Fonts team provided helpful feedback on font load events, as did Boris Zbarsky, Jonas Sicking and ms2ger.
Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.
All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for
example” or are set apart from the normative text with
class="example", like this:
This is an example of an informative example.
Informative notes begin with the word “Note” and are set apart from
the normative text with class="note", like this:
Note, this is an informative note.
Conformance to CSS Font Load Events Level 3 Module is defined for three conformance classes:
A style sheet is conformant to CSS Font Load Events Level 3 Module if all of its declarations that use properties defined in this module have values that are valid according to the generic CSS grammar and the individual grammars of each property as given in this module.
A renderer is conformant to CSS Font Load Events Level 3 Module if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by CSS Font Load Events Level 3 Module by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)
An authoring tool is conformant to CSS Font Load Events Level 3 Module if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.
So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.
To avoid clashes with future CSS features, the CSS2.1 specification reserves a prefixed syntax for proprietary and experimental extensions to CSS.
Prior to a specification reaching the Candidate Recommendation stage in the W3C process, all implementations of a CSS feature are considered experimental. The CSS Working Group recommends that implementations use a vendor-prefixed syntax for such features, including those in W3C Working Drafts. This avoids incompatibilities with future changes in the draft.
Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.
To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.
Further information on submitting testcases and implementation reports can be found from on the CSS Working Group's website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.