WOFF フォントファイル形式
Web Open Font Format — ウェブ配信向けに TTF/OTF を圧縮して包んだ形式。
- MIME タイプ
- font/woff
- 拡張子
- .woff
- カテゴリ
- フォント
マジックナンバー(ファイル署名)
| 0x00000000 | 774F4646 | wOFF | 'wOFF' tag |
WOFF フォント形式について
WOFF は独立したフォント形式ではなく、コンテナです。完成した TrueType または OpenType フォントを受け取り、各テーブルを個別に zlib で圧縮し、44 バイトのヘッダと新しいテーブルディレクトリを前に付けます。取り出したフォントは、入れたものとバイト単位で等価です。動機は 2 つありました。サイズの削減と、WOFF が「インストールできるデスクトップ用ファイル」ではなく明らかにウェブフォントだと見て取れること。後者は、フォントベンダーに @font-face 向けのライセンスを許可させるのに十分な理由でした。まさにそのライセンス情報を入れるための、圧縮された XML メタデータのブロックも省略可能な形で持てます。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 4 | signature | 77 4F 46 46、小文字の w を含む ASCII の wOFF。この大文字小文字の混在は意図的で、覚えておく価値があります。hex ビューアで大文字小文字を無視して WOFF を検索すると、メタデータブロックや埋め込みの著作権表示の文字列にも引っかかるからです。 |
| 4 | 4 | flavor | 中に入っているフォントの sfntVersion で、TrueType アウトラインなら 00 01 00 00、CFF なら 4F 54 54 4F。.ttf や .otf がオフセット 0 に持っているものを 4 バイト後ろへずらしたもので、ラッパーを外したときに何が出てくるかを教えてくれます。 |
| 8 | 4 | length | WOFF ファイル全体のバイト数。実際のファイル長と一致していなければならないので、途中で切れたダウンロードを、展開もフォントの知識もなしに先頭 12 バイトだけで検出できます。この検査をただで手に入れられる形式はごくわずかです。 |
| 12 | 2 | numTables | テーブルディレクトリのエントリ数。エントリはちょうど 20 バイトずつなので、この数値から圧縮データの開始位置も分かります。 |
| 14 | 2 | reserved | ゼロでなければなりません。ブラウザはウェブフォントをすべてサニタイザに通してからラスタライザへ渡すので、誰も読まないフィールドが非ゼロというだけで、デスクトップのツールが平気で開くファイルがウェブでは門前払いされます。 |
| 16 | 4 | totalSfntSize | 再構成したフォントのサイズで、ディレクトリとテーブル間のパディングも含みます。オフセット 8 の length と並べれば、何も展開せずに圧縮率が分かります。本文用書体なら 2 対 1 を少し上回るくらいが典型です。 |
| 20 | 4 | majorVersion and minorVersion | オフセット 20 と 22 にある 16 ビットの数値 2 つ。バージョンを付けている対象は WOFF 形式ではなくフォントのほうで、たいていは元フォントの head テーブルから写すか、それに合わせてあります。ほとんどの場合 1.0 か 1.1 が入っています。 |
| 24 | 12 | metaOffset, metaLength, metaOrigLength | オフセット 24、28、32 にある 3 つの 32 ビットフィールドで、省略可能な zlib 圧縮の XML メタデータのブロックを記述します。ライセンス、ベンダー、説明を入れることを想定した場所です。無ければ 3 つともゼロで、実際にはそれが普通です。 |
| 36 | 8 | privOffset and privLength | オフセット 36 と 40 にある 2 つ目の省略可能なブロックで、フォントの作者が好きなものを入れてよく、中身は何も定義されていません。これも通常はゼロなので、非ゼロならフォントの出どころを突き止めたいときに覗く価値があります。 |
| 44 | variable | Table directory | ヘッダの直後から、テーブルごとに 20 バイト。タグ、WOFF ファイル内のオフセット、圧縮後の長さ、元の長さ、そして元の非圧縮テーブルのチェックサム。したがって最初のテーブルの圧縮データは 44 + 20 × numTables から始まり、hex ビューアの前で暗算できる程度の計算です。 |
| variable | variable | Compressed table data | テーブルごとに独立した zlib ストリームが、ディレクトリの順に並びます。圧縮しても小さくならないテーブルはそのまま格納してよいことになっていて、ディレクトリ上では圧縮後の長さと元の長さが等しいエントリとして見分けられます。数十バイトしかない小さなテーブルではよくあることです。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| WOFF2 フォント | オフセット 0 が 77 4F 46 46 か 77 4F 46 32 か。そしてそれ以降もすべて違います。WOFF2 のヘッダはオフセット 20 に totalCompressedSize を足したぶん 44 ではなく 48 バイト、ディレクトリのレコードは 20 バイト固定ではなく可変長、本体はテーブルごとの zlib ではなくフォント全体で 1 本の Brotli ストリームです。 |
| TrueType フォント | WOFF の中にあるのは TrueType か OpenType のフォントそのもので、何も改変されていません。ただ、それを識別する 4 バイトがオフセット 0 から 4 へ移っているだけです。オフセット 0 しか見ない読み手は wOFF を見て「不明なフォント」と報告し、オフセット 4 も見る読み手は、展開した後に何が手に入るかまで教えてくれます。 |
| GZIP | どちらも zlib 圧縮のペイロードを運びますし、どちらも汎用の展開器をオフセット 0 に向けても読めません。gzip のファイルは 1F 8B で、先頭近くから始まるストリームを 1 本持ちます。WOFF はディレクトリしか知らないオフセットから始まるストリームを多数持ち、そのどれにもローカルヘッダが付いていません。WOFF を .gz にリネームして gunzip にかければ即座に失敗しますが、その失敗はフォントが無事かどうかについて何も語っていません。 |
よくある壊れ方
- length フィールドがファイルと食い違っている。オフセット 8 の 4 バイトがファイル全体のサイズを宣言しているので、途中切れや余分なパディングは、何も展開しないうちに hex ビューアで証明できます。まず走らせるべき検査であり、これだけで失敗したウェブフォント読み込みのかなりの割合が片付きます。
- フォントの URL の下にエラーページが置かれていた。404 やログインへのリダイレクト、レート制限の通知が .woff として保存されると、テキストエディタでは HTML として開きます。ブラウザのコンソールは「ダウンロードしたフォントをデコードできない」とサニタイザのパースエラーを報告しますが、そのメッセージのどこにも「これはウェブページです」とは書いていないので、やたらと時間を溶かします。
- ブラウザのサニタイザに拒否された。ブラウザはデスクトップのフォントツールよりかなり厳格です。ゼロでない予約フィールド、許容範囲外の値、重なり合う構造。手元のマシンには問題なくインストールできるファイルでも、ウェブではこれらが理由で拒否されます。ローカルでは動くのにページでは動かないフォントは、サーバーの問題ではなくたいていこれです。
- テーブルが 1 つ壊れた。テーブルごとに zlib ストリームが独立しているので、1 バイトの反転はちょうど 1 つを殺し、残りは無傷で残ります。その結果、フォントは読み込まれ、正しいメトリクスを報告し、グリフも描くのに、カーニングだけが、あるいは縦組みのメトリクスだけが失われている、という奇妙な壊れ方をします。展開に失敗したテーブル次第です。
- テキストモード転送。改行を変換するデプロイ手順は圧縮ストリーム内の 0D 0A を書き換えますが、そこはテキストではないので生き延びません。ヘッダとディレクトリは無傷で通るので、inflate が失敗するその瞬間まで、ファイルはちゃんとフォントに見えています。
この形式の現在地
WOFF はおおよそ 2012 年から WOFF2 が追いつくまでの間、ウェブフォントの形式でした。今の役目は配信ではなく互換性です。この 10 年に出たブラウザはどれも WOFF2 を優先しますし、同じ内容で 3 分の 1 ほど小さくなるので、今どきの @font-face は WOFF2 を先に書き、WOFF はフォールバックとしてだけ添えます。しかも最近はそれすら書かなくなりました。フォールバックが要るブラウザは、解析データからほぼ消えたからです。今も WOFF に出くわすのは、何年も前に作られてそのまま再ビルドされていないパッケージ済みソフトウェア、ドキュメントのバンドル、テーマの中、そして Brotli より古いツール群の中です。この形式の本当の功績は技術面ではありませんでした。明らかにインストールできない形で包み、ライセンスがファイルと一緒に旅できるメタデータのブロックを持たせたことで、ベンダーがウェブ利用を認めない理由になっていた論争に決着を付けたのです。それ以降のウェブフォントはすべて、この決着の上で暮らしています。
WOFF フォントファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
WOFF フォントと混同しやすい形式です。先頭バイトを見比べてください。
| 形式 | 先頭バイト | 拡張子 |
|---|---|---|
| WOFF2 フォント | 77 4F 46 32 | .woff2 |
| TrueType フォント | 00 01 00 00 | .ttf |
| OpenType フォント | 4F 54 54 4F | .otf |