自訂字型:FontRegistry 擴充契約
FontRegistryInterface 是行程生命週期層級的契約,用於註冊與查找字型。你可以從檔案路徑、目錄或原始二進位資料註冊字型,接著鎖定此 registry(登錄表),讓正式環境中的 worker 無法再變更它。
composer require nextpdf/core:^3概念總覽
標題為「概念總覽」的區段字型 registry 是 singleton(單例),生命週期比個別的 Document 實例更長。它只保存純 PHP 資料,不持有任何資源 handle 或擴充物件,因此能在長時間執行的 worker 中安全地跨多個請求共用。
此契約支援三種註冊途徑:
- 從檔案註冊。
register()會剖析.ttf、.otf、.ttc或.pfb檔案,並回傳剖析後的中繼資料。若是 TrueType Collection,請傳入子字型 Index(索引)。 - 從目錄註冊。
addFontDirectory()會新增一個搜尋路徑;引擎依名稱 resolve(解析)字型家族時會掃描這個路徑。 - 從二進位資料註冊。
registerFromBinary()會剖析原始的 TrueType 或 OpenType 位元組。這也是@font-face橋接器處理字型時所走的途徑;這些字型是從data:URI 或遠端來源取得的。
若要分攤首次請求的延遲,請在 worker 啟動時呼叫 warmup(),預先剖析一批字型,接著呼叫 lock()。在 lock() 之後,每一個變更方法都會擲出 LogicException。這些方法是 register()、addFontDirectory()、warmup()、registerBase14() 與 registerFromBinary()。查找方法仍可使用:get()、has()、all() 與 getSearchDirectories()。這個鎖定機制是正式環境的安全防護,可確保沒有任何請求能更動共用的字型集合。
多數情況下,你不需要自行實作 FontRegistryInterface。引擎已提供實作,直接呼叫即可。只有在需要自訂字型解析策略時,才會自行實作它,例如以內容定址儲存作為後端的策略。無論哪一種情況,契約都是邊界。
API 介面
標題為「API 介面」的區段NextPDF\Contracts\FontRegistryInterface(穩定,自 1.7.0 起):
| 方法 | 回傳 | 用途 |
|---|---|---|
register(string $fontFile, string $alias, int $fontIndex) | FontInfo | 剖析並註冊一個字型檔案。若 registry 已鎖定或檔案無法剖析,則會擲出例外。 |
registerFromBinary(string $fontData, string $alias) | FontInfo | 從原始的 TrueType 或 OpenType 位元組註冊一個字型。 |
registerBase14(string $key, FontInfo $font) | void | 註冊一個預先建構的 Base 14 標準字型。 |
addFontDirectory(string $directory) | void | 新增一個字型搜尋目錄。 |
warmup(array $fontFiles) | void | 在 worker 啟動時預先剖析一批字型。 |
lock() | void | 凍結 registry,使其無法再被變更。 |
isLocked() | bool | 回報 registry 是否已鎖定。 |
get(string $family, string $style) | FontInfo | null | 依字型家族與樣式查找字型。 |
has(string $key) | bool | 檢查某個註冊鍵是否存在。 |
all() | array<string, FontInfo> | 回傳所有已註冊的字型。 |
getSearchDirectories() | list<string> | 依序回傳搜尋目錄。 |
memoryUsage() | MemoryReport | 回報 registry 目前的記憶體使用量。 |
程式碼範例——快速上手
標題為「程式碼範例——快速上手」的區段<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;
/** @var FontRegistryInterface $fonts */$info = $fonts->register('/srv/fonts/Inter-Regular.ttf', 'Inter');
if (!$fonts->has('inter')) { throw new RuntimeException('Inter failed to register');}程式碼範例——正式環境
標題為「程式碼範例——正式環境」的區段這段 worker 啟動常式會預熱一組字型、鎖定 registry,並觀測每次載入以利授權追蹤。它用到的每個型別都是公開型別。
<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Event\Content\FontLoadedEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;use Psr\Log\LoggerInterface;
final class FontWarmup{ /** @param list<string> $fontFiles */ public function __construct( private readonly FontRegistryInterface $fonts, private readonly LoggerInterface $logger, private readonly array $fontFiles, ) {}
public function boot(): EventDispatcher { $listeners = new ListenerProvider(); $listeners->addListener( FontLoadedEvent::class, function (FontLoadedEvent $event): void { $this->logger->info('font.loaded', [ 'family' => $event->family, 'style' => $event->style, 'type' => $event->fontType->name, ]); }, );
if (!$this->fonts->isLocked()) { $this->fonts->warmup($this->fontFiles); $this->fonts->lock(); }
return new EventDispatcher($listeners); }}邊界情況與陷阱
標題為「邊界情況與陷阱」的區段- 已鎖定的 registry。 在
lock()之後的任何變更都會擲出LogicException。在重複使用的 worker 中,進行條件式預熱前一律先檢查isLocked()。 - 二進位註冊不會依鍵快取。
registerFromBinary()會寫入一個暫存檔再加以剖析。請把回傳的FontInfo當成 handle 看待。 - TTC 索引。 若是 TrueType Collection,
register()的第三個引數用來選擇子字型。預設值0會選擇第一個字型面。 - 字型家族解析。 對於未知的字型家族與樣式組合,
get()會回傳null。切勿假設結果一定不是 null。
warmup() 會將剖析成本從首次請求移到啟動階段。registry 的方法都只在純 PHP 資料上運作,查找是常數時間的 map 讀取。請呼叫 memoryUsage(),依你的記憶體預算評估 worker 常駐字型集合的大小。
安全性注意事項
標題為「安全性注意事項」的區段已註冊的字型會成為可內嵌的 PDF 內容。註冊前必須驗證字型的 provenance(來源資訊)。在未完成大小與格式檢查前,切勿註冊受攻擊者控制的二進位資料。FontLoadedEvent hook 是強制執行字型授權合規,並記錄文件內嵌了哪些字型面的官方支援位置。
符合性
標題為「符合性」的區段此處不適用任何簽章或封存方面的規範性宣告。字型內嵌與子集化符合 PDF 2.0 字型模型;此符合性由內部子集化器負責,而非由此契約負責。
商業情境
標題為「商業情境」的區段NextPDF Enterprise 在同一份 FontRegistryInterface 之上,加上字型授權證明與經稽核的子集化政策。因為契約就是邊界,所以你的註冊程式碼在各版本之間都不需更動。
另請參閱
標題為「另請參閱」的區段相關契約與模組
標題為「相關契約與模組」的區段- 字型模組參考——registry 的實作、剖析與子集化內部細節。
- 排版契約參考——
FontRegistryInterface列入目錄的位置。 - 動作觸發器與事件監聽器——
FontLoadedEvent與其分派器。 - 自訂版面配置與文字攔截——同層級的繪製階段策略契約。
- SPI 穩定性規則——
FontRegistryInterface背後的介面承諾。
詞彙表定義了 font registry、image registry 與 event listener;各項的標準定義請參閱已發布詞彙表。