ByteScope

TrueType 字型檔案格式

TrueType 外框字型,字形是二次貝茲曲線,副檔名 .ttf。

MIME 類型
font/ttf
副檔名
.ttf
分類
字型

Magic number(檔案簽章)

0x0000000000010000····sfnt version 1.0

關於 TrueType 字型格式

TrueType 由 Apple 在 1980 年代末設計、後來被微軟採用,它把每個字形描述成一組二次貝茲曲線,外加一段 hinting bytecode 程式,告訴點陣化引擎在小字級時該怎麼把曲線扣到像素格上。檔案本身是 sfnt 容器:前面一段簡短的目錄用四字元標籤列出字型裡每一張表,每張表都是獨立的資料塊、用絕對檔案位移定址,所以表可以增刪或重排而不動到其他任何東西。位移 0 的版本標籤 00 01 00 00,就是宣告這些外框是 TrueType 而不是 PostScript 的地方。

檔頭結構,一個位元組一個位元組看

位移長度欄位意義
04sfntVersionTrueType 外框是 00 01 00 00。同一個欄位還有另外三個合法值,各代表一種不同的檔案:4F 54 54 4F(OTTO)是帶 PostScript 外框的 OpenType 字型、74 74 63 66(ttcf)是一次裝好幾個字體的集合、74 72 75 65(true)是較舊的 Apple 標籤,有些 Mac 上做的字型到現在還帶著。只認 00 01 00 00 的偵測器會默默漏掉最後那一種。
42numTables目錄後面接著幾筆表記錄。大端序——sfnt 檔案裡每個多位元組數字都是大端序,不管寫它的是哪種處理器——所以這是少數幾種「小端序讀取端一讀就明顯出錯」的格式之一。
62searchRange不大於 numTables 的最大 2 次方,再乘以 16。它只是給表記錄做二分搜尋的提示,而實際出貨的字型把它寫錯的頻率高到(連 Apple 系統字體都在內)解析器乾脆忽略它,改成線性走過所有記錄。
82entrySelector同一個 2 次方取以 2 為底的對數。也是二分搜尋提示的殘留物,同樣可以放心忽略;幾十年來沒有任何點陣化引擎依賴過它。
102rangeShiftnumTables 乘 16 再減掉 searchRange。真實字型把它寫錯的比例高得驚人,這就是「這三個欄位只是為了向後相容留著的贅重」最直白的證據。
12variableTable records每筆 16 個位元組:四字元標籤、檢查碼、絕對檔案位移與長度,全部大端序。記錄依標籤字母排序,所以目錄裡第一筆是「排序最前面」的那個,不是「檔案裡最前面」的那個;表本身可以任意順序擺放,所以位移是唯一可靠的定位方式。
variable54head table透過它的目錄記錄才找得到,不在固定位置。它往內 12 個位元組是 magic number 5F 0F 3C F5,這是「這個檔案真的是 sfnt」最可靠的單一檢查;unitsPerEm 在 +18,而決定 loca 表存的是 16 位元還是 32 位元位移的 indexToLocFormat 在 +50。
variablevariableglyf and loca tablesloca 是一個指進 glyf 的位移陣列,每個字形一筆再加一個結束項,glyf 則裝著輪廓本身。因為 loca 每一筆的寬度是由 head 裡那一個欄位決定的,indexToLocFormat 對不上的字型會畫出一堆垃圾外框,而檔案其他每個部分都驗證得乾乾淨淨。

怎麼跟長得像的格式分開

容易搞混的怎麼分
OpenType 字型兩者都是 sfnt 檔案,就所有實質意義而言也都是 OpenType;差別在外框類型,而位移 0 那 4 個位元組就宣告了答案。00 01 00 00 代表住在 glyf 表裡的二次 TrueType 外框,4F 54 54 4F(OTTO)代表塞在 CFF 表裡的三次 PostScript 外框。副檔名兩邊都不算證據——很多叫 .otf 的檔案裝的是 TrueType 外框。
TrueType Collection (.ttc)集合檔案開頭是 74 74 63 66(ttcf),位移 4 是版本、位移 8 是字型數量,後面接一個位移陣列,每個指向一份普通的表目錄。這樣好幾個字體就能共用同一份字形資料。macOS 多數系統字族都是這樣出貨的,所以把 .ttc 交給一個堅持位移 0 必須是 00 01 00 00 的工具,會被判成損毀——而它其實一點問題都沒有。
WOFF 字型同一個字型,為網頁包了一層。這層外殼把 77 4F 46 46(wOFF)放在位移 0,把原本的 sfntVersion 移到位移 4 當作 flavor 欄位,所以包著 TrueType 的 WOFF 是在位移 4、而不是位移 0 讀到 00 01 00 00。把檔案改名成 .ttf 什麼都沒變;那些表仍然是 zlib 資料流。
WOFF2 字型下一個世代的同樣關係:位移 0 是 77 4F 46 32(wOF2),外框類型一樣在位移 4。因為整個字型主體是單一條 Brotli 資料流,從瀏覽器網路面板存下來、改名成 .ttf 的 WOFF2 沒辦法靠改回名字救回來——得用看得懂這層外殼的工具解壓縮才行。

