Font Awesome のアイコンが箱(☐)として描かれていた。
静的試験(tests/src/test_sugi_lab_cascade.rs)で以下を確定済み:
.fas に Font Awesome の font-family
が当たる — OK::before の content がある —
OKcontent が私用領域の文字へ変換されている —
OK.fas に枠線が当たっていない — OK(☐
は枠線ではない)カスケードは正しく、☐ はフォントから描かれた字形そのもの。
WOFF2 のテーブル変換の判定が仕様と逆だった。
| テーブル | version 0 | version 3 |
|---|---|---|
glyf / loca |
変換あり | 変換なし |
| その他 | 変換なし | 変換あり |
実装は「0 = 変換なし」と決め打ちしていたため:
glyf を「変換なし」と誤判定し、
transformLength を読まずに元長で切り出す →
ストリーム上の位置がそこから全部ずれるglyf として書くhead / cmap
は無事なのでフォントはパースに成功し glyph_index()
も引けるが、輪郭が壊れているので箱になる。
変換された glyf は 7
本のストリームの連結として格納される。 先頭に固定長ヘッダがある。
version u32 (予約。0)
numGlyphs u16
indexFormat u16 (復元後の loca の形式。0=short, 1=long)
nContourStreamSize u32
nPointsStreamSize u32
flagStreamSize u32
glyphStreamSize u32
compositeStreamSize u32
bboxStreamSize u32
instructionStreamSize u32
続いて各ストリームがこの順で並ぶ。
nContourStream から輪郭数 nContours
を読む(i16)。
nContours == 0: 空グリフ(loca の長さ
0)nContours < 0:
複合グリフ。compositeStream から
そのままコピーする(複合グリフのデータは無変換)nContours > 0: 単純グリフ。以下で復元する単純グリフ:
nPointsStream から輪郭ごとの点数を 255UInt16
で読むflagStream から 1 バイトずつフラグを読む
(最上位ビットが「x/y の符号と幅」の三角符号化に使う)glyphStream から座標を三角符号化で読むinstructionStream から命令列を読む(長さは
glyphStream の 255UInt16)glyf グリフ(endPtsOfContours / instructions /
flags / xCoordinates / yCoordinates)を組み立てるbboxStream は先頭に ceil(numGlyphs/8)
バイトのビットマップを持ち、 立っているグリフだけ 4 個の
i16(xMin/yMin/xMax/yMax)が続く。
立っていない単純グリフは座標から計算する。
glyf と
loca は、元のフォントと
バイト単位で一致する必要はないが、
ttf_parser が輪郭を正しく読めることloca は復元した glyf
の実オフセットから作る (indexFormat に従い short / long
を選ぶ)None を返す。壊れたデータを SFNT
に書かないkernel/woff2_glyf.rs(純粋・no_std)
/// 変換された glyf ストリームから (glyf, loca) を復元する。
pub fn reconstruct_glyf(data: &[u8]) -> Option<(Vec<u8>, Vec<u8>, u16)>;
/// 255UInt16(WOFF2 の可変長整数)
pub fn read_255_u16(data: &[u8], pos: &mut usize) -> Option<u16>;