1. はじめに
CSSは、@font-face規則を使って、ウェブからカスタムフォントを著者が読み込むことを可能にします。 スタイルシートを作成する際には簡単ですが、 スクリプトで動的に利用するのはかなり難しくなります。
さらに、CSSではユーザーエージェントが実際にフォントをロードするタイミングを選択できます。 ページ上でフォントフェイスが現在何も使われていない場合、 多くのユーザーエージェントは関連ファイルをダウンロードしません。 つまり、後からそのフォントフェイスを使用すると、 ユーザーエージェントが利用を検知してフォントファイルのダウンロードと解析を開始するまで遅延が発生します。
この仕様は、CSSのフォントフェイスに対するスクリプティングインターフェイスを定義し、
フォントフェイスを簡単に作成(FontFace
インターフェイス経由)
およびスクリプトからロード(document.fonts経由)できるようにします。
また、個々のフォントやページ全体のフォントのロード状況を追跡するメソッドも提供します。
この仕様書のいくつかの箇所では、通常のESオブジェクトを使って挙動を定義しています。 例えば内部的にPromiseを利用したり、 FontFaceSetがSetを内部で使うなどです。 ここで意図しているのは、これらのオブジェクト(およびそのプロトタイプチェーン)がプリスティンであり、 著者が行ったいかなる操作にも影響されないことだと思っています。 この意図は良いものでしょうか? もしそうなら、仕様書内でどう記載すべきでしょうか?
1.1. 値
この仕様では、Promise(
ECMAScript
6で定義)を使用します。
MDNにはPromiseを導入する良いチュートリアル資料があります。
1.2. タスクソース
この仕様がタスクをキューするときは、"font loading"タスクソースにキューします。
2. FontFaceインターフェイス
FontFace
インターフェイスは、1つの利用可能なフォントフェイスを表します。
CSSの@font-face規則は暗黙的にFontFaceオブジェクトを定義しますし、
URLやバイナリデータから手動で構築することもできます。
typedef (ArrayBuffer or ArrayBufferView );BinaryData dictionary {FontFaceDescriptors CSSOMString = "normal";style CSSOMString = "normal";weight CSSOMString = "normal";stretch CSSOMString = "U+0-10FFFF";unicodeRange CSSOMString = "normal";variant CSSOMString = "normal";featureSettings CSSOMString = "normal";variationSettings CSSOMString = "auto";display CSSOMString = "normal";ascentOverride CSSOMString = "normal";descentOverride CSSOMString = "normal"; };lineGapOverride enum {FontFaceLoadStatus ,"unloaded" ,"loading" ,"loaded" }; ["error" Exposed =(Window ,Worker )]interface {FontFace constructor (CSSOMString , (family CSSOMString or BinaryData ),source optional FontFaceDescriptors = {});descriptors attribute CSSOMString family ;attribute CSSOMString style ;attribute CSSOMString weight ;attribute CSSOMString stretch ;attribute CSSOMString unicodeRange ;attribute CSSOMString variant ;attribute CSSOMString featureSettings ;attribute CSSOMString variationSettings ;attribute CSSOMString display ;attribute CSSOMString ascentOverride ;attribute CSSOMString descentOverride ;attribute CSSOMString lineGapOverride ;readonly attribute FontFaceLoadStatus status ;Promise <FontFace >load ();readonly attribute Promise <FontFace >loaded ; };
"the document"という表現について、どの文書を指しているのか明確にするようにしてください。 オブジェクトが文書間を移動する可能性があるためです。
family, 型: CSSOMStringstyle, 型: CSSOMStringweight, 型: CSSOMStringstretch, 型: CSSOMStringunicodeRange, 型: CSSOMString-
これらの属性はすべて、CSSの@font-face規則で定義される記述子で定義されるフォントフェイスの該当側面を表します。 対応する@font-face記述子と同じようにパースされます。 これらはフォントマッチングアルゴリズムで使われますが、それ以外には影響しません。
例えば、
FontFaceのstyle属性が"italic"の場合、「イタリック体のフォントフェイス」を表しますが、 フォントフェイス自体をイタリック体にするわけではありません。取得時は、この属性に関連付けられた文字列を返します。
設定時は、対応する記述子の文法に従って文字列をパースします。 文法と一致しない場合は、
SyntaxErrorを投げます。 一致すれば、パースされた値のシリアライズを属性に設定します。 variant, 型: CSSOMStringfeatureSettings, 型: CSSOMStringvariationSettings, 型: CSSOMStringdisplay, 型: CSSOMStringascentOverride, 型: CSSOMStringdescentOverride, 型: CSSOMStringlineGapOverride, 型: CSSOMString-
これらの属性も同じ意味を持ち、 CSSの@font-face規則の対応する記述子と同じようにパースされます。
対応するフォントがサポートしていれば、特定の機能をオン・オフします。 前述の属性と違い、 これらの属性はフォントフェイス自体に実際に影響します。
取得時は、この属性に関連付けられた文字列を返します。
設定時は、対応する記述子の文法に従って文字列をパースします。 文法と一致しない場合は、
SyntaxErrorを投げます。 一致すれば、パースされた値のシリアライズを属性に設定します。 status, 型: FontFaceLoadStatus, 読み取り専用-
この属性は、フォントフェイスの現在の状態を反映します。 新しく作成した
FontFaceでは"unloaded"でなければなりません。著者が明示的にフォントフェイスのロードを要求した場合(例えば、
load()メソッドやFontFace経由)、 またはユーザーエージェントが画面のテキスト描画に必要だと検知した場合に状態が変化する可能性があります。 loaded, 型: Promise<FontFace>, 読み取り専用-
この属性はフォントフェイスの
[[FontStatusPromise]]を反映します。
すべてのFontFace
オブジェクトは、フォントの状態を追跡する内部スロット[[FontStatusPromise]]を持っています。
初期状態はpendingで、
フォントが正常にロード・解析された場合やエラーが発生した場合にfulfillまたはrejectされます。
すべてのFontFace
オブジェクトにはさらに、
内部スロット[[Urls]]と[[Data]]も含まれます。
片方はnullで、もう片方はnullではありません(コンストラクターで渡されたデータによって設定されます)。
2.1. コンストラクター
FontFaceは、
フォントフェイスファイルへのURL、
またはフォントフェイスのバイナリ表現を含むArrayBuffer
(またはArrayBufferView)
から構築できます。
FontFace(family, source, descriptors)メソッドが呼び出されたとき、以下の手順を実行します:
-
font faceを新しい
FontFaceオブジェクトとして作成する。 font faceのstatus属性を"unloaded"に設定し、 内部スロット[[FontStatusPromise]]を新しいpending状態のPromiseオブジェクトに設定する。family引数と
descriptors引数の各メンバーを、CSS@font-face規則の各記述子の文法に従ってパースする。source引数がCSSOMStringの場合は、 src記述子の文法に従ってパースする。 いずれかが正しくパースできない場合は、 font faceの[[FontStatusPromise]]を"SyntaxError"という名前のDOMExceptionでrejectし、 font faceの該当属性を空文字列に設定し、 font faceのstatus属性を"error"に設定する。 それ以外の場合は、解析された値のシリアライズを各属性に設定する。注: source引数に裸のURLを渡しても動作しません(例:
"http://example.com/myFont.woff")。 少なくともurl() 関数でラップする必要があります(例:"url(http://example.com/myFont.woff)")。 この手間の代わりに、複数のフォールバック指定や各フォールバックのフォントタイプ指定、 ローカルフォントの参照が簡単にできます。基底URLの定義が必要です。 相対URLを解決するために、文書のURLを使うべきでしょうか? Workerの場合はWorkerのURLを使うべきか? 常に定義されていますか?
font faceを返す。 font faceの
statusが"error"の場合はこのアルゴリズムを終了し、 それ以外の場合は残りの手順を非同期で完了する。 -
source引数がCSSOMStringの場合は、 font faceの内部スロット[[Urls]]にその文字列を設定する。source引数がBinaryDataの場合は、 font faceの内部スロット[[Data]]に渡された引数を設定する。 -
font faceの
[[Data]]スロットがnullでない場合、以下の手順を同期的に実行するタスクをキューする:-
font faceの
status属性を"loading"に設定する。 -
font faceが所属する各
FontFaceSetについて:-
FontFaceSetの[[LoadingFonts]]リストが空なら、FontFaceSetをloadingに切り替える。 -
font faceを
FontFaceSetの[[LoadingFonts]]リストに追加する。
-
非同期的に、内部データをフォントとして解析を試みる。 完了したら(成功・失敗いずれでも)以下の手順を同期的に実行するタスクをキューする:
-
ロードが成功した場合、font faceは解析されたフォントを表すようになり、 font faceの
[[FontStatusPromise]]をfont faceでfulfillし、status属性を"loaded"に設定する。font faceが所属する各
FontFaceSetについて:-
font faceを
FontFaceSetの[[LoadedFonts]]リストに追加する。 -
font faceを
FontFaceSetの[[LoadingFonts]]リストから削除する。 そのリストの最後の項目だった場合(空になった場合)はFontFaceSetをloadedに切り替える。
-
-
それ以外の場合は、 font faceの
[[FontStatusPromise]]を"SyntaxError"という名前のDOMExceptionでrejectし、status属性を"error"に設定する。font faceが所属する各
FontFaceSetについて:-
font faceを
FontFaceSetの[[FailedFonts]]リストに追加する。 -
font faceを
FontFaceSetの[[LoadingFonts]]リストから削除する。 そのリストの最後の項目だった場合(空になった場合)はFontFaceSetをloadedに切り替える。
-
-
注: 新しく構築されたFontFaceオブジェクトは、 文書やWorkerスレッドのコンテキストに関連するFontFaceSetに自動的に追加されません。 そのため、構築直後のフォントはプリロードできても、 明示的にFontFaceSetに追加しない限り実際には利用できません。 FontFaceSetの詳細は次節を参照してください。
2.2. load()メソッド
load()
メソッドは、URLベースのフォントフェイスに対してフォントデータのリクエストとロードを強制します。
バイナリデータから構築されたフォントや、すでにロード中・ロード済みのフォントには何もしません。
load()メソッドが呼び出されたとき、以下の手順を実行します:
- font faceを、このメソッドが呼び出された
FontFaceオブジェクトとする。 - font faceの
[[Urls]]スロットがnull、またはstatus属性が"unloaded"以外の場合は、 font faceの[[FontStatusPromise]]を返して、これ以降の手順を中断する。 - それ以外の場合は、
font faceの
status属性を"loading"に設定し、 font faceの[[FontStatusPromise]]を返し、このアルゴリズムの残りを非同期で続行する。 - font faceの
[[Urls]]スロットの値を使って、 [CSS-FONTS-3]で定義されるようにフォントのロードを試みる。 @font-face規則のsrc記述子の値として扱う。 -
ロード操作が完了したら(成功・失敗いずれでも)以下の手順を同期的に実行するタスクをキューする:
-
ロードに失敗した場合は、
font faceの
[[FontStatusPromise]]を 名前が"NetworkError"のDOMExceptionでrejectし、 font faceのstatus属性を"error"に設定する。font faceが所属する各
FontFaceSetについて:-
font faceを
FontFaceSetの[[FailedFonts]]リストに追加する。 -
font faceを
FontFaceSetの[[LoadingFonts]]リストから削除する。 そのリストの最後の項目だった場合(空になった場合)はFontFaceSetをloadedに切り替える。
-
-
それ以外の場合は、font faceがロード済みのフォントを表すようになり、
font faceの
[[FontStatusPromise]]をfont faceでfulfillし、 font faceのstatus属性を"loaded"に設定する。font faceが所属する各
FontFaceSetについて:-
font faceを
FontFaceSetの[[LoadedFonts]]リストに追加する。 -
font faceを
FontFaceSetの[[LoadingFonts]]リストから削除する。 そのリストの最後の項目だった場合(空になった場合)はFontFaceSetをloadedに切り替える。
-
-
ロードに失敗した場合は、
font faceの
ユーザーエージェントは、ページ上の何かを描画するために特定のフォントフェイスが必要と判断した場合、
自動的にフォントロードを開始できます。
この場合は、ここで説明されている該当FontFaceのload()
メソッドを呼び出したかのように動作しなければなりません。
注: 一部のUAは「フォントキャッシュ」を利用して、
同じフォントをページ内や同一オリジンの複数ページで何度もダウンロードすることを避けます。
複数のFontFaceオブジェクトが同じフォントキャッシュのエントリにマッピングされる場合があり、
そのためFontFaceオブジェクトが
予期せずロードを開始することがあります。
たとえそれがFontFaceSetに所属していなくても、
他のFontFaceオブジェクトが
同じフォントデータを参照している場合(まったく別のページでも!)ロードが始まることがあります。
2.3. CSSの@font-face規則との連携
CSSの@font-face規則は、該当するFontFaceオブジェクトを自動的に定義し、規則がパースされると同時にドキュメントのfont sourceに自動的に配置されます。
このFontFaceオブジェクトはCSS接続済みです。
@font-face規則に対応するFontFace
オブジェクトは、family、
style、
weight、
stretch、
unicodeRange、
variant、
featureSettings
の属性に、@font-face規則の該当する記述子の値が設定されます。
これらは双方向に連携しており、@font-face記述子に変更があると、即座に対応するFontFace属性に反映され、逆も同様です。
FontFaceが文書間で転送された場合、CSS接続済みでなくなります。
FontFaceオブジェクトの内部[[Urls]]スロットは、@font-face規則のsrc記述子の値が設定され、その記述子に変更があれば反映されます。
それ以外は、CSSの@font-face規則により生成されたFontFaceオブジェクトは、手動で作成したものと同一です。
@font-face規則がドキュメントから削除されると、対応するFontFaceオブジェクトはCSS接続済みでなくなります。
この連携はどの手段でも復元できません(ただし、@font-faceをスタイルシートに再追加すれば、新しいFontFaceオブジェクトが作成され、それはCSS接続済みとなります)。
@font-face規則のsrc記述子が新たな値に変更された場合、
元のCSS接続済みFontFaceオブジェクトはCSS接続済みでなくなる必要があります。
新しいsrcを反映する新しいFontFaceオブジェクトが作成され、CSS接続済みとして@font-faceに連携されます。
(これにより古いFontFaceオブジェクトはfont sourcesから削除、新しいものが追加されます)
2.4. フォント情報の取得
FontFace
オブジェクトには、フォントファイルの内容に関するさまざまな読み取り専用情報が含まれます。
[Exposed =(Window ,Worker )]interface { /* The CSSWG is still discussing what goes in here */ }; [FontFaceFeatures Exposed =(Window ,Worker )]interface {FontFaceVariationAxis readonly attribute DOMString ;name readonly attribute DOMString ;axisTag readonly attribute double ;minimumValue readonly attribute double ;maximumValue readonly attribute double ; }; [defaultValue Exposed =(Window ,Worker )]interface {FontFaceVariations readonly setlike <FontFaceVariationAxis >; }; [Exposed =(Window ,Worker )]interface {FontFacePalette iterable <DOMString >;readonly attribute unsigned long ;length getter DOMString (unsigned long );index readonly attribute boolean ;usableWithLightBackground readonly attribute boolean ; }; [usableWithDarkBackground Exposed =(Window ,Worker )]interface {FontFacePalettes iterable <FontFacePalette >;readonly attribute unsigned long ;length getter FontFacePalette (unsigned long ); };index partial interface FontFace {readonly attribute FontFaceFeatures ;features readonly attribute FontFaceVariations ;variations readonly attribute FontFacePalettes ; };palettes
注: この読み取り専用データは、font-feature-settingsやfont-variation-settings、 @font-palette-valuesでどんな値が使えるか、著者が把握しやすいように設計されています。
3. FontFaceSetインターフェイス
dictionary :FontFaceSetLoadEventInit EventInit {sequence <FontFace >= []; }; [fontfaces Exposed =(Window ,Worker )]interface :FontFaceSetLoadEvent Event {(constructor CSSOMString ,type optional FontFaceSetLoadEventInit = {}); [eventInitDict SameObject ]readonly attribute FrozenArray <FontFace >; };fontfaces enum {FontFaceSetLoadStatus ,"loading" }; ["loaded" Exposed =(Window ,Worker )]interface :FontFaceSet EventTarget {constructor (sequence <FontFace >);initialFaces setlike <FontFace >;FontFaceSet add (FontFace );font boolean delete (FontFace );font undefined clear (); // events for when loading state changesattribute EventHandler ;onloading attribute EventHandler ;onloadingdone attribute EventHandler ; // check and start loads if appropriate // and fulfill promise when all loads completeonloadingerror Promise <sequence <FontFace >>load (CSSOMString font ,optional CSSOMString text = " "); // return whether all fonts in the fontlist are loaded // (does not initiate load if not available)boolean check (CSSOMString font ,optional CSSOMString text = " "); // async notification that font loading and layout operations are donereadonly attribute Promise <FontFaceSet >ready ; // loading state, "loading" while one or more fonts loading, "loaded" otherwisereadonly attribute FontFaceSetLoadStatus ; };status
ready, 型: Promise<FontFaceSet>, 読み取り専用-
この属性は
FontFaceSetの[[ReadyPromise]]スロットを反映します。この
Promiseとその使い方の詳細は§ 3.4 ready属性を参照してください。 FontFaceSet(initialFaces)-
FontFaceSetコンストラクターは、呼び出されたとき、initialFaces引数を反復し、 すべての値をset entriesに追加しなければなりません。 - 反復順序
-
反復時、すべてのCSS接続済み
FontFaceオブジェクトが先に来ます(接続された@font-face規則のドキュメント順)。 その後に非CSS接続済みFontFaceオブジェクトが追加順で並びます。 - set entries
-
FontFaceSetがfont sourceの場合、 set entriesは§ 4.2 CSSの@font-face規則との連携に従って初期化されます。それ以外の場合は、set entriesは初期状態で空です。
add(font)-
add()メソッドが呼び出されたとき、以下の手順を実行します:-
fontがすでに
FontFaceSetのset entriesに含まれている場合は、このアルゴリズムの最後の手順に即座に進みます。 -
fontがCSS接続済みの場合、
InvalidModificationError例外をthrowし、即座にこのアルゴリズムを終了します。 -
font引数を
FontFaceSetのset entriesに追加します。 -
fontの
status属性が"loading"の場合:-
FontFaceSetの[[LoadingFonts]]リストが空なら、FontFaceSetをloadingに切り替えます。 -
fontを
FontFaceSetの[[LoadingFonts]]リストに追加します。
-
-
FontFaceSetを返します。
-
delete(font)-
delete()メソッドが呼び出されたとき、以下の手順を実行します:-
fontがCSS接続済みの場合、
を返して即座にこのアルゴリズムを終了します。false -
deletedに、fontを
FontFaceSetのset entriesから削除した結果を設定します。 -
fontが
FontFaceSetの[[LoadedFonts]]または[[FailedFonts]]リストに含まれている場合、削除します。 -
fontが
FontFaceSetの[[LoadingFonts]]リストに含まれている場合、削除します。 そのリストの最後の項目だった場合(空になった場合)はFontFaceSetをloadedに切り替えます。 -
deletedを返します。
-
clear()-
clear()メソッドが呼び出されたとき、以下の手順を実行します:-
非CSS接続済み項目を
FontFaceSetのset entries、[[LoadedFonts]]リスト、[[FailedFonts]]リストから削除します。 -
FontFaceSetの[[LoadingFonts]]リストが空でなければ、すべて削除し、その後FontFaceSetをloadedに切り替えます。
-
FontFaceSetオブジェクトは、内部に[[LoadingFonts]]、[[LoadedFonts]]、[[FailedFonts]]スロットを持ち、すべて空リストで初期化されます。
また、[[ReadyPromise]]スロットを持ち、これは新しいpending状態のPromiseで初期化されます。
フォントファミリーは使用されたときだけロードされるため、 コンテンツがフォントのロードタイミングを把握する必要がある場合があります。 著者はここで定義されたイベントやメソッドを使って、 特定フォントの利用可能性に依存するアクションをより細かく制御できます。
FontFaceSetは、次のいずれかが真の場合、環境でpendingです:
-
文書がまだロード中の場合
-
文書にスタイルシートリクエストがpendingの場合
-
文書に、ユーザーエージェントがフォントリクエストする可能性がある、または最近ロードされたフォントに依存するレイアウト処理がpendingの場合
注: FontFaceSetが環境でpendingでなくなった時点で、以降文書に変化がなければ、著者はサイズや位置の測定値が「正しい」と信頼できます。
上記条件がこの保証を十分に表現できていなければ、修正が必要です。
3.1. イベント
フォントロードイベントを使うことで、ドキュメント全体のフォントロード挙動に簡単に対応でき、個々のフォントごとに監視する必要がなくなります。
loadingイベントは
ドキュメントがフォントのロードを開始した際に発火し、
loadingdoneおよびloadingerrorイベントは
ドキュメントのフォントロードが完了した際に発火し、それぞれ成功したフォント・失敗したフォントを含みます。
以下はFontFaceSetオブジェクトがIDL属性としてサポートしなければならないイベントハンドラー(および対応するイベントタイプ)です:
| イベントハンドラー | イベントハンドラーイベントタイプ |
|---|---|
onloading
| loading
|
onloadingdone
| loadingdone
|
onloadingerror
| loadingerror
|
eという名前のフォントロードイベントを発火するには、FontFaceSetのtargetで、オプションとしてfont
facesを指定し、以下の条件を満たすFontFaceSetLoadEventインターフェイスを使って単純なイベントを発火することを意味します:
指定されたFontFaceSetについてFontFaceSetをloadingに切り替えるよう要求された場合、ユーザーエージェントは以下の手順を実行します:
- font face setを指定された
FontFaceSetとする。 - font face setの
status属性を"loading"に設定する。 - font face setの
[[ReadyPromise]]スロットが現在fulfilledなpromiseを保持している場合、新しいpending promiseに置き換える。 - font face setに
loadingという名前のフォントロードイベントを発火するタスクをキューする。
指定されたFontFaceSetについてFontFaceSetをloadedに切り替えるよう要求された場合、ユーザーエージェントは以下の手順を実行します:
-
font face setを指定された
FontFaceSetとする。 -
font face setが環境でpendingの場合、 それを環境でstuckとマークし、このアルゴリズムを終了します。
-
font face setの
status属性を"loaded"に設定します。 -
font face setの
[[ReadyPromise]]属性値をfont face setでfulfillします。 -
同期的に以下の手順を実行するタスクをキューします:
-
loaded fontsをfont face setの
[[LoadedFonts]]スロットの内容(空の場合もあり)とする。 -
failed fontsをfont face setの
[[FailedFonts]]スロットの内容(空の場合もあり)とする。 -
[[LoadedFonts]]と[[FailedFonts]]スロットを空リストにリセットする。 -
font face setにloaded fontsを使って、
loadingdoneという名前のフォントロードイベントを発火する。 -
もしfont face setのfailed fontsが空でない場合、failed fontsを使って
loadingerrorという名前のフォントロードイベントを発火する。
-
FontFaceSetが環境でpendingからpendingでなくなった際、ユーザーエージェントは以下の手順を実行しなければなりません:
-
もし
FontFaceSetが環境にスタックされている状態で、 その[[LoadingFonts]]リストが空の場合、FontFaceSetをloaded状態に切り替える。 -
もし
FontFaceSetが環境にスタックされている状態なら、 その印付けを解除する。
FontFaceSetからマッチするフォントフェイスを探すには、 source(FontFaceSet)、font(フォント文字列)、オプションのサンプルテキストtext、オプションのallow system fontsフラグを指定し、以下の手順を実行します:
-
fontをfontプロパティのCSS値構文でパースする。
構文エラーが発生した場合は、構文エラーを返す。
パースされた値がCSS全体キーワードの場合は、構文エラーを返す。
すべての相対長さは、対応するプロパティの初期値に対して絶対化する(例:bolderは初期値normalに対して評価される)。
- textが明示的に指定されていなければ、U+0020 SPACEのみからなる1文字の文字列とする。
- font family listをfontからパースしたフォントファミリーリスト、font styleをその他のスタイル属性とする。
- available font facesをsource内の利用可能なフォントフェイスのリストとする。 allow system fontsフラグが指定されていれば、すべてのシステムフォントも追加する。
- matched font facesを空リストで初期化する。
- font family list内の各familyに対し、フォントマッチングルールを使ってavailable font facesからfont
styleに一致するフォントフェイスを選び、matched font facesに追加する。
unicodeRange属性の利用により、1つ以上のフォントフェイスが選ばれる場合がある。 - matched font facesが空の場合、found facesフラグをfalseに設定する。 そうでなければtrueに設定する。
-
matched font faces内の各フォントフェイスについて、
定義されたunicode-rangeがtext内の少なくとも1文字のコードポイントを含まない場合は、リストから削除する。
注: したがって、textが空文字列なら、すべてのフォントが削除される。
- matched font facesとfound facesフラグを返す。
3.2. load()メソッド
load()
メソッド(FontFaceSet)は、指定されたフォントリスト内のすべてのフォントがロード済みで利用可能かどうかを判定します。
ダウンロード可能なフォントで、まだロードされていないものがあれば、
ユーザーエージェントはそれらのロードを開始します。
このメソッドはPromiseを返し、
全てのフォントがロード・利用可能になった時にfulfilledとなり、
いずれかのフォントのロードに失敗した場合はrejectされます。
load( font, text )
メソッドが呼び出された際、以下の手順を実行します:
- font face setをこのメソッドが呼ばれた
FontFaceSetオブジェクトとする。 promiseを新しく作成したpromiseオブジェクトとする。 - promiseを返す。 残りの手順は非同期で完了する。
- font face setから、関数に渡された
font引数とtext引数を使って該当フォントフェイスを検索する。 戻り値をfont face listとし(found facesフラグは無視する)。 もし構文エラーが返された場合は、promiseをSyntaxError例外で拒否し、この手順を終了する。 -
同期的に以下の手順を実行するタスクをキューする:
- font face list内のすべてのフォントフェイスについて、
load()メソッドを呼び出す。 - font face list内の各フォントフェイスの
[[FontStatusPromise]]を順番に待機し、その結果でpromiseをresolveする。
- font face list内のすべてのフォントフェイスについて、
3.3. check()メソッド
check()
メソッド(FontFaceSet)は、指定されたテキストとフォントリストで「安全に」レンダリングできるかどうかを判定します。
つまり、後で「フォントスワップ」が発生しないかどうかです。
指定されたテキスト/フォントの組み合わせが、未ロードまたはロード中のフォントを使おうとせずにレンダリングされる場合はtrueを返し、
そうでなければfalseを返します。
-
指定フォントが存在していても、unicode-rangeが指定テキストをカバーしないために、 すべてのフェイスが除外された場合、メソッドは
trueを返します。 この場合、テキストはUAのフォールバックフォントで描画され、フォントロードは発生しません。 -
同様に、指定フォントが何も存在しない場合(例えば名前のスペルミスなど)も、メソッドは
trueを返します。 このフォントリストを使ってもロードは発生せず、フォールバックになります。
check( font, text)
メソッドが呼び出されたとき、以下の手順を実行します:
- font face setを、このメソッドが呼び出された
FontFaceSetオブジェクトとする。 -
font引数とtext引数を使い、システムフォントも含めてfont face setから一致するフォントフェイスを検索し、 戻り値のフォントフェイスリストをfont face list、戻り値のfound facesフラグをfound facesとする。 構文エラーが返された場合は、SyntaxError例外を投げて、これらの手順を終了する。 - font face listが空、またはfont face list内の全てのフォントが
status属性が"loaded"であるかシステムフォントの場合は、trueを返す。 それ以外の場合はfalseを返す。
3.4. ready属性
どのフォントがロードされるかは、どのテキストで何フォントが使われるかによって異なるため、場合によってはロードの必要性が分からないことがあります。
ready
属性には、ドキュメントのフォントロードが完了した時にresolveされるPromiseが格納されます。
これにより、著者はどのフォントがロード済みかを個別に管理せずとも、フォントロードに影響されるコンテンツを安全に参照できます。
注: ready
promiseは1度だけfulfilledになりますが、その後でもさらにフォントがロードされる可能性があります。
これはloadingdone
イベントを監視するのに似ていますが、ready
Promiseのコールバックは、対象フォントがすでにロード済みの場合でも必ず呼び出されます。
必要なフォントやロードタイミングを逐一管理せずに、コードをフォントロードに同期させるシンプルな方法です。
注: UAはready promiseがfulfilledされるまで複数回にわたってフォントロードを繰り返す場合があります。 これはフォントフォールバック等で、フォントリスト内の一つがロードされても該当グリフがない場合に他のフォントもロードされるケースです。 ready promiseはレイアウト処理が完了し、追加のフォントロードが不要になった時点でのみfulfilledされます。
注: このready
属性が返すPromiseはrejectされることはなく、必ずfulfilledになります。
これはFontFaceのload()
メソッドが返すPromiseと異なります。
3.5. CSSフォントのロードとマッチングとの連携
[CSS-FONTS-3]のフォントマッチングアルゴリズムがUAにより自動実行される際、対象となるフォントフェイスの集合は、ドキュメントのfont sourceに含まれるフォントに加え、ローカルフォントフェイスの集合でなければなりません。
UAがフォントフェイスのロードを必要とする場合は、該当FontFaceオブジェクトのload()
メソッドを呼び出すことでロードしなければなりません。
(これは同じアルゴリズムを実行するという意味であり、オブジェクトのloadプロパティに現在格納されている値を文字通り呼ぶわけではありません。)
FontFaceSetに追加されると利用可能になります。
新しい@font-face規則をスタイルシートに追加すると、
新しいFontFaceが
FontFaceSetに追加されます(Documentオブジェクト)。
新しい@font-face規則の追加例:
document. styleSheets[ 0 ]. insertRule( "@font-face { font-family: newfont; src: url(newfont.woff); }" , 0 ); document. body. style. fontFamily= "newfont, serif" ;
新しいFontFace
オブジェクトを構築してdocumentに追加する例:
var f= new FontFace( "newfont" , "url(newfont.woff)" ); document. fonts. add( f); document. body. style. fontFamily= "newfont, serif" ;
どちらの場合も、レイアウトエンジンが「newfont.woff」リソースのロードを開始します。他の@font-face規則のフォントと同様です。
documentに追加しない場合は、フォントはロードされず、
テキストはデフォルトのserifフォントで表示されます:
var f= new FontFace( "newfont" , "url(newtest.woff)" , {}); /* 新しい {{FontFace}} は {{FontFaceSet}} に追加されていないため、 'font-family'プロパティからは参照できず、serifが使用される */ document. body. style. fontFamily= "newfont, serif" ;
フォントを使用前に明示的にプリロードする場合、新しいFontFaceをFontFaceSetに追加するまでロード完了を待つことができます:
var f= new FontFace( "newfont" , "url(newfont.woff)" , {}); f. load(). then( function ( loadedFace) { document. fonts. add( loadedFace); document. body. style. fontFamily= "newfont, serif" ; });
この場合、まず「newfont.woff」がダウンロードされ、ダウンロード完了後にフォントがドキュメントのFontFaceSetに追加され、bodyのフォントを変更し、レイアウトエンジンが新しいフォントリソースを使います。
4. FontFaceSourceミックスイン
interface mixin {FontFaceSource readonly attribute FontFaceSet ; };fonts Document includes FontFaceSource ;WorkerGlobalScope includes FontFaceSource ;
任意のドキュメント、ワーカー、またはフォントを利用できる他のコンテキストは、FontFaceSourceミックスインを含める必要があります。
コンテキストのfonts属性の値は、そのfont sourceとなり、
特に指定がなければフォント関連操作で使われる全フォントを提供します。
「font source」を参照する操作は、該当コンテキストのfont
sourceを指すものとして解釈されます。
これらコンテキスト内で行われるフォント関連操作では、font
source内のFontFaceオブジェクトが利用可能なフォントフェイスとなります。
4.1. WorkerのFontFaceSource
Workerドキュメント内では、font sourceは初期状態で空です。
注: FontFaceオブジェクトは通常通り構築して追加でき、
Worker内のCSSフォントマッチング(例えばOffscreenCanvasでテキスト描画等)に影響します。
4.2. CSSの@font-face規則との連携
ドキュメントのfont sourceのset
entriesは、すべてのCSS@font-face規則から得られるCSS接続済みFontFaceオブジェクトで初期化され、ドキュメント順に並べられます。
@font-face規則やそれを含むスタイルシートの追加/削除に伴い、
対応するCSS接続済みFontFaceオブジェクトもドキュメントのfont sourceから追加・削除され、この順序を保ちます。
手動で追加されたFontFaceオブジェクトは、CSS接続済みのものより後ろに並べられます。
FontFaceSetオブジェクトのadd()メソッドにCSS接続済みFontFaceオブジェクトを渡した場合、オブジェクトがすでにセット内にある場合はno-op、
そうでなければ何もせずInvalidModificationErrorをthrowします。
FontFaceSetオブジェクトのdelete()メソッドにCSS接続済みFontFaceオブジェクトを渡した場合はno-opとして、を返します。
注: 削除されたFontFaceへの参照は著者が保持可能ですが、§ 2.3 CSSの@font-face規則との連携にある通り、その時点ではFontFaceはCSS接続済みではありません。
注: 今後の仕様ではローカルフォントへの操作やクエリ方法も定義される予定です。
5. API例
document. fonts. ready. then( function () { var content= document. getElementById( "content" ); content. style. visibility= "visible" ; });
function drawStuff() { var ctx= document. getElementById( "c" ). getContext( "2d" ); ctx. fillStyle= "red" ; ctx. font= "50px MyDownloadableFont" ; ctx. fillText( "Hello!" , 100 , 100 ); } document. fonts. load( "50px MyDownloadableFont" ) . then( drawStuff, handleError);
function measureTextElements() { // ダウンロード可能フォントのメトリクスで計測可能 } function doEditing() { // フォントロードを発生させる可能性のあるコンテンツ/レイアウト操作 document. fonts. ready. then( measureTextElements); }
loadingdone
イベントは、すべてのフォント関連ロードが完了し、テキストが追加のフォントロードなしでレイアウトされた後のみ発火します:
< style > @ font-face { font-family : latin-serif ; src : url ( latinserif . woff ) format ( "woff" ); /* 漢字・仮名を含まない */ } @ font-face { font-family : jpn-mincho ; src : url ( mincho . woff ) format ( "woff" ); } @ font-face { font-family : unused ; src : url ( unused . woff ); } body { font-family : latin-serif , jpn-mincho ; } </ style > < p > 納豆はいかがでしょうか
この場合、UAはまず「latinserif.woff」をダウンロードし、日本語テキストを描画しようとします。
しかしそのフォントに日本語グリフがないため、フォールバックとして「mincho.woff」がダウンロードされます。
2つ目のフォントがダウンロードされ、日本語テキストがレイアウトされた後、loadingdone
イベントが発火します。
"unused"フォントはロードされませんが、テキストがそれを利用していないため、UAはロードしようとすらしません。
これはloadingdone
イベントには影響しません。
変更点
2014年5月 CSS Font Loading Last Call Working Draftからの変更点:
- フォント情報取得用IDLを追加
- FontFaceSet.clear()がCSS接続済み項目をクリアしないことを明確化
- はじめにでdocument.fontsに言及
- フォントロードはシャドウルートにも適用
- 指定フォントが存在しない場合はエラーを投げず、ロードも発生しない
- WebIDLとの整合性向上
- constructor()メソッド構文へ変更
- マッチングアルゴリズムの空文字列処理を明確化
- FontFaceSourceをmixin化
- CanvasProxyをOffscreenCanvasに変更
- FontFaceと@font-faceの整合性向上、variationSettingsとfontDisplay追加
- ID Lで一貫して[Exposed]を利用
- DOMStringよりCSSOMStringを優先
- check()の説明文改善
- 最近ロードされたフォントに依存するレイアウト処理は完了を待つ必要があることを明確化
- loadイベント発火時のエッジケースを網羅
- 非同期イベントキューイングを同期呼び出しより優先
- fonts.readyは関数ではなくプロパティ
- 存在しないフォントと必要グリフが欠けているフォントの区別
- 複数メソッドの手順を明確化
- load()とcheck()でグローバルキーワードや相対値の扱いを明確化
- src引数のパースはCSS @font-face src記述子と同様
- CSS接続済みフォント削除は効果なし、falseを返すことを明確化
- 重複フォント追加の効果はなし
- 手動追加FontFaceオブジェクトの順序明確化
- loadイベントはセット内に残っているfaceのみ含むことを明確化
variationSettingsとdisplayを@font-faceと同期fontfacesをFrozenArrayに変更し、IDL慣例に合わせた- FontFaceSetにロード中フォントを追加した際のloadingイベント発火とPromise処理を追加
- 非同期アルゴリズムを"queue a task"記述に修正、タイミングの明確化
- 複数参照を最新版へ更新
- IDL修正
- その他のタイポ修正と文法ミス訂正
謝辞
Google Fontsチームの数名のメンバー、ならびにBoris Zbarsky、Jonas Sicking、ms2gerからフォントロードイベントについて有益なフィードバックをいただきました。
プライバシーに関する考慮事項
FontFaceSet
オブジェクトはユーザーがインストールしているフォント情報を漏洩しますが、既存の@font-face規則と全く同じ方法です。
新たな情報が漏洩することはなく、容易になるわけでもありません。
セキュリティに関する考慮事項
本仕様に対してセキュリティ上の懸念は提出されていません。