常見的壞法

  • 下載被截斷。檔案前面的目錄還在,所以 hex 檢視器會顯示合理的表數量與完整的標籤清單,但後面幾筆記錄的位移與長度指到檔案結尾之外。把目錄裡「位移加長度」的最大值和實際檔案大小比一比,一次就抓得到,完全不用解碼。
  • 文字模式傳輸。會轉換換行的 FTP 用戶端或建置步驟,會把 hinting bytecode 與字形資料裡的每個 0D 0A 變成單獨的 0A。目錄本身很少含有那一對位元組,所以它照樣解析得動,字型也打得開、回報正確的字形數量,然後畫出一堆莫名其妙的東西。
  • checkSumAdjustment 過期。子集化與修補工具很常改寫表卻不重算 head 表往內 8 個位元組那個值。點陣化引擎不看它,所以字型在使用時到處都正常,但驗證工具會標記這個檔案,而編輯前原本有效的 DSIG 簽章表現在也失去意義了。
  • 被改名的網頁字型。從瀏覽器存下 .woff2 再叫它 .ttf,是字型裝不起來最常見的單一原因:那些位元組是 Brotli 壓縮過的、開頭是 wOF2,而作業系統會回報檔案損毀而不是格式不對,於是大家跑去找錯的問題。
  • 前面被塞了垃圾。透過會注入錯誤頁的代理伺服器抓字型,或在連線階段過期之後才下載,拿到的檔案位移 0 是一段 HTML doctype,而裡面一個位元組的字型資料都沒有。檔案大小往往看起來很合理,所以在讀到前 4 個位元組之前,什麼都不像有問題。

這個格式現在還在用嗎

TrueType 到現在還是桌面排版的主力。Windows 和 macOS 絕大多數系統字體都是以 TrueType 外框出貨的,通常打包成字型集合;而讓這個格式成名的 hinting bytecode,在低密度螢幕上要把文字算繪得很小的場合仍然重要。在網頁上它幾乎被完全取代:瀏覽器確實接受用 @font-face 直接載入 .ttf,但這麼做很浪費頻寬,因為 WOFF2 送的是一模一樣的那些表,位元組數卻少了大約三分之一。TrueType 仍然是首選的場合,是任何「要安裝而不是下載」的東西——要放進設計軟體、嵌入式裝置、印刷流程或 PDF 的字體——以及任何之後還要再編輯的東西,因為那些表是明擺著存的,每一套字型編輯器都能直接讀寫。OpenType 1.8 加入的可變字型擴充建立在同一套二次外框之上,所以現代的可變字型骨子裡仍然是 TrueType 檔案。

在這個站上打開 TrueType 字型檔

這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。

相關格式

容易和 TrueType 字型搞混的格式,可以比對它們的開頭位元組。

格式開頭位元組副檔名
OpenType 字型4F 54 54 4F.otf
WOFF 字型77 4F 46 46.woff
WOFF2 字型77 4F 46 32.woff2

常見問題

檔案的 magic number 是什麼?

檔案開頭的前幾個位元組,不管檔名寫什麼,它標明的是真正的格式。PNG 一定以 89 50 4E 47 開頭,ZIP 則是 50 4B 03 04。作業系統、瀏覽器和 file 指令讀的都是這幾個位元組,而不是相信副檔名 — 這就是為什麼把檔案改名並不會改變它實際上是什麼。

我要怎麼自己檢查 magic number?

在 macOS 或 Linux 上,xxd -l 16 檔名 會印出前 16 個位元組;在 Windows 上,PowerShell 的 Format-Hex -Path 檔名 -Count 16。或者把檔案丟進本站的檔案類型辨識工具,它會在本機讀取位元組並告訴你是什麼格式,不會上傳任何東西。

為什麼兩種格式的 magic number 會一樣?

因為其中一種是建立在另一種之上。docx、xlsx、pptx、apk、jar 與 epub 骨子裡都是 ZIP 壓縮檔,所以全都以 ZIP 的簽章開頭;要分辨它們得看裡面的項目。Java class 檔和 macOS 的通用二進位檔都以 CA FE BA BE 開頭,靠緊接其後的欄位區分。

有完全沒有 magic number 的檔案嗎?

有。XML、HTML、JSON、SVG、CSV 這類以文字為基礎的格式沒有固定的位元組簽章,所以改用結構來辨識:開頭的 <?xml 宣告、<svg 元素,或是 { 後面接著帶引號的鍵。這種偵測是合理推測而非確定,因此本參考頁會把這些格式標示為結構偵測。

magic number 相符就代表檔案安全嗎?

不代表。它告訴你的是格式,不是內容是否無害 — 一個貨真價實的 PDF 或 docx 仍然可能夾帶惡意內容。辨識真實類型是有用的第一道檢查,尤其在副檔名和位元組不一致的時候,但它不是惡意軟體掃描。

手上有檔案可能是 TrueType 字型?用檔案類型辨識工具查出來 — 它在本機讀取 magic number,不上傳任何東西。或者瀏覽所有格式。