Sun, 31 Jan 2016 15:42:31 -0800
change //dev.w3.org/csswg/ urls to //drafts.csswg.org/
jackalmage@10009 | 1 | <h1>CSS Font Loading Module Level 3</h1> |
jackalmage@8992 | 2 | |
jackalmage@8992 | 3 | <pre class='metadata'> |
jackalmage@10009 | 4 | Shortname: css-font-loading |
jackalmage@13979 | 5 | Level: 3 |
jackalmage@9499 | 6 | Group: csswg |
jackalmage@14063 | 7 | Status: ED |
jackalmage@15674 | 8 | Work Status: Exploring |
peter@16986 | 9 | ED: https://drafts.csswg.org/css-font-loading/ |
jackalmage@10012 | 10 | TR: http://w3.org/TR/css-font-loading/ |
jackalmage@14063 | 11 | Previous Version: http://www.w3.org/TR/2014/WD-css-font-loading-3-20140522/ |
jackalmage@8992 | 12 | Editor: Tab Atkins Jr., Google, http://xanthir.com/contact/ |
jackalmage@9496 | 13 | Former Editor: John Daggett, Mozilla, [email protected] |
jackalmage@8992 | 14 | Abstract: This CSS module describes events and interfaces used for dynamically loading font resources. |
jackalmage@15466 | 15 | Link Defaults: css-fonts-3 (descriptor) src, dom-ls (interface) Event, typedarray (interface) ArrayBuffer/ArrayBufferView |
jackalmage@15974 | 16 | Ignored Terms: EventHandler, InvalidModificationError, WorkerGlobalScope, CanvasProxy, Document, add(), src |
jackalmage@8992 | 17 | </pre> |
jackalmage@8992 | 18 | |
jackalmage@16463 | 19 | <pre class="link-defaults"> |
jackalmage@16463 | 20 | spec:dom-ls; type:interface; text:EventTarget |
jackalmage@16463 | 21 | </pre> |
jackalmage@16463 | 22 | |
jackalmage@8992 | 23 | <h2 id="introduction"> |
jackalmage@8992 | 24 | Introduction</h2> |
jackalmage@8992 | 25 | |
jackalmage@10011 | 26 | CSS allows authors to load custom fonts from the web via the ''@font-face'' rule. |
jackalmage@10011 | 27 | While this is easy to use when authoring a stylesheet, |
jackalmage@10011 | 28 | it's much more difficult to use dynamically via scripting. |
jackalmage@10011 | 29 | |
jackalmage@10011 | 30 | Further, CSS allows the user agent to choose when to actually load a font; |
jackalmage@10011 | 31 | if a font face isn't <em>currently</em> used by anything on a page, |
jackalmage@10011 | 32 | most user agents will not download its associated file. |
jackalmage@10011 | 33 | This means that later use of the font face will incur a delay |
jackalmage@10011 | 34 | as the user agent finally notices a usage and begins downloading and parsing the font file. |
jackalmage@10011 | 35 | |
jackalmage@10011 | 36 | This specification defines a scripting interface to font faces in CSS, |
jackalmage@10011 | 37 | allowing font faces to be easily created and loaded from script. |
jackalmage@10011 | 38 | It also provides methods to track the loading status of an individual font, |
jackalmage@10011 | 39 | or of all the fonts on an entire page. |
jackalmage@8992 | 40 | |
jackalmage@14167 | 41 | Issue: Several things in this spec use normal ES objects to define behavior, |
jackalmage@14167 | 42 | such as various things using Promises internally, |
jackalmage@14167 | 43 | and FontFaceSet using a Set internally. |
jackalmage@14167 | 44 | I believe the intention here is that these objects |
jackalmage@14167 | 45 | (and their prototype chains) are pristine, |
jackalmage@14167 | 46 | unaffected by anything the author has done. |
jackalmage@14167 | 47 | Is this a good intention? |
jackalmage@14167 | 48 | If so, how should I indicate this in the spec? |
jackalmage@14167 | 49 | |
jackalmage@10101 | 50 | <h3 id="values"> |
jackalmage@10101 | 51 | Values</h3> |
jackalmage@10101 | 52 | |
jackalmage@15132 | 53 | This specification uses <dfn interface lt="Promise">Promises</dfn>, |
jackalmage@13948 | 54 | which are defined in <a href="http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts">ECMAScript 6</a>. |
jackalmage@10101 | 55 | HTML5Rocks has some <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">good tutorial material introducing Promises</a>. |
jackalmage@10101 | 56 | |
jackalmage@14216 | 57 | <h3 id='task-source'> |
jackalmage@14216 | 58 | Task Sources</h3> |
jackalmage@14216 | 59 | |
jackalmage@14216 | 60 | Whenever this specification queues a task, |
jackalmage@14216 | 61 | it queues it onto the "font loading" task source. |
jackalmage@14216 | 62 | |
jackalmage@14019 | 63 | <!-- |
jackalmage@14019 | 64 | ââââââââ âââââââ ââ ââ ââââââââ ââââââââ âââ ââââââ ââââââââ |
jackalmage@14020 | 65 | ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 66 | ââ ââ ââ ââââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 67 | ââââââ ââ ââ ââ ââ ââ ââ ââââââ ââ ââ ââ ââââââ |
jackalmage@14020 | 68 | ââ ââ ââ ââ ââââ ââ ââ âââââââââ ââ ââ |
jackalmage@14020 | 69 | ââ ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 70 | ââ âââââââ ââ ââ ââ ââ ââ ââ ââââââ ââââââââ |
jackalmage@14019 | 71 | --> |
jackalmage@14019 | 72 | |
jackalmage@9045 | 73 | <h2 id="fontface-interface"> |
jackalmage@9045 | 74 | The <code>FontFace</code> Interface</h2> |
jackalmage@9018 | 75 | |
jackalmage@14551 | 76 | The {{FontFace}} interface represents a single usable font face. |
jackalmage@9018 | 77 | CSS ''@font-face'' rules implicitly define FontFace objects, |
jackalmage@9018 | 78 | or they can be constructed manually from a url or binary data. |
jackalmage@9018 | 79 | |
jackalmage@9018 | 80 | <pre class="idl"> |
jackalmage@9018 | 81 | typedef (ArrayBuffer or ArrayBufferView) BinaryData; |
jackalmage@9018 | 82 | |
jackalmage@9018 | 83 | dictionary FontFaceDescriptors { |
jackalmage@9018 | 84 | DOMString style = "normal"; |
jackalmage@9018 | 85 | DOMString weight = "normal"; |
jackalmage@9018 | 86 | DOMString stretch = "normal"; |
jackalmage@9018 | 87 | DOMString unicodeRange = "U+0-10FFFF"; |
jackalmage@9018 | 88 | DOMString variant = "normal"; |
jackalmage@9018 | 89 | DOMString featureSettings = "normal"; |
jackalmage@9018 | 90 | }; |
jackalmage@9018 | 91 | |
jackalmage@9018 | 92 | enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" }; |
jackalmage@9018 | 93 | |
jackalmage@9019 | 94 | [Constructor(DOMString family, (DOMString or BinaryData) source, |
jackalmage@14641 | 95 | optional FontFaceDescriptors descriptors), |
jackalmage@14064 | 96 | Exposed=Window,Worker] |
jackalmage@9018 | 97 | interface FontFace { |
jackalmage@9018 | 98 | attribute DOMString family; |
jackalmage@9018 | 99 | attribute DOMString style; |
jackalmage@9018 | 100 | attribute DOMString weight; |
jackalmage@9018 | 101 | attribute DOMString stretch; |
jackalmage@9018 | 102 | attribute DOMString unicodeRange; |
jackalmage@9018 | 103 | attribute DOMString variant; |
jackalmage@9018 | 104 | attribute DOMString featureSettings; |
jackalmage@9018 | 105 | |
jackalmage@9024 | 106 | readonly attribute FontFaceLoadStatus status; |
jackalmage@9018 | 107 | |
jackalmage@13945 | 108 | Promise<FontFace> load(); |
jackalmage@14334 | 109 | readonly attribute Promise<FontFace> loaded; |
jackalmage@9018 | 110 | }; |
jackalmage@9018 | 111 | </pre> |
jackalmage@9018 | 112 | |
jackalmage@14335 | 113 | Issue: Other APIs use other names for .loaded, like .readyState. Can we align? |
jackalmage@14335 | 114 | |
jackalmage@14335 | 115 | Issue: "unloaded" is usually used for things that start loaded and then become not loaded. |
jackalmage@14335 | 116 | Can we rename that value? |
jackalmage@14335 | 117 | Media stuff uses "none", other APIs use "empty", "idle", "nothing". |
jackalmage@14335 | 118 | |
jackalmage@16171 | 119 | Issue: Clarify all mentions of "the document" to be clear about which document is being referenced, |
jackalmage@16171 | 120 | since objects can move between documents. |
jackalmage@16171 | 121 | |
jackalmage@14828 | 122 | <div dfn-type=attribute dfn-for=FontFace> |
jackalmage@14802 | 123 | : <dfn>family</dfn> |
jackalmage@14802 | 124 | : <dfn>style</dfn> |
jackalmage@14802 | 125 | : <dfn>weight</dfn> |
jackalmage@14802 | 126 | : <dfn>stretch</dfn> |
jackalmage@14802 | 127 | : <dfn>unicodeRange</dfn> |
jackalmage@14802 | 128 | :: |
jackalmage@9018 | 129 | These attributes all represent the corresponding aspects of a font face, |
jackalmage@9018 | 130 | as defined by the descriptors defined in the CSS ''@font-face'' rule. |
jackalmage@9018 | 131 | They are parsed the same as the corresponding ''@font-face'' descriptors. |
jackalmage@9018 | 132 | They are used by the font matching algorithm, |
jackalmage@9018 | 133 | but otherwise have no effect. |
jackalmage@9018 | 134 | |
jackalmage@14551 | 135 | For example, a {{FontFace}} with a {{FontFace/style}} of <code>"italic"</code> |
jackalmage@9018 | 136 | <em>represents</em> an italic font face; |
jackalmage@9018 | 137 | it does not <strong>make</strong> the font face italic. |
jackalmage@9018 | 138 | |
jackalmage@14092 | 139 | On getting, return the string associated with this attribute. |
jackalmage@14092 | 140 | |
jackalmage@14092 | 141 | On setting, parse the string according to the grammar for the CSS ''@font-face'' rule. |
jackalmage@14092 | 142 | If it does not match the grammar, |
jackalmage@14120 | 143 | throw a SyntaxError; |
jackalmage@14121 | 144 | otherwise, set the attribute to the serialization of the parsed value. |
jackalmage@14092 | 145 | |
jackalmage@14802 | 146 | : <dfn>variant</dfn> |
jackalmage@14802 | 147 | : <dfn>featureSettings</dfn> |
jackalmage@14802 | 148 | :: |
jackalmage@9018 | 149 | These attributes have the same meaning, |
jackalmage@9018 | 150 | and are parsed the same as, |
jackalmage@9018 | 151 | the corresponding descriptors in the CSS ''@font-face'' rules. |
jackalmage@9018 | 152 | |
jackalmage@9018 | 153 | They turn on or off specific features in fonts that support them. |
jackalmage@9018 | 154 | Unlike the previous attributes, |
jackalmage@9018 | 155 | these attributes actually affect the font face. |
jackalmage@9018 | 156 | |
jackalmage@14092 | 157 | On getting, return the string associated with this attribute. |
jackalmage@14092 | 158 | |
jackalmage@14092 | 159 | On setting, parse the string according to the grammar for the CSS ''@font-face'' rule. |
jackalmage@14092 | 160 | If it does not match the grammar, |
jackalmage@14120 | 161 | throw a SyntaxError; |
jackalmage@14121 | 162 | otherwise, set the attribute to the serialization of the parsed value. |
jackalmage@14092 | 163 | |
jackalmage@14802 | 164 | : <dfn>status</dfn> |
jackalmage@14802 | 165 | :: |
jackalmage@9018 | 166 | This attribute reflects the current status of the font face. |
jackalmage@14551 | 167 | It must be "unloaded" for a newly-created {{FontFace}}. |
jackalmage@9024 | 168 | |
jackalmage@9024 | 169 | It can change due to an author explicitly requesting a font face to load, |
jackalmage@14551 | 170 | such as through the {{FontFace/load()}} method on {{FontFace}}, |
jackalmage@9024 | 171 | or implicitly by the user agent, |
jackalmage@9024 | 172 | due to it detecting that the font face is needed to draw some text on the screen. |
jackalmage@13635 | 173 | |
jackalmage@14802 | 174 | : <dfn>loaded</dfn> |
jackalmage@14802 | 175 | :: |
jackalmage@14551 | 176 | This attribute reflects the {{[[FontStatusPromise]]}} of the font face. |
jackalmage@14802 | 177 | </div> |
jackalmage@9018 | 178 | |
jackalmage@14551 | 179 | All {{FontFace}} objects contain an internal <dfn attribute for=FontFace>\[[FontStatusPromise]]</dfn> slot, |
jackalmage@9018 | 180 | which tracks the status of the font. |
jackalmage@9018 | 181 | It starts out pending, |
jackalmage@9018 | 182 | and fulfills or rejects when the font is successfully loaded and parsed, or hits an error. |
jackalmage@9018 | 183 | |
jackalmage@14551 | 184 | All {{FontFace}} objects also contain |
jackalmage@14551 | 185 | internal <dfn attribute for=FontFace>\[[Urls]]</dfn> and <dfn attribute for=FontFace>\[[Data]]</dfn> slots, |
jackalmage@14336 | 186 | of which one is <code>null</code> and the other is not <code>null</code> |
jackalmage@14336 | 187 | (the non-null one is set by the constructor, |
jackalmage@14336 | 188 | based on which data is passed in). |
jackalmage@9018 | 189 | |
jackalmage@14019 | 190 | <!-- |
jackalmage@14020 | 191 | ââââââ âââââââ ââ ââ ââââââ ââââââââ ââââââââ ââ ââ ââââââ ââââââââ âââââââ ââââââââ |
jackalmage@14019 | 192 | ââ ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 193 | ââ ââ ââ ââââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 194 | ââ ââ ââ ââ ââ ââ ââââââ ââ ââââââââ ââ ââ ââ ââ ââ ââ ââââââââ |
jackalmage@14020 | 195 | ââ ââ ââ ââ ââââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 196 | ââ ââ ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 197 | ââââââ âââââââ ââ ââ ââââââ ââ ââ ââ âââââââ ââââââ ââ âââââââ ââ ââ |
jackalmage@14019 | 198 | --> |
jackalmage@14019 | 199 | |
jackalmage@9045 | 200 | <h3 id='font-face-constructor'> |
jackalmage@9045 | 201 | The Constructor</h3> |
jackalmage@9018 | 202 | |
jackalmage@14551 | 203 | A {{FontFace}} can be constructed either |
jackalmage@9019 | 204 | from a URL pointing to a font face file, |
jackalmage@9019 | 205 | or from an ArrayBuffer (or ArrayBufferView) containing the binary representation of a font face. |
jackalmage@9018 | 206 | |
jackalmage@15132 | 207 | When the <dfn constructor lt='FontFace()' for=FontFace>FontFace</dfn>( |
jackalmage@14842 | 208 | <span dfn-for="FontFace/FontFace(family, source, descriptors)"> |
jackalmage@14842 | 209 | DOMString <dfn argument>family</dfn>, |
jackalmage@14842 | 210 | (DOMString or {{/BinaryData}}) <dfn argument>source</dfn>, |
jackalmage@14842 | 211 | {{/FontFaceDescriptors}} <dfn argument>descriptors</dfn> |
jackalmage@14842 | 212 | </span> |
jackalmage@14842 | 213 | ) |
jackalmage@14842 | 214 | method is called, |
jackalmage@9019 | 215 | execute these steps: |
jackalmage@9018 | 216 | |
jackalmage@14552 | 217 | 1. Let <var>font face</var> be a fresh {{FontFace}} object. |
jackalmage@14552 | 218 | Set <var>font face's</var> {{FontFace/status}} attribute to <code>"unloaded"</code>, |
jackalmage@14552 | 219 | Set its internal {{[[FontStatusPromise]]}} slot to a fresh pending {{Promise}} object. |
jackalmage@14208 | 220 | |
jackalmage@14666 | 221 | Parse the {{family!!argument}} argument, |
jackalmage@14666 | 222 | and the members of the {{descriptors!!argument}} argument, |
jackalmage@14552 | 223 | according to the grammars of the corresponding descriptors of the CSS ''@font-face'' rule. |
jackalmage@15409 | 224 | If the {{source!!argument}} argument is a {{DOMString}}, |
jackalmage@15409 | 225 | parse it according to the grammar of the CSS ''@font-face/src'' descriptor of the ''@font-face'' rule. |
jackalmage@14552 | 226 | If any of them fail to parse correctly, |
jackalmage@14552 | 227 | reject <var>font face's</var> {{[[FontStatusPromise]]}} with a DOMException named "SyntaxError", |
jackalmage@14552 | 228 | set <var>font faceâs</var> corresponding attributes to the empty string, |
jackalmage@14552 | 229 | and set <var>font faceâs</var> {{FontFace/status}} attribute to "error". |
jackalmage@14552 | 230 | Otherwise, set <var>font face's</var> corresponding attributes to the serialization of the parsed values. |
jackalmage@14209 | 231 | |
jackalmage@14552 | 232 | Note: Note that this means that passing a naked url as the source argument, |
jackalmage@14552 | 233 | like <code>"http://example.com/myFont.woff"</code>, |
jackalmage@14552 | 234 | won't work - it needs to be at least wrapped in a ''url()'' function, |
jackalmage@14552 | 235 | like <code>"url(http://example.com/myFont.woff)"</code>. |
jackalmage@14552 | 236 | In return for this inconvenience, |
jackalmage@14552 | 237 | you get to specify multiple fallbacks, |
jackalmage@14552 | 238 | specify the type of font each fallback is, |
jackalmage@14552 | 239 | and refer to local fonts easily. |
jackalmage@9018 | 240 | |
jackalmage@14552 | 241 | Issue: Need to define the base url, |
jackalmage@14552 | 242 | so relative urls can resolve. |
jackalmage@14552 | 243 | Should it be the url of the document? |
jackalmage@14552 | 244 | Is that correct for workers too, |
jackalmage@14552 | 245 | or should they use their worker url? |
jackalmage@14552 | 246 | Is that always defined? |
jackalmage@14122 | 247 | |
jackalmage@15409 | 248 | Return <var>font face</var>. |
jackalmage@15409 | 249 | If <var>font faceâs</var> {{FontFace/status}} is "error", |
jackalmage@15409 | 250 | terminate this algorithm; |
jackalmage@15409 | 251 | otherwise, |
jackalmage@15409 | 252 | complete the rest of these steps asynchronously. |
jackalmage@15409 | 253 | |
jackalmage@15409 | 254 | 2. If the {{source!!argument}} argument was a {{DOMString}}, |
jackalmage@15409 | 255 | set <var>font face's</var> internal {{[[Urls]]}} slot to the string. |
jackalmage@15409 | 256 | |
jackalmage@14552 | 257 | If the {{source}} argument was a {{BinaryData}}, |
jackalmage@14552 | 258 | set <var>font face's</var> internal {{[[Data]]}} slot to the passed argument. |
jackalmage@9018 | 259 | |
jackalmage@14552 | 260 | 3. If <var>font face's</var> {{[[Data]]}} slot is not <code>null</code>, |
jackalmage@15424 | 261 | queue a task to run the following steps synchronously: |
jackalmage@15424 | 262 | |
jackalmage@15424 | 263 | 1. Set <var>font face's</var> {{FontFace/status}} attribute to "loading". |
jackalmage@15424 | 264 | 2. For each {{FontFaceSet}} <var>font face</var> is in: |
jackalmage@15424 | 265 | 1. If the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list is empty, |
jackalmage@15424 | 266 | <a>switch the FontFaceSet to loading</a>. |
jackalmage@15424 | 267 | 2. Append <var>font face</var> to the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 268 | |
jackalmage@15424 | 269 | Asynchronously, attempt to parse the data in it as a font. |
jackalmage@14552 | 270 | When this is completed, |
jackalmage@14552 | 271 | successfully or not, |
jackalmage@14552 | 272 | queue a task to run the following steps synchronously: |
jackalmage@14015 | 273 | |
jackalmage@14552 | 274 | 1. If the load was successful, |
jackalmage@14552 | 275 | <var>font face</var> now represents the parsed font; |
jackalmage@14552 | 276 | fulfill <var>font face's</var> {{[[FontStatusPromise]]}} with <var>font face</var>, |
jackalmage@14552 | 277 | and set its {{FontFace/status}} attribute to "loaded". |
jackalmage@14015 | 278 | |
jackalmage@15424 | 279 | For each {{FontFaceSet}} <var>font face</var> is in: |
jackalmage@15424 | 280 | 1. Add <var>font face</var> to the {{FontFaceSet}}âs {{[[LoadedFonts]]}} list. |
jackalmage@15424 | 281 | 2. Remove <var>font face</var> from the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 282 | If <var>font</var> was the last item in that list |
jackalmage@15424 | 283 | (and so the list is now empty), |
jackalmage@15424 | 284 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@15424 | 285 | |
jackalmage@14552 | 286 | 2. Otherwise, |
jackalmage@14552 | 287 | reject <var>font face's</var> {{[[FontStatusPromise]]}} with a DOMException named "SyntaxError" |
jackalmage@14552 | 288 | and set <var>font face's</var> {{FontFace/status}} attribute to "error". |
jackalmage@9019 | 289 | |
jackalmage@15424 | 290 | For each {{FontFaceSet}} <var>font face</var> is in: |
jackalmage@15424 | 291 | 1. Add <var>font face</var> to the {{FontFaceSet}}âs {{[[FailedFonts]]}} list. |
jackalmage@15424 | 292 | 2. Remove <var>font face</var> from the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 293 | If <var>font</var> was the last item in that list |
jackalmage@15424 | 294 | (and so the list is now empty), |
jackalmage@15424 | 295 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@15424 | 296 | |
jackalmage@13480 | 297 | Note: Newly constructed FontFace objects are not automatically added |
jackalmage@13480 | 298 | to the FontFaceSet associated with a document |
jackalmage@13480 | 299 | or a context for a worker thread. |
jackalmage@13480 | 300 | This means that while newly constructed fonts can be preloaded, |
jackalmage@13480 | 301 | they cannot actually be used until they are explicitly added to a FontFaceSet. |
jackalmage@13480 | 302 | See the following section for a more complete description of FontFaceSet. |
jackalmage@10100 | 303 | |
jackalmage@14019 | 304 | <!-- |
jackalmage@14020 | 305 | ââ âââââââ âââ ââââââââ âââ âââ |
jackalmage@14020 | 306 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 307 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 308 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 309 | ââ ââ ââ âââââââââ ââ ââ ââ ââ |
jackalmage@14020 | 310 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 311 | ââââââââ âââââââ ââ ââ ââââââââ âââ âââ |
jackalmage@14019 | 312 | --> |
jackalmage@14019 | 313 | |
jackalmage@9045 | 314 | <h3 id='font-face-load'> |
jackalmage@9045 | 315 | The <code>load()</code> method</h3> |
jackalmage@9019 | 316 | |
jackalmage@14551 | 317 | The {{FontFace/load()}} method of {{FontFace}} |
jackalmage@9034 | 318 | forces a url-based font face to request its font data and load. |
jackalmage@9034 | 319 | For fonts constructed from binary data, |
jackalmage@9034 | 320 | or fonts that are already loading or loaded, |
jackalmage@9034 | 321 | it does nothing. |
jackalmage@9034 | 322 | |
jackalmage@9025 | 323 | When the <dfn method for=FontFace>load()</dfn> method is called, |
jackalmage@9025 | 324 | execute these steps: |
jackalmage@9019 | 325 | |
jackalmage@15424 | 326 | <ol> |
jackalmage@9019 | 327 | <li> |
jackalmage@14551 | 328 | Let <var>font face</var> be the {{FontFace}} object on which this method was called. |
jackalmage@9018 | 329 | |
jackalmage@9019 | 330 | <li> |
jackalmage@14551 | 331 | If <var>font face's</var> {{[[Urls]]}} slot is <code>null</code>, |
jackalmage@14551 | 332 | or its {{FontFace/status}} attribute is anything other than <code>"unloaded"</code>, |
jackalmage@14551 | 333 | return <var>font face's</var> {{[[FontStatusPromise]]}} |
jackalmage@10102 | 334 | and abort these steps. |
jackalmage@9018 | 335 | |
jackalmage@9019 | 336 | <li> |
jackalmage@9495 | 337 | Otherwise, |
jackalmage@14551 | 338 | set <var>font face's</var> {{FontFace/status}} attribute to "loading", |
jackalmage@14551 | 339 | return <var>font face's</var> {{[[FontStatusPromise]]}}, |
jackalmage@10102 | 340 | and continue executing the rest of this algorithm asynchronously. |
jackalmage@9018 | 341 | |
jackalmage@9019 | 342 | <li> |
jackalmage@14551 | 343 | Using the value of <var>font face's</var> {{[[Urls]]}} slot, |
jackalmage@14762 | 344 | attempt to load a font as defined in [[!CSS-FONTS-3]], |
jackalmage@9025 | 345 | as if it was the value of a ''@font-face'' rule's 'src' descriptor. |
jackalmage@9018 | 346 | |
jackalmage@9019 | 347 | <li> |
jackalmage@14015 | 348 | When the load operation completes, |
jackalmage@14015 | 349 | successfully or not, |
jackalmage@14126 | 350 | queue a task to run the following steps synchronously: |
jackalmage@9018 | 351 | |
jackalmage@14015 | 352 | <ol> |
jackalmage@14015 | 353 | <li> |
jackalmage@14015 | 354 | If the attempt to load fails, |
jackalmage@14551 | 355 | reject <var>font face's</var> {{[[FontStatusPromise]]}} with |
jackalmage@14065 | 356 | a DOMException whose name is "NetworkError" |
jackalmage@14551 | 357 | and set <var>font face's</var> {{FontFace/status}} attribute to "error". |
jackalmage@14015 | 358 | |
jackalmage@15424 | 359 | For each {{FontFaceSet}} <var>font face</var> is in: |
jackalmage@15424 | 360 | 1. Add <var>font face</var> to the {{FontFaceSet}}âs {{[[FailedFonts]]}} list. |
jackalmage@15424 | 361 | 2. Remove <var>font face</var> from the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 362 | If <var>font</var> was the last item in that list |
jackalmage@15424 | 363 | (and so the list is now empty), |
jackalmage@15424 | 364 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@15424 | 365 | |
jackalmage@14015 | 366 | <li> |
jackalmage@14015 | 367 | Otherwise, |
jackalmage@14015 | 368 | <var>font face</var> now represents the loaded font; |
jackalmage@14551 | 369 | fulfill <var>font face's</var> {{[[FontStatusPromise]]}} with <var>font face</var> |
jackalmage@14551 | 370 | and set <var>font face's</var> {{FontFace/status}} attribute to "loaded". |
jackalmage@15424 | 371 | |
jackalmage@15424 | 372 | For each {{FontFaceSet}} <var>font face</var> is in: |
jackalmage@15424 | 373 | 1. Add <var>font face</var> to the {{FontFaceSet}}âs {{[[LoadedFonts]]}} list. |
jackalmage@15424 | 374 | 2. Remove <var>font face</var> from the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 375 | If <var>font</var> was the last item in that list |
jackalmage@15424 | 376 | (and so the list is now empty), |
jackalmage@15424 | 377 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@14015 | 378 | </ol> |
jackalmage@9019 | 379 | </ol> |
jackalmage@9019 | 380 | |
jackalmage@9030 | 381 | User agents can initiate font loads on their own, |
jackalmage@9030 | 382 | whenever they determine that a given font face is necessary to render something on the page. |
jackalmage@9030 | 383 | When this happens, |
jackalmage@14551 | 384 | they must act as if they had called the corresponding {{FontFace}}âs {{FontFace/load()}} method described here. |
jackalmage@9030 | 385 | |
jackalmage@14579 | 386 | Note: Some UAs utilize a "font cache" |
jackalmage@14579 | 387 | which avoids having to download the same font multiple times |
jackalmage@14579 | 388 | on a page or on multiple pages within the same origin. |
jackalmage@14579 | 389 | Multiple {{FontFace}} objects can be mapped to the same entry in the font cache, |
jackalmage@14579 | 390 | which means that a {{FontFace}} object might start loading unexpectedly, |
jackalmage@14579 | 391 | even if it's not in a {{FontFaceSet}}, |
jackalmage@14579 | 392 | because some other {{FontFace}} object pointing to the same font data |
jackalmage@14579 | 393 | (perhaps on a different page entirely!) |
jackalmage@14579 | 394 | has been loaded. |
jackalmage@14579 | 395 | |
jackalmage@9045 | 396 | <h3 id='font-face-css-connection'> |
jackalmage@9047 | 397 | Interaction with CSSâs ''@font-face'' Rule</h3> |
jackalmage@9024 | 398 | |
jackalmage@14551 | 399 | A CSS ''@font-face'' rule automatically defines a corresponding {{FontFace}} object, |
jackalmage@10099 | 400 | which is automatically placed in the document's <a>font source</a> |
jackalmage@10099 | 401 | when the rule is parsed. |
jackalmage@14551 | 402 | This {{FontFace}} object is <dfn>CSS-connected</dfn>. |
jackalmage@9024 | 403 | |
jackalmage@14551 | 404 | The {{FontFace}} object corresponding to a ''@font-face'' rule |
jackalmage@14551 | 405 | has its {{FontFace/family}}, {{FontFace/style}}, {{FontFace/weight}}, {{FontFace/stretch}}, {{FontFace/unicodeRange}}, {{FontFace/variant}}, and {{FontFace/featureSettings}} attributes |
jackalmage@10011 | 406 | set to the same value as the corresponding descriptors in the ''@font-face'' rule. |
jackalmage@9024 | 407 | There is a two-way connection between the two: |
jackalmage@14551 | 408 | any change made to a ''@font-face'' descriptor is immediately reflected in the corresponding {{FontFace}} attribute, |
jackalmage@9024 | 409 | and vice versa. |
jackalmage@9024 | 410 | |
jackalmage@16171 | 411 | Issue: When a FontFace is transferred between documents, it's no longer CSS-connected. |
jackalmage@16171 | 412 | |
jackalmage@14551 | 413 | The internal {{[[Urls]]}} slot of the {{FontFace}} object is set to the value of the ''@font-face'' rule's 'src' descriptor, |
jackalmage@9024 | 414 | and reflects any changes made to the 'src' descriptor. |
jackalmage@9024 | 415 | |
jackalmage@14551 | 416 | Otherwise, a {{FontFace}} object created by a CSS ''@font-face'' rule is identical to one created manually. |
jackalmage@9024 | 417 | |
jackalmage@14551 | 418 | If a ''@font-face'' rule is removed from the document, its corresponding {{FontFace}} object is no longer <a>CSS-connected</a>. |
jackalmage@10011 | 419 | The connection is not restorable by any means |
jackalmage@14551 | 420 | (but adding the ''@font-face'' back to the stylesheet will create a brand new {{FontFace}} object which <em>is</em> <a>CSS-connected</a>). |
jackalmage@9104 | 421 | |
jackalmage@14612 | 422 | If a ''@font-face'' rule has its '@font-face/src' descriptor changed to a new value, |
jackalmage@14612 | 423 | the original connected {{FontFace}} object must stop being <a>CSS-connected</a>. |
jackalmage@14612 | 424 | A new {{FontFace}} reflecting its new '@font-face/src' must be created |
jackalmage@14612 | 425 | and <a>CSS-connected</a> to the ''@font-face''. |
jackalmage@14613 | 426 | (This will also remove the old and add the new {{FontFace}} objects from any <a>font sources</a> they appear in.) |
jackalmage@14612 | 427 | |
jackalmage@14019 | 428 | <!-- |
jackalmage@14019 | 429 | ââââââââ âââââââ ââ ââ ââââââââ ââââââââ âââ ââââââ ââââââââ ââââââ ââââââââ ââââââââ |
jackalmage@14020 | 430 | ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 431 | ââ ââ ââ ââââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 432 | ââââââ ââ ââ ââ ââ ââ ââ ââââââ ââ ââ ââ ââââââ ââââââ ââââââ ââ |
jackalmage@14020 | 433 | ââ ââ ââ ââ ââââ ââ ââ âââââââââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 434 | ââ ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 435 | ââ âââââââ ââ ââ ââ ââ ââ ââ ââââââ ââââââââ ââââââ ââââââââ ââ |
jackalmage@14019 | 436 | --> |
jackalmage@9045 | 437 | |
jackalmage@9045 | 438 | <h2 id="FontFaceSet-interface"> |
jackalmage@9045 | 439 | The <code>FontFaceSet</code> Interface</h2> |
jackalmage@8992 | 440 | |
jackalmage@8992 | 441 | <pre class="idl"> |
jackalmage@14125 | 442 | dictionary FontFaceSetLoadEventInit : EventInit { |
jackalmage@14093 | 443 | sequence<FontFace> fontfaces = []; |
jackalmage@8992 | 444 | }; |
jackalmage@8992 | 445 | |
jackalmage@14125 | 446 | [Constructor(DOMString type, optional FontFaceSetLoadEventInit eventInitDict), |
jackalmage@14124 | 447 | Exposed=Window,Worker] |
jackalmage@14125 | 448 | interface FontFaceSetLoadEvent : Event { |
jackalmage@14093 | 449 | readonly attribute sequence<FontFace> fontfaces; |
jackalmage@9071 | 450 | }; |
jackalmage@8992 | 451 | |
jackalmage@9024 | 452 | enum FontFaceSetLoadStatus { "loading", "loaded" }; |
jackalmage@9024 | 453 | |
jackalmage@14117 | 454 | callback ForEachCallback = void (FontFace font, long index, FontFaceSet self); |
jackalmage@14117 | 455 | |
jackalmage@14154 | 456 | [Exposed=Window,Worker, |
jackalmage@14154 | 457 | Constructor(sequence<FontFace> initialFaces)] |
jackalmage@14123 | 458 | interface FontFaceSet : EventTarget { |
jackalmage@14756 | 459 | // FontFaceSet is Set-like! |
jackalmage@14756 | 460 | setlike<FontFace>; |
jackalmage@15424 | 461 | FontFaceSet add(FontFace font); |
jackalmage@15424 | 462 | boolean delete(FontFace font); |
jackalmage@15424 | 463 | void clear(); |
jackalmage@8992 | 464 | |
jackalmage@14756 | 465 | // events for when loading state changes |
jackalmage@9064 | 466 | attribute EventHandler onloading; |
jackalmage@9064 | 467 | attribute EventHandler onloadingdone; |
jackalmage@9064 | 468 | attribute EventHandler onloadingerror; |
jackalmage@8992 | 469 | |
jackalmage@9033 | 470 | // check and start loads if appropriate |
jackalmage@9003 | 471 | // and fulfill promise when all loads complete |
jackalmage@13945 | 472 | Promise<sequence<FontFace>> load(DOMString font, optional DOMString text = " "); |
jackalmage@8992 | 473 | |
jackalmage@8992 | 474 | // return whether all fonts in the fontlist are loaded |
jackalmage@8992 | 475 | // (does not initiate load if not available) |
jackalmage@9064 | 476 | boolean check(DOMString font, optional DOMString text = " "); |
jackalmage@8992 | 477 | |
jackalmage@9003 | 478 | // async notification that font loading and layout operations are done |
jackalmage@14063 | 479 | readonly attribute Promise<FontFaceSet> ready; |
jackalmage@8992 | 480 | |
jackalmage@9907 | 481 | // loading state, "loading" while one or more fonts loading, "loaded" otherwise |
jackalmage@14079 | 482 | readonly attribute FontFaceSetLoadStatus status; |
jackalmage@8992 | 483 | }; |
jackalmage@8992 | 484 | </pre> |
jackalmage@8992 | 485 | |
jackalmage@14842 | 486 | {{FontFaceSet/load()}} |
jackalmage@14842 | 487 | |
jackalmage@14828 | 488 | <div dfn-for="FontFaceSet"> |
jackalmage@14802 | 489 | : <dfn attribute>ready</dfn> |
jackalmage@14802 | 490 | :: This attribute reflects the {{FontFaceSet}}'s {{[[ReadyPromise]]}} slot. |
jackalmage@14063 | 491 | |
jackalmage@14580 | 492 | See [[#font-face-set-ready]] for more details on this {{Promise}} and its use. |
jackalmage@14117 | 493 | |
jackalmage@15132 | 494 | : <dfn constructor lt="FontFaceSet()">FontFaceSet</dfn>(sequence<{{FontFace}}> <dfn argument for="FontFaceSet/FontFaceSet()">initialFaces</dfn>) |
jackalmage@14802 | 495 | :: The {{FontFaceSet}} constructor, when called, |
jackalmage@14756 | 496 | must iterate its {{initialFaces}} argument |
jackalmage@14756 | 497 | and add each value to its <a>set entries</a>. |
jackalmage@14154 | 498 | |
jackalmage@14802 | 499 | : <dfn dfn>iteration order</dfn> |
jackalmage@14802 | 500 | :: When iterated over, |
jackalmage@14756 | 501 | all <a>CSS-connected</a> {{FontFace}} objects must come first, |
jackalmage@14756 | 502 | in document order of their connected ''@font-face'' rules, |
jackalmage@14756 | 503 | followed by the non-<a>CSS-connected</a> {{FontFace}} objects, |
jackalmage@14756 | 504 | in insertion order. |
jackalmage@14168 | 505 | |
jackalmage@14802 | 506 | : <dfn dfn>set entries</dfn> |
jackalmage@14802 | 507 | :: If a {{FontFaceSet}} is a <a>font source</a>, |
jackalmage@14756 | 508 | its <a spec=webidl for>set entries</a> are initialized as specified in [[#document-font-face-set]]. |
jackalmage@14142 | 509 | |
jackalmage@15424 | 510 | Otherwise, its <a spec=webidl>set entries</a> are initially empty. |
jackalmage@15424 | 511 | |
jackalmage@15424 | 512 | : <dfn method>add(font)</dfn> |
jackalmage@15424 | 513 | :: |
jackalmage@15424 | 514 | When the {{add()}} method is called, |
jackalmage@15424 | 515 | execute the following steps: |
jackalmage@15424 | 516 | |
jackalmage@15424 | 517 | 1. If <var>font</var> is already in the {{FontFaceSet}}âs <a>set entries</a>, |
jackalmage@15424 | 518 | skip to the last step of this algorithm immediately. |
jackalmage@15424 | 519 | 2. If <var>font</var> is <a>CSS-connected</a>, |
jackalmage@15424 | 520 | throw an {{InvalidModificationError}} exception |
jackalmage@15424 | 521 | and exit this algorithm immediately. |
jackalmage@15424 | 522 | 3. Add the <var>font</var> argument to the {{FontFaceSet}}âs <a>set entries</a>. |
jackalmage@15424 | 523 | 2. If <var>font</var>âs {{FontFace/status}} attribute is "loading": |
jackalmage@15424 | 524 | 1. If the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list is empty, |
jackalmage@15424 | 525 | <a>switch the FontFaceSet to loading</a>. |
jackalmage@15424 | 526 | 2. Append <var>font</var> to the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list. |
jackalmage@15424 | 527 | 3. Return the {{FontFaceSet}}. |
jackalmage@15424 | 528 | |
jackalmage@15424 | 529 | : <dfn method>delete(font)</dfn> |
jackalmage@15424 | 530 | :: |
jackalmage@15424 | 531 | When the {{delete()}} method is called, |
jackalmage@15424 | 532 | execute the following steps: |
jackalmage@15424 | 533 | |
jackalmage@15424 | 534 | 1. If <var>font</var> is <a>CSS-connected</a>, |
jackalmage@15424 | 535 | return <code class='lang-javascript'>false</code> |
jackalmage@15424 | 536 | and exit this algorithm immediately. |
jackalmage@15424 | 537 | 2. Let <var>deleted</var> be the result of removing <var>font</var> from the {{FontFaceSet}}âs <a>set entries</a>. |
jackalmage@15424 | 538 | 3. If <var>font</var> is present in the {{FontFaceSet}}âs {{[[LoadedFonts]]}}, or {{[[FailedFonts]]}} lists, |
jackalmage@15424 | 539 | remove it. |
jackalmage@15424 | 540 | 4. If <var>font</var> is present in the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list, |
jackalmage@15424 | 541 | remove it. |
jackalmage@15424 | 542 | If <var>font</var> was the last item in that list |
jackalmage@15424 | 543 | (and so the list is now empty), |
jackalmage@15424 | 544 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@15424 | 545 | 5. Return <var>deleted</var>. |
jackalmage@15424 | 546 | |
jackalmage@15424 | 547 | : <dfn method>clear()</dfn> |
jackalmage@15424 | 548 | :: |
jackalmage@15424 | 549 | When the {{clear()}} method is called, |
jackalmage@15424 | 550 | execute the following steps: |
jackalmage@15424 | 551 | |
jackalmage@15424 | 552 | 1. Remove all items from the {{FontFaceSet}}âs <a>set entries</a>, |
jackalmage@15424 | 553 | its {{[[LoadedFonts]]}} list, |
jackalmage@15424 | 554 | and its {{[[FailedFonts]]}} list. |
jackalmage@15424 | 555 | 2. If the {{FontFaceSet}}âs {{[[LoadingFonts]]}} list is non-empty, |
jackalmage@15424 | 556 | remove all items from it, |
jackalmage@15424 | 557 | then <a>switch the FontFaceSet to loaded</a>. |
jackalmage@14802 | 558 | </div> |
jackalmage@13945 | 559 | |
jackalmage@14551 | 560 | {{FontFaceSet}} objects also have internal |
jackalmage@14551 | 561 | <dfn attribute for=FontFaceSet>\[[LoadingFonts]]</dfn>, |
jackalmage@14551 | 562 | <dfn attribute for=FontFaceSet>\[[LoadedFonts]]</dfn>, |
jackalmage@14551 | 563 | and <dfn attribute for=FontFaceSet>\[[FailedFonts]]</dfn> slots, |
jackalmage@14756 | 564 | all of which are initialized to empty lists, |
jackalmage@14756 | 565 | and a <dfn attribute for=FontFaceSet>\[[ReadyPromise]]</dfn> slot, |
jackalmage@14756 | 566 | which is initialized to a fresh pending {{Promise}}. |
jackalmage@9029 | 567 | |
jackalmage@9495 | 568 | Because font families are loaded only when they are used, |
jackalmage@9495 | 569 | content sometimes needs to understand when the loading of fonts occurs. |
jackalmage@9495 | 570 | Authors can use the events and methods defined here to allow greater control over actions |
jackalmage@9025 | 571 | that are dependent upon the availability of specific fonts. |
jackalmage@8992 | 572 | |
jackalmage@15424 | 573 | A {{FontFaceSet}} is <dfn export for="FontFaceSet">pending on the environment</dfn> if any of the following are true: |
jackalmage@14581 | 574 | |
jackalmage@15424 | 575 | * the document is still loading |
jackalmage@15424 | 576 | * the document has pending stylesheet requests |
jackalmage@16461 | 577 | * the document has pending layout operations which might cause the user agent to request a font, |
jackalmage@16461 | 578 | or which depend on recently-loaded fonts |
jackalmage@16461 | 579 | |
jackalmage@16461 | 580 | Note: The idea is that once a {{FontFaceSet}} stops being <a>pending on the environment</a>, |
jackalmage@16461 | 581 | as long as nothing further changes the document, |
jackalmage@16461 | 582 | an author can depend on sizes/positions of things being "correct" when measured. |
jackalmage@16461 | 583 | If the above conditions do not fully capture this guarantee, |
jackalmage@16461 | 584 | they need to be amended to do so. |
jackalmage@14118 | 585 | |
jackalmage@14019 | 586 | <!-- |
jackalmage@14020 | 587 | ââââââââ ââ ââ ââââââââ ââ ââ ââââââââ ââââââ |
jackalmage@14019 | 588 | ââ ââ ââ ââ âââ ââ ââ ââ ââ |
jackalmage@14020 | 589 | ââ ââ ââ ââ ââââ ââ ââ ââ |
jackalmage@14020 | 590 | ââââââ ââ ââ ââââââ ââ ââ ââ ââ ââââââ |
jackalmage@14019 | 591 | ââ ââ ââ ââ ââ ââââ ââ ââ |
jackalmage@14019 | 592 | ââ ââ ââ ââ ââ âââ ââ ââ ââ |
jackalmage@14020 | 593 | ââââââââ âââ ââââââââ ââ ââ ââ ââââââ |
jackalmage@14019 | 594 | --> |
jackalmage@9135 | 595 | |
jackalmage@9045 | 596 | <h3 id='FontFaceSet-events'> |
jackalmage@9045 | 597 | Events</h3> |
jackalmage@8992 | 598 | |
jackalmage@9029 | 599 | Font load events make it easy to respond to the font-loading behavior of the entire document, |
jackalmage@9029 | 600 | rather than having to listen to each font specifically. |
jackalmage@9029 | 601 | The <dfn event for="FontFaceSet">loading</dfn> event |
jackalmage@9029 | 602 | fires when the document begins loading fonts, |
jackalmage@9029 | 603 | while the <dfn event for="FontFaceSet">loadingdone</dfn> |
jackalmage@9029 | 604 | and <dfn event for="FontFaceSet">loadingerror</dfn> events |
jackalmage@9029 | 605 | fire when the document is done loading fonts, |
jackalmage@9029 | 606 | containing the fonts that successfully loaded |
jackalmage@9029 | 607 | or failed to load, |
jackalmage@9029 | 608 | respectively. |
jackalmage@8992 | 609 | |
jackalmage@8992 | 610 | The following are the event handlers (and their corresponding event handler event types) |
jackalmage@9018 | 611 | that must be supported by <code>FontFaceSet</code> objects as IDL attributes: |
jackalmage@8992 | 612 | |
jackalmage@8992 | 613 | <table class="data" id="eventhandlers"> |
jackalmage@8992 | 614 | <thead> |
jackalmage@8992 | 615 | <tr> |
jackalmage@8992 | 616 | <th>Event handler |
jackalmage@8992 | 617 | <th>Event handler event type |
jackalmage@8992 | 618 | <tbody> |
jackalmage@8992 | 619 | <tr> |
jackalmage@14551 | 620 | <th>{{onloading}} |
jackalmage@14551 | 621 | <td>{{loading}} |
jackalmage@8992 | 622 | <tr> |
jackalmage@14551 | 623 | <th>{{onloadingdone}} |
jackalmage@14551 | 624 | <td>{{loadingdone}} |
jackalmage@8992 | 625 | <tr> |
jackalmage@14551 | 626 | <th>{{onloadingerror}} |
jackalmage@14551 | 627 | <td>{{loadingerror}} |
jackalmage@8992 | 628 | </table> |
jackalmage@8992 | 629 | |
jackalmage@9495 | 630 | To <dfn>fire a font load event</dfn> named <var>e</var> |
jackalmage@14551 | 631 | at a {{FontFaceSet}} <var>target</var> |
jackalmage@9029 | 632 | with optional <var>font faces</var> |
jackalmage@8992 | 633 | means to |
jackalmage@8992 | 634 | <a href="http://www.w3.org/TR/html5/webappapis.html#event-firing">fire a simple event</a> named <var>e</var> |
jackalmage@14551 | 635 | using the {{FontFaceSetLoadEvent}} interface that also meets these conditions: |
jackalmage@8992 | 636 | |
jackalmage@8992 | 637 | <ol> |
jackalmage@8992 | 638 | <li> |
jackalmage@15300 | 639 | The {{FontFaceSetLoadEvent/fontfaces}} attribute is initialized to |
jackalmage@15300 | 640 | the result of filtering <var>font faces</var> to only contain {{FontFace}} objects contained in <var>target</var>. |
jackalmage@8992 | 641 | </ol> |
jackalmage@8992 | 642 | |
jackalmage@15424 | 643 | When asked to <dfn>switch the FontFaceSet to loading</dfn> for a given {{FontFaceSet}}, |
jackalmage@9495 | 644 | the user agent must run the following steps: |
jackalmage@8992 | 645 | |
jackalmage@8992 | 646 | <ol> |
jackalmage@8992 | 647 | <li> |
jackalmage@15424 | 648 | Let <var>font face set</var> be the given {{FontFaceSet}}. |
jackalmage@8992 | 649 | |
jackalmage@8992 | 650 | <li> |
jackalmage@14551 | 651 | Set the {{FontFaceSet/status}} attribute of <var>font face set</var> to "loading". |
jackalmage@8992 | 652 | |
jackalmage@8992 | 653 | <li> |
jackalmage@15972 | 654 | If <var>font face set's</var> {{[[ReadyPromise]]}} slot currently holds a fulfilled promise, |
jackalmage@15972 | 655 | replace it with a fresh pending promise. |
jackalmage@14063 | 656 | |
jackalmage@14063 | 657 | <li> |
jackalmage@15972 | 658 | Queue a task to <a>fire a font load event</a> named {{loading}} at <var>font face set</var>. |
jackalmage@8992 | 659 | </ol> |
jackalmage@8992 | 660 | |
jackalmage@15424 | 661 | When asked to <dfn>switch the FontFaceSet to loaded</dfn> for a given {{FontFaceSet}}, |
jackalmage@9029 | 662 | the user agent must run the following steps: |
jackalmage@8992 | 663 | |
jackalmage@15424 | 664 | 1. Let <var>font face set</var> be the given {{FontFaceSet}}. |
jackalmage@8992 | 665 | |
jackalmage@15424 | 666 | 2. If <var>font face set</var> is <a>pending on the environment</a>, |
jackalmage@15424 | 667 | mark it as <dfn export for=FontFaceSet>stuck on the environment</dfn>, |
jackalmage@15424 | 668 | and exit this algorithm. |
jackalmage@8992 | 669 | |
jackalmage@15424 | 670 | 3. Set <var>font face setâs</var> {{FontFaceSet/status}} attribute to "loaded". |
jackalmage@8992 | 671 | |
jackalmage@15972 | 672 | 4. Fulfill <var>font face set's</var> {{[[ReadyPromise]]}} attribute's value with <var>font face set</var>. |
jackalmage@14581 | 673 | |
jackalmage@15972 | 674 | 5. Queue a task to perform the following steps synchronously: |
jackalmage@8992 | 675 | |
jackalmage@15973 | 676 | 1. Let <var>loaded fonts</var> be the (possibly empty) contents of <var>font face set's</var> {{[[LoadedFonts]]}} slot. |
jackalmage@15973 | 677 | 2. Let <var>failed fonts</var> be the (possibly empty) contents of <var>font face set's</var> {{[[FailedFonts]]}} slot. |
jackalmage@15973 | 678 | 3. Reset the {{[[LoadedFonts]]}} and {{[[FailedFonts]]}} slots to empty lists. |
jackalmage@15973 | 679 | 4. <a>Fire a font load event</a> named {{loadingdone}} at <var>font face set</var> |
jackalmage@15973 | 680 | with <var>loaded fonts</var>. |
jackalmage@15973 | 681 | 5. If <var>font face set's</var> <var>failed fonts</var> is non-empty, |
jackalmage@15972 | 682 | <a>fire a font load event</a> named {{loadingerror}} at <var>font face set</var> |
jackalmage@15973 | 683 | with <var>failed fonts</var>. |
jackalmage@8992 | 684 | |
jackalmage@15424 | 685 | Whenever a {{FontFaceSet}} goes from <a>pending on the environment</a> to not <a>pending on the environment</a>, |
jackalmage@15424 | 686 | the user agent must run the following steps: |
jackalmage@9029 | 687 | |
jackalmage@15424 | 688 | 1. If the {{FontFaceSet}} is <a>stuck on the environment</a> and its {{[[LoadingFonts]]}} list is empty, |
jackalmage@15424 | 689 | <a>switch the FontFaceSet to loaded</a>. |
jackalmage@15424 | 690 | |
jackalmage@15424 | 691 | 2. If the {{FontFaceSet}} is <a>stuck on the environment</a>, |
jackalmage@15424 | 692 | unmark it as such. |
jackalmage@8992 | 693 | |
jackalmage@9033 | 694 | |
jackalmage@9904 | 695 | If asked to <dfn export>find the matching font faces</dfn> |
jackalmage@9904 | 696 | from a FontFaceSet <var>source</var>, |
jackalmage@9904 | 697 | for a given font string <var>font</var> |
jackalmage@14062 | 698 | optionally some sample text <var>text</var>, |
jackalmage@14062 | 699 | and optionally an <var>allow system fonts</var> flag, |
jackalmage@9904 | 700 | run the following steps: |
jackalmage@9033 | 701 | |
jackalmage@9033 | 702 | <ol> |
jackalmage@9033 | 703 | <li> |
jackalmage@9904 | 704 | Parse <var>font</var> |
jackalmage@9033 | 705 | using the CSS value syntax of the 'font' property. |
jackalmage@9904 | 706 | If a syntax error occurs, |
jackalmage@9904 | 707 | return a syntax error. |
jackalmage@9033 | 708 | |
jackalmage@15410 | 709 | If the parsed value is a <a>CSS-wide keyword</a>, |
jackalmage@15410 | 710 | return a syntax error. |
jackalmage@15410 | 711 | |
jackalmage@15410 | 712 | Absolutize all relative lengths against the initial values of the corresponding properties. |
jackalmage@15422 | 713 | (For example, a relative font weight like ''bolder'' is evaluated against the initial value ''font-weight/normal''.) |
jackalmage@15410 | 714 | |
jackalmage@9033 | 715 | <li> |
jackalmage@9904 | 716 | If <var>text</var> was not explicitly provided, |
jackalmage@9904 | 717 | let it be a string containing a single space character (U+0020 SPACE). |
jackalmage@9033 | 718 | |
jackalmage@9033 | 719 | <li> |
jackalmage@9904 | 720 | Let <var>font family list</var> be the list of font families parsed from <var>font</var>, |
jackalmage@9904 | 721 | and <var>font style</var> be the other font style attributes parsed from <var>font</var>. |
jackalmage@9904 | 722 | |
jackalmage@9904 | 723 | <li> |
jackalmage@9904 | 724 | Let <var>available font faces</var> be the font faces within <var>source</var>. |
jackalmage@14062 | 725 | If the <var>allow system fonts</var> flag is specified, |
jackalmage@14062 | 726 | add all system fonts to <var>available font faces</var>. |
jackalmage@9904 | 727 | |
jackalmage@9904 | 728 | <li> |
jackalmage@9904 | 729 | Let <var>matched font faces</var> initially be an empty list. |
jackalmage@9033 | 730 | |
jackalmage@9033 | 731 | <li> |
jackalmage@9495 | 732 | For each family in <var>font family list</var>, |
jackalmage@9904 | 733 | use the font matching rules to select the font faces from <var>available font faces</var> |
jackalmage@9904 | 734 | that match the <var>font style</var>, |
jackalmage@9904 | 735 | and add them to <var>matched font faces</var>. |
jackalmage@14551 | 736 | The use of the {{FontFace/unicodeRange}} attribute means that this may be more than just a single font face. |
jackalmage@9033 | 737 | |
jackalmage@9033 | 738 | <li> |
jackalmage@15665 | 739 | If <var>matched font faces</var> is empty, |
jackalmage@15665 | 740 | set the <var>found faces</var> flag to false. |
jackalmage@15665 | 741 | Otherwise, set it to true. |
jackalmage@15665 | 742 | |
jackalmage@15665 | 743 | <li> |
jackalmage@9904 | 744 | For each font face in <var>matched font faces</var>, |
jackalmage@9904 | 745 | if its defined 'unicode-range' does not include the codepoint of at least one character in <var>text</var>, |
jackalmage@9904 | 746 | remove it from the list. |
jackalmage@9033 | 747 | |
jackalmage@9033 | 748 | <li> |
jackalmage@15665 | 749 | Return <var>matched font faces</var> and the <var>found faces</var> flag. |
jackalmage@9498 | 750 | </ol> |
jackalmage@9033 | 751 | |
jackalmage@14019 | 752 | <!-- |
jackalmage@14020 | 753 | ââ âââââââ âââ ââââââââ âââ âââ |
jackalmage@14020 | 754 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 755 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 756 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 757 | ââ ââ ââ âââââââââ ââ ââ ââ ââ |
jackalmage@14020 | 758 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 759 | ââââââââ âââââââ ââ ââ ââââââââ âââ âââ |
jackalmage@14019 | 760 | --> |
jackalmage@9033 | 761 | |
jackalmage@9045 | 762 | <h3 id='font-face-set-load'> |
jackalmage@9045 | 763 | The <code>load()</code> method</h3> |
jackalmage@8992 | 764 | |
jackalmage@14842 | 765 | The {{FontFaceSet/load()}} method of {{FontFaceSet}} will determine whether all fonts in the given font list |
jackalmage@9019 | 766 | have been loaded and are available. |
jackalmage@9019 | 767 | If any fonts are downloadable fonts and have not already been loaded, |
jackalmage@9019 | 768 | the user agent will initiate the load of each of these fonts. |
jackalmage@9019 | 769 | It returns a Promise, |
jackalmage@9019 | 770 | which is fulfilled when all of the fonts are loaded and ready to be used, |
jackalmage@9019 | 771 | or rejected if any font failed to load properly. |
jackalmage@8992 | 772 | |
jackalmage@15132 | 773 | When the <dfn method for="FontFaceSet" lt="load(font, text)">load</dfn>( |
jackalmage@14842 | 774 | <span dfn-for="FontFaceSet/load(font, text)"> |
jackalmage@14842 | 775 | <dfn argument>font</dfn>, |
jackalmage@14842 | 776 | <dfn argument>text</dfn> |
jackalmage@14842 | 777 | </span> |
jackalmage@14842 | 778 | ) method is called, |
jackalmage@9019 | 779 | execute these steps: |
jackalmage@8992 | 780 | |
jackalmage@9904 | 781 | <ol> |
jackalmage@8992 | 782 | <li> |
jackalmage@14551 | 783 | Let <var>font face set</var> be the {{FontFaceSet}} object this method was called on. |
jackalmage@9062 | 784 | Let <var>promise</var> be a newly-created promise object. |
jackalmage@9062 | 785 | |
jackalmage@9062 | 786 | <li> |
jackalmage@9062 | 787 | Return <var>promise</var>. |
jackalmage@9062 | 788 | Complete the rest of these steps asynchronously. |
jackalmage@9002 | 789 | |
jackalmage@9002 | 790 | <li> |
jackalmage@9904 | 791 | <a>Find the matching font faces</a> from <var>font face set</var> |
jackalmage@14551 | 792 | using the {{FontFaceSet/load()/font}} and {{FontFaceSet/load()/text}} arguments passed to the function, |
jackalmage@15665 | 793 | and let <var>font face list</var> be the return value |
jackalmage@15665 | 794 | (ignoring the <var>found faces</var> flag). |
jackalmage@9904 | 795 | If a syntax error was returned, |
jackalmage@9904 | 796 | reject <var>promise</var> with a SyntaxError exception |
jackalmage@9904 | 797 | and terminate these steps. |
jackalmage@8992 | 798 | |
jackalmage@8992 | 799 | <li> |
jackalmage@14126 | 800 | Queue a task to run the following steps synchronously: |
jackalmage@8992 | 801 | |
jackalmage@14015 | 802 | <ol> |
jackalmage@14015 | 803 | <li> |
jackalmage@14015 | 804 | For all of the font faces in the <var>font face list</var>, |
jackalmage@14551 | 805 | call their {{FontFace/load()}} method. |
jackalmage@14015 | 806 | |
jackalmage@14015 | 807 | <li> |
jackalmage@14015 | 808 | Resolve <var>promise</var> with the result of |
jackalmage@14551 | 809 | waiting for all of the {{[[FontStatusPromise]]}}s of each font face in the <var>font face list</var>, in order. |
jackalmage@14015 | 810 | </ol> |
jackalmage@8992 | 811 | </ol> |
jackalmage@8992 | 812 | |
jackalmage@14019 | 813 | <!-- |
jackalmage@14020 | 814 | ââââââ ââ ââ ââââââââ ââââââ ââ ââ âââ âââ |
jackalmage@14020 | 815 | ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 816 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 817 | ââ âââââââââ ââââââ ââ âââââ ââ ââ |
jackalmage@14019 | 818 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 819 | ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 820 | ââââââ ââ ââ ââââââââ ââââââ ââ ââ âââ âââ |
jackalmage@14019 | 821 | --> |
jackalmage@14019 | 822 | |
jackalmage@9045 | 823 | <h3 id='font-face-set-check'> |
jackalmage@9045 | 824 | The <code>check()</code> method</h3> |
jackalmage@9019 | 825 | |
jackalmage@14842 | 826 | The {{FontFaceSet/check()}} method of {{FontFaceSet}} will determine whether all fonts in the given font list |
jackalmage@9019 | 827 | have been loaded and are available. |
jackalmage@9019 | 828 | If all fonts are available, |
jackalmage@9019 | 829 | it returns true; |
jackalmage@9019 | 830 | otherwise, it returns false. |
jackalmage@9003 | 831 | |
jackalmage@15132 | 832 | When the <dfn method for="FontFaceSet" lt="check(font, text)|check(font)">check</dfn>( |
jackalmage@14842 | 833 | <span data-dfn-for="FontFaceSet/check(font, text)"><dfn argument>font</dfn>, <dfn argument>text</dfn>)</span> |
jackalmage@14842 | 834 | method is called, |
jackalmage@9025 | 835 | execute these steps: |
jackalmage@8992 | 836 | |
jackalmage@8992 | 837 | <ol> |
jackalmage@8992 | 838 | <li> |
jackalmage@14551 | 839 | Let <var>font face set</var> be the {{FontFaceSet}} object this method was called on. |
jackalmage@8992 | 840 | |
jackalmage@8992 | 841 | <li> |
jackalmage@9904 | 842 | <a>Find the matching font faces</a> from <var>font face set</var> |
jackalmage@14551 | 843 | using the {{FontFaceSet/check()/font}} and {{FontFaceSet/check()/text}} arguments passed to the function, |
jackalmage@14062 | 844 | and including system fonts, |
jackalmage@15665 | 845 | and let <var>font face list</var> be the returned list of font faces, |
jackalmage@15665 | 846 | and <var>found faces</var> be the returned <var>found faces</var> flag. |
jackalmage@9904 | 847 | If a syntax error was returned, |
jackalmage@10068 | 848 | throw a SyntaxError exception |
jackalmage@9904 | 849 | and terminate these steps. |
jackalmage@8992 | 850 | |
jackalmage@8992 | 851 | <li> |
jackalmage@15665 | 852 | If <var>found faces</var> is false, |
jackalmage@15665 | 853 | throw an XXX error |
jackalmage@15665 | 854 | and abort this algorithm. |
jackalmage@8992 | 855 | |
jackalmage@8992 | 856 | <li> |
jackalmage@15665 | 857 | If <var>font face list</var> is empty, |
jackalmage@15665 | 858 | or all fonts in the <var>font face list</var> either have a {{FontFace/status}} attribute of "loaded" or are system fonts, |
jackalmage@9495 | 859 | return <code>true</code>. |
jackalmage@9033 | 860 | Otherwise, return <code>false</code>. |
jackalmage@8992 | 861 | </ol> |
jackalmage@8992 | 862 | |
jackalmage@14019 | 863 | <!-- |
jackalmage@14063 | 864 | ââââââââ ââââââââ âââ ââââââââ ââ ââ |
jackalmage@14063 | 865 | ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14063 | 866 | ââ ââ ââ ââ ââ ââ ââ ââââ |
jackalmage@14063 | 867 | ââââââââ ââââââ ââ ââ ââ ââ ââ |
jackalmage@14063 | 868 | ââ ââ ââ âââââââââ ââ ââ ââ |
jackalmage@14063 | 869 | ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14063 | 870 | ââ ââ ââââââââ ââ ââ ââââââââ ââ |
jackalmage@14019 | 871 | --> |
jackalmage@14019 | 872 | |
jackalmage@9045 | 873 | <h3 id='font-face-set-ready'> |
jackalmage@14063 | 874 | The <code>ready</code> attribute</h3> |
jackalmage@8992 | 875 | |
jackalmage@9495 | 876 | Because the number of fonts loaded depends on the how many fonts are used for a given piece of text, |
jackalmage@9003 | 877 | in some cases whether fonts need to be loaded or not may not be known. |
jackalmage@14551 | 878 | The {{FontFaceSet/ready}} attribute contains a {{Promise}} which is resolved when the document is done loading fonts, |
jackalmage@9495 | 879 | which provides a way for authors to avoid having to keep track of which fonts have or haven't been loaded |
jackalmage@9003 | 880 | before examining content which may be affected by loading fonts. |
jackalmage@8992 | 881 | |
jackalmage@9063 | 882 | Note: Authors should note that a given <var>ready promise</var> is only fulfilled once, |
jackalmage@9003 | 883 | but further fonts may be loaded after it fulfills. |
jackalmage@14551 | 884 | This is similar to listening for a {{loadingdone}} event to fire, |
jackalmage@14551 | 885 | but the callbacks passed to the {{FontFaceSet/ready}} promise will <strong>always</strong> get called, |
jackalmage@9495 | 886 | even when no font loads occur because the fonts in question are already loaded. |
jackalmage@9495 | 887 | It's a simple, easy way to synchronize code to font loads |
jackalmage@9003 | 888 | without the need to keep track of what fonts are needed and precisely when they load. |
jackalmage@8992 | 889 | |
jackalmage@9063 | 890 | Note: Note that the user agent may need to iterate over multiple font loads before the <var>ready promise</var> is fulfilled. |
jackalmage@9495 | 891 | This can occur with font fallback situations, |
jackalmage@9495 | 892 | where one font in the fontlist is loaded |
jackalmage@9495 | 893 | but doesn't contain a particular glyph |
jackalmage@9495 | 894 | and other fonts in the fontlist need to be loaded. |
jackalmage@9495 | 895 | The <var>ready promise</var> is only fulfilled after layout operations complete |
jackalmage@9003 | 896 | and no additional font loads are necessary. |
jackalmage@8992 | 897 | |
jackalmage@14551 | 898 | Note: Note that the Promise returned by this {{FontFaceSet/ready}} attribute is only ever fulfilled, |
jackalmage@9034 | 899 | never rejected, |
jackalmage@14551 | 900 | unlike the Promise returned by the {{FontFace}} {{FontFace/load()}} method. |
jackalmage@9034 | 901 | |
jackalmage@9137 | 902 | <h3 id='font-face-set-css'> |
jackalmage@9137 | 903 | Interaction with CSS Font Loading and Matching</h3> |
jackalmage@9137 | 904 | |
jackalmage@14762 | 905 | When the font matching algorithm in [[CSS-FONTS-3]] is run automatically by the user-agent, |
jackalmage@9137 | 906 | the set of font faces it matches over must be precisely the set of fonts in the <a>font source</a> for the document, |
jackalmage@9137 | 907 | plus any local font faces. |
jackalmage@9137 | 908 | |
jackalmage@9137 | 909 | When a user-agent needs to load a font face, |
jackalmage@14551 | 910 | it must do so by calling the {{FontFace/load()}} method |
jackalmage@14551 | 911 | of the corresponding {{FontFace}} object. |
jackalmage@9137 | 912 | |
jackalmage@9137 | 913 | (This means it must run the same algorithm, |
jackalmage@9137 | 914 | not literally call the value currently stored in the <code>load</code> property of the object.) |
jackalmage@9137 | 915 | |
jackalmage@13481 | 916 | <div class="example"> |
jackalmage@14551 | 917 | Fonts are available when they are added to a {{FontFaceSet}}. |
jackalmage@13481 | 918 | Adding a new ''@font-face'' rule to a stylesheet |
jackalmage@14551 | 919 | also adds a new {{FontFace}} to the {{FontFaceSet}} of the {{Document}} object. |
jackalmage@13481 | 920 | |
jackalmage@13481 | 921 | Adding a new ''@font-face'' rule: |
jackalmage@13481 | 922 | |
jackalmage@13481 | 923 | <pre> |
jackalmage@13481 | 924 | document.styleSheets[0].insertRule( |
jackalmage@13481 | 925 | "@font-face { font-family: newfont; src: url(newfont.woff); }", 0); |
jackalmage@13481 | 926 | document.body.style.fontFamily = "newfont, serif"; |
jackalmage@13481 | 927 | </pre> |
jackalmage@13481 | 928 | |
jackalmage@14551 | 929 | Constructing a new {{FontFace}} object and adding it to <code>document.fonts</code>: |
jackalmage@13481 | 930 | |
jackalmage@13481 | 931 | <pre> |
jackalmage@13481 | 932 | var f = new FontFace("newfont", "url(newfont.woff)"); |
jackalmage@13481 | 933 | document.fonts.add(f); |
jackalmage@13481 | 934 | document.body.style.fontFamily = "newfont, serif"; |
jackalmage@13481 | 935 | </pre> |
jackalmage@13481 | 936 | |
jackalmage@13481 | 937 | In both cases, the loading of the font resource ânewfont.woffâ will be initiated by the layout engine, |
jackalmage@13481 | 938 | just as other ''@font-face'' rule fonts are loaded. |
jackalmage@13481 | 939 | |
jackalmage@13481 | 940 | Omitting the addition to <code>document.fonts</code> means the font would never be loaded |
jackalmage@13481 | 941 | and text would be displayed in the default serif font: |
jackalmage@13481 | 942 | |
jackalmage@13481 | 943 | <pre> |
jackalmage@13481 | 944 | var f = new FontFace("newfont", "url(newtest.woff)", {}); |
jackalmage@13481 | 945 | |
jackalmage@14551 | 946 | /* new {{FontFace}} not added to {{FontFaceSet}}, |
jackalmage@13481 | 947 | so the 'font-family' property can't see it, |
jackalmage@13481 | 948 | and serif will be used instead */ |
jackalmage@13481 | 949 | document.body.style.fontFamily = "newfont, serif"; |
jackalmage@13481 | 950 | </pre> |
jackalmage@13481 | 951 | |
jackalmage@13481 | 952 | To explicitly preload a font before using it, |
jackalmage@14551 | 953 | authors can defer the addition of a new {{FontFace}} to a {{FontFaceSet}} until the load has completed: |
jackalmage@13481 | 954 | |
jackalmage@13481 | 955 | <pre> |
jackalmage@13481 | 956 | var f = new FontFace("newfont", "url(newfont.woff)", {}); |
jackalmage@13482 | 957 | f.load().then(function (loadedFace) { |
jackalmage@13482 | 958 | document.fonts.add(loadedFace); |
jackalmage@13481 | 959 | document.body.style.fontFamily = "newfont, serif"; |
jackalmage@13481 | 960 | }); |
jackalmage@13481 | 961 | </pre> |
jackalmage@13481 | 962 | |
jackalmage@13481 | 963 | In this case, the font resource ânewfont.woffâ is first downloaded. |
jackalmage@13481 | 964 | Once the download completes, |
jackalmage@14551 | 965 | the font is added to the document's {{FontFaceSet}}, |
jackalmage@13481 | 966 | the body font is changed, |
jackalmage@13481 | 967 | and the layout engine uses the new font resource. |
jackalmage@13481 | 968 | </div> |
jackalmage@13481 | 969 | |
jackalmage@14019 | 970 | <!-- |
jackalmage@14019 | 971 | ââââââââ âââââââ ââ ââ ââââââââ ââââââââ âââ ââââââ ââââââââ ââââââ âââââââ ââ ââ ââââââââ ââââââ ââââââââ |
jackalmage@14020 | 972 | ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 973 | ââ ââ ââ ââââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 974 | ââââââ ââ ââ ââ ââ ââ ââ ââââââ ââ ââ ââ ââââââ ââââââ ââ ââ ââ ââ ââââââââ ââ ââââââ |
jackalmage@14020 | 975 | ââ ââ ââ ââ ââââ ââ ââ âââââââââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 976 | ââ ââ ââ ââ âââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 977 | ââ âââââââ ââ ââ ââ ââ ââ ââ ââââââ ââââââââ ââââââ âââââââ âââââââ ââ ââ ââââââ ââââââââ |
jackalmage@14019 | 978 | --> |
jackalmage@14019 | 979 | |
jackalmage@9047 | 980 | <h2 id='font-face-source'> |
jackalmage@9047 | 981 | The <code>FontFaceSource</code> interface</h2> |
jackalmage@9045 | 982 | |
jackalmage@9047 | 983 | <pre class='idl'> |
jackalmage@10105 | 984 | [NoInterfaceObject] |
jackalmage@9906 | 985 | interface FontFaceSource { |
jackalmage@9906 | 986 | readonly attribute FontFaceSet fonts; |
jackalmage@9071 | 987 | }; |
jackalmage@9045 | 988 | |
jackalmage@9906 | 989 | Document implements FontFaceSource; |
jackalmage@9906 | 990 | WorkerGlobalScope implements FontFaceSource; |
jackalmage@9045 | 991 | </pre> |
jackalmage@9045 | 992 | |
jackalmage@14551 | 993 | Any document, workers, or other context which can use fonts in some manner must implement the {{FontFaceSource}} interface. |
jackalmage@14551 | 994 | The value of the contextâs {{fonts}} attribute is its <dfn>font source</dfn>, |
jackalmage@9047 | 995 | which provides all of the fonts used in font-related operations, |
jackalmage@9047 | 996 | unless defined otherwise. |
jackalmage@9047 | 997 | Operations referring to âthe font sourceâ must be interpreted as referring to the <a>font source</a> of the relevant context in which the operation is taking place. |
jackalmage@9045 | 998 | |
jackalmage@9047 | 999 | For any font-related operation that takes place within one of these contexts, |
jackalmage@14551 | 1000 | the {{FontFace}} objects within the <a>font source</a> are its <dfn>available font faces</dfn>. |
jackalmage@9045 | 1001 | |
jackalmage@13597 | 1002 | <h3 id="fontfacesource-workers"> |
jackalmage@13597 | 1003 | Worker FontFaceSources</h3> |
jackalmage@13597 | 1004 | |
jackalmage@13597 | 1005 | Within a Worker document, the <a>font source</a> is initially empty. |
jackalmage@13597 | 1006 | |
jackalmage@14551 | 1007 | Note: {{FontFace}} objects can be constructed and added to it as normal, |
jackalmage@13597 | 1008 | which affects CSS font-matching within the worker |
jackalmage@14551 | 1009 | (such as, for example, drawing text into a {{CanvasProxy}}). |
jackalmage@13597 | 1010 | |
jackalmage@9047 | 1011 | <h3 id="document-font-face-set"> |
jackalmage@9047 | 1012 | Interaction with CSSâs ''@font-face'' Rule</h3> |
jackalmage@9047 | 1013 | |
jackalmage@9047 | 1014 | The set entries for a document's <a>font source</a> |
jackalmage@14551 | 1015 | must be initially populated with all the <a>CSS-connected</a> {{FontFace}} objects |
jackalmage@9047 | 1016 | from all of the CSS ''@font-face'' rules in the document's stylesheets, |
jackalmage@9047 | 1017 | in document order. |
jackalmage@9135 | 1018 | As ''@font-face'' rules are added or removed from a stylesheet, |
jackalmage@9135 | 1019 | or stylesheets containing ''@font-face'' rules are added or removed, |
jackalmage@14551 | 1020 | the corresponding <a>CSS-connected</a> {{FontFace}} objects |
jackalmage@9135 | 1021 | must be added or removed from the document's <a>font source</a>, |
jackalmage@9495 | 1022 | and maintain this ordering. |
jackalmage@9135 | 1023 | |
jackalmage@15407 | 1024 | Any manually-added {{FontFace}} objects must be ordered <em>after</em> |
jackalmage@15407 | 1025 | the <a>CSS-connected</a> ones. |
jackalmage@15407 | 1026 | |
jackalmage@15407 | 1027 | When a {{FontFaceSet}} object's {{FontFaceSet/add()}} method is called with a <a>CSS-connected</a> {{FontFace}} object, |
jackalmage@15407 | 1028 | if the object is already in the set, |
jackalmage@15407 | 1029 | the operation must be a no-op; |
jackalmage@15407 | 1030 | otherwise, the operation must do nothing, |
jackalmage@15407 | 1031 | and throw an {{InvalidModificationError}}. |
jackalmage@15407 | 1032 | |
jackalmage@15407 | 1033 | When a {{FontFaceSet}} object's {{FontFaceSet/delete()}} method is called with a <a>CSS-connected</a> {{FontFace}} object, |
jackalmage@15421 | 1034 | the operation must be a no-op, |
jackalmage@15421 | 1035 | and return <code class="lang-javascript">false</code>. |
jackalmage@15407 | 1036 | |
jackalmage@14582 | 1037 | Note: Authors can still maintain references to a removed {{FontFace}}, |
jackalmage@14582 | 1038 | even if it's been automatically removed from a <a>font source</a>. |
jackalmage@14582 | 1039 | As specified in [[#font-face-css-connection]], though, |
jackalmage@14582 | 1040 | the {{FontFace}} is no longer <a>CSS-connected</a> at that point. |
jackalmage@14582 | 1041 | |
jackalmage@13598 | 1042 | Note: It is expected that a future version of this specification |
jackalmage@13598 | 1043 | will define ways of interacting with and querying local fonts as well. |
jackalmage@9137 | 1044 | |
jackalmage@14019 | 1045 | <!-- |
jackalmage@14020 | 1046 | âââ ââââââââ ââââ ââââââââ ââ ââ âââ ââ ââ ââââââââ ââ ââââââââ ââââââ |
jackalmage@14019 | 1047 | ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ âââ âââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 1048 | ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââââ ââââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 1049 | ââ ââ ââââââââ ââ ââââââ âââ ââ ââ ââ âââ ââ ââââââââ ââ ââââââ ââââââ |
jackalmage@14019 | 1050 | âââââââââ ââ ââ ââ ââ ââ âââââââââ ââ ââ ââ ââ ââ ââ |
jackalmage@14019 | 1051 | ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ ââ |
jackalmage@14020 | 1052 | ââ ââ ââ ââââ ââââââââ ââ ââ ââ ââ ââ ââ ââ ââââââââ ââââââââ ââââââ |
jackalmage@14019 | 1053 | --> |
jackalmage@14019 | 1054 | |
jackalmage@9045 | 1055 | <h2 id="font-load-event-examples"> |
jackalmage@9045 | 1056 | API Examples</h2> |
jackalmage@8992 | 1057 | |
jackalmage@8992 | 1058 | <div class="example"> |
jackalmage@8992 | 1059 | To show content only after all font loads complete: |
jackalmage@8992 | 1060 | |
jackalmage@8992 | 1061 | <pre> |
jaffathecake@15851 | 1062 | document.fonts.ready.then(function() { |
jackalmage@8992 | 1063 | var content = document.getElementById("content"); |
jackalmage@8992 | 1064 | content.style.visibility = "visible"; |
jackalmage@9003 | 1065 | }); |
jackalmage@8992 | 1066 | </pre> |
jackalmage@8992 | 1067 | </div> |
jackalmage@8992 | 1068 | |
jackalmage@8992 | 1069 | <div class="example"> |
jackalmage@8992 | 1070 | Drawing text in a canvas with a downloadable font, explicitly |
jackalmage@8992 | 1071 | initiating the font download and drawing upon completion: |
jackalmage@8992 | 1072 | |
jackalmage@8992 | 1073 | <pre> |
jackalmage@8992 | 1074 | function drawStuff() { |
jackalmage@8992 | 1075 | var ctx = document.getElementById("c").getContext("2d"); |
jackalmage@8992 | 1076 | |
jackalmage@8992 | 1077 | ctx.fillStyle = "red"; |
jackalmage@8992 | 1078 | ctx.font = "50px MyDownloadableFont"; |
jackalmage@8992 | 1079 | ctx.fillText("Hello!", 100, 100); |
jackalmage@8992 | 1080 | } |
jackalmage@8992 | 1081 | |
jackalmage@9033 | 1082 | document.fonts.load("50px MyDownloadableFont") |
jackalmage@9033 | 1083 | .then(drawStuff, handleError); |
jackalmage@8992 | 1084 | </pre> |
jackalmage@8992 | 1085 | </div> |
jackalmage@8992 | 1086 | |
jackalmage@8992 | 1087 | <div class="example"> |
jackalmage@8992 | 1088 | A rich text editing application may need to measure text elements |
jackalmage@8992 | 1089 | after editing operations have taken place. Since style changes may |
jackalmage@8992 | 1090 | or may not require additional fonts to be downloaded, or the fonts |
jackalmage@8992 | 1091 | may already have been downloaded, the measurement procedures need to |
jackalmage@8992 | 1092 | occur after those font loads complete: |
jackalmage@8992 | 1093 | |
jackalmage@8992 | 1094 | <pre> |
jackalmage@8992 | 1095 | function measureTextElements() { |
jackalmage@8992 | 1096 | // contents can now be measured using the metrics of |
jackalmage@8992 | 1097 | // the downloadable font(s) |
jackalmage@8992 | 1098 | } |
jackalmage@8992 | 1099 | |
jackalmage@8992 | 1100 | function doEditing() { |
jackalmage@8992 | 1101 | // content/layout operations that may cause additional font loads |
jaffathecake@15851 | 1102 | document.fonts.ready.then(measureTextElements); |
jackalmage@8992 | 1103 | } |
jackalmage@8992 | 1104 | </pre> |
jackalmage@8992 | 1105 | </div> |
jackalmage@8992 | 1106 | |
jackalmage@8992 | 1107 | <div class="example"> |
jackalmage@14551 | 1108 | The {{loadingdone}} event only fires after all font related loads have completed |
jackalmage@9033 | 1109 | <strong>and</strong> text has been laid out without causing additional font loads: |
jackalmage@8992 | 1110 | |
jackalmage@8992 | 1111 | <pre> |
jackalmage@10108 | 1112 | <style> |
jackalmage@8992 | 1113 | @font-face { |
jackalmage@8992 | 1114 | font-family: latin-serif; |
jackalmage@8992 | 1115 | src: url(latinserif.woff) format("woff"); /* contains no kanji/kana */ |
jackalmage@8992 | 1116 | } |
jackalmage@8992 | 1117 | @font-face { |
jackalmage@8992 | 1118 | font-family: jpn-mincho; |
jackalmage@8992 | 1119 | src: url(mincho.woff) format("woff"); |
jackalmage@8992 | 1120 | } |
jackalmage@10108 | 1121 | @font-face { |
jackalmage@10108 | 1122 | font-family: unused; |
jackalmage@10108 | 1123 | src: url(unused.woff); |
jackalmage@10108 | 1124 | } |
jackalmage@8992 | 1125 | |
jackalmage@8992 | 1126 | body { font-family: latin-serif, jpn-mincho; } |
jackalmage@10108 | 1127 | </style> |
jackalmage@8992 | 1128 | <p>ç´è±ã¯ãããã§ãããã |
jackalmage@8992 | 1129 | </pre> |
jackalmage@8992 | 1130 | |
jackalmage@8992 | 1131 | In this situation, the user agent first downloads âlatinserif.woffâ |
jackalmage@10108 | 1132 | and then tries to use this to draw the Japanese text. |
jackalmage@10108 | 1133 | But because no Japanese glyphs are present in that font, |
jackalmage@10108 | 1134 | fallback occurs and the font âmincho.woffâ is downloaded. |
jackalmage@14551 | 1135 | Only after the second font is downloaded and the Japanese text laid out does the {{loadingdone}} event fire. |
jackalmage@10108 | 1136 | |
jackalmage@10108 | 1137 | The "unused" font isn't loaded, |
jackalmage@10108 | 1138 | but no text is using it, |
jackalmage@10108 | 1139 | so the UA isn't even <em>trying</em> to load it. |
jackalmage@14551 | 1140 | It doesn't interfere with the {{loadingdone}} event. |
jackalmage@8992 | 1141 | </div> |
jackalmage@8992 | 1142 | |
jackalmage@8992 | 1143 | |
jackalmage@8992 | 1144 | <h2 class="no-num" id="changes">Changes</h2> |
jackalmage@8992 | 1145 | |
jackalmage@14016 | 1146 | Changes from the <a href="http://www.w3.org/TR/2014/WD-css-font-loading-3-20140522/">May 2014 CSS Font Loading Last Call Working Draft</a>: |
jackalmage@8992 | 1147 | |
jackalmage@14016 | 1148 | <ol> |
jackalmage@14016 | 1149 | <li> |
jackalmage@14126 | 1150 | Corrected the async algorithms to use "queue a task" language, |
jackalmage@14016 | 1151 | to ensure that side-effect timing is well-defined. |
jackalmage@14016 | 1152 | </ol> |
jackalmage@8992 | 1153 | |
jackalmage@8992 | 1154 | <h2 class=no-num id=acknowledgments> |
jackalmage@8992 | 1155 | Acknowledgments</h2> |
jackalmage@8992 | 1156 | |
jackalmage@8992 | 1157 | Several members of the Google Fonts team provided helpful feedback on font load events, |
jackalmage@9495 | 1158 | as did Boris Zbarsky, Jonas Sicking and ms2ger. |