Pro 版本
Font Tools — 深入參考
本頁是 NextPDF Pro Font Tools 的合約層級參考。其介面為一個掃描器 NextPDF\Pro\FontTools\FontDesubsetter,以及兩個不可變值物件 SubsetInfo 與 DesubsetPlan。掃描器讀取原始 PDF 位元組、回報每一個相異的 /BaseFont 項目,並標記符合 ISO 32000-2:2020 §9.9.2 子集命名慣例的項目。規劃會彙總被標記的子集,並估算還原完整字型程式所需的位元組成本。此模組僅進行分析與估算;它絕不改寫已嵌入的字型程式。本頁說明公開 API、可觀察的行為合約,以及失敗模式。
供應與授權
標題為「供應與授權」的區段此功能隨 NextPDF Pro(nextpdf/pro)提供,並以 Pro 層級的授權封套啟用。未持有該授權的部署不會載入此功能的類別。比較版本並取得授權。
沒有任何單功能授權旗標閘控此模組。只要安裝了 nextpdf/pro,Font Tools 類別即可使用。
公開 API 介面
標題為「公開 API 介面」的區段| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
FontDesubsetter | 無 | 針對原始 PDF 位元組的無狀態掃描器 | — | — | final;可安全跨文件重複使用 |
FontDesubsetter::analyzeSubsets() | string $pdfData | 回報每一個相異的 /BaseFont 項目(無論是否為子集),並以 isSubset 標記 | list<SubsetInfo> | 當由寬度推導的子集估計值超過由名稱推導的完整計數估計值時,拋出 InvalidArgumentException | 位元組層級掃描;不會解碼壓縮的物件串流 |
FontDesubsetter::isSubsetFont() | string $baseFontName | 比對「六個大寫字母加 +」的前綴慣例 | bool | — | 錨定於名稱開頭 |
FontDesubsetter::extractSubsetPrefix() | string $baseFontName | 回傳六字母的子集標記 | string | — | 非子集名稱回傳空字串 |
FontDesubsetter::generateDesubsetPlan() | list<SubsetInfo> $subsets | 收集 isSubset 為 true 的項目並加總大小估計值 | DesubsetPlan | 不會拋出 | 非子集項目會被靜默略過 |
SubsetInfo | 建構子:$fontName、$baseFont、$subsetGlyphCount、$fullGlyphCount、$isSubset、$encoding | 單一 /BaseFont 項目的不可變描述 | — | 字符數為負、或子集數超過完整數時拋出 InvalidArgumentException | final readonly;所有屬性皆為 public |
SubsetInfo::subsetPrefix() | 無 | 從 fontName 擷取六字母標記 | string | — | 非子集、或 + 不在第六位時回傳空字串 |
SubsetInfo::coveragePercent() | 無 | 子集佔完整字符集的比例 | 位於 [0.0, 100.0] 的 float | — | 當 fullGlyphCount 為 0 時回傳 0.0 |
DesubsetPlan | 建構子:list<SubsetInfo> $targets、int $estimatedSizeIncrease | 不可變的去子集規劃 | — | — | final readonly;所有屬性皆為 public |
DesubsetPlan::count() | 無 | 目標字型的數量 | int | — | 等於 targets 的長度 |
DesubsetPlan::totalGlyphsNeeded() | 無 | 所有目標缺少字符的總和 | int | — | 每個目標 fullGlyphCount - subsetGlyphCount 的總和 |
進入點簽章
標題為「進入點簽章」的區段public function analyzeSubsets(string $pdfData): array
public function isSubsetFont(string $baseFontName): bool
public function extractSubsetPrefix(string $baseFontName): string
public function generateDesubsetPlan(array $subsets): DesubsetPlanpublic function __construct( public string $fontName, public string $baseFont, public int $subsetGlyphCount, public int $fullGlyphCount, public bool $isSubset, public string $encoding,)
public function subsetPrefix(): string
public function coveragePercent(): floatpublic function __construct( public array $targets, public int $estimatedSizeIncrease,) {}
public function count(): int
public function totalGlyphsNeeded(): int行為合約
標題為「行為合約」的區段掃描與子集偵測
標題為「掃描與子集偵測」的區段analyzeSubsets() 以位元組層級的模式比對,從原始位元組中擷取 /BaseFont 名稱權杖。重複的名稱會合併為單一項目;順序依首次出現為準。每一個相異名稱都會產生一個 SubsetInfo,無論其是否為子集。當名稱以恰好六個大寫 ASCII 字母後接 + 開頭時,即為子集,這是 §9.9.2 的慣例。對子集名稱而言,baseFont 是移除七個字元前綴後的名稱。對一般名稱而言,baseFont 等於 fontName。每一個相異的子集名稱都會回報為其自身的項目,符合 §9.9.2 將子集視為獨立實體的指引。
編碼偵測
標題為「編碼偵測」的區段對每一個字型,掃描器會在 /BaseFont 出現處之後搜尋一個有界的位元組視窗。視窗中的 /Encoding 名稱項目優先。若無,則回報視窗中的 Identity-H 或 Identity-V 子字串。兩者皆無時,該項目回報 Unknown。存放於字典中、或需透過間接參照取得的編碼值會回報 Unknown。
字符計量
標題為「字符計量」的區段兩個字符數皆為估計值。subsetGlyphCount 由字型項目附近可見的寬度陣列推導:CIDFont 的 /W 陣列大致上每個寬度三元組產生一個字符,簡單字型的 /Widths 陣列則每個數值項目產生一個字符。當視窗中兩種陣列皆不可見時,會套用一個固定的小型預設值。當無法為視窗搜尋重新定位 /BaseFont 出現處時,計數為 0。fullGlyphCount 由家族名稱啟發式推導:一張知名 Latin 家族的表、一組 CJK 家族名稱指標,其餘則採通用下限。已嵌入的字型程式絕不會被解析。特定的表、視窗大小與常數屬於實作細節,不會公開,且可能在不同版本間變動。
規劃產生
標題為「規劃產生」的區段generateDesubsetPlan() 會將輸入過濾為 isSubset 為 true 的項目。每個目標會將其缺少字符數乘以固定的「平均每字符位元組數」常數,計入 estimatedSizeIncrease。此規劃是供容量決策使用的推估,而非實測的差異量。執行規劃(改寫字型程式)不在此模組範圍內。
決定性
標題為「決定性」的區段整個介面是其輸入的純函式。相同的位元組產生相同的結果。沒有任何隨機性、網路呼叫或檔案系統存取。
邊界案例與失敗模式
標題為「邊界案例與失敗模式」的區段SubsetInfo建構會拒絕無效狀態:字符數為負、或子集數超過完整數,皆會拋出InvalidArgumentException。analyzeSubsets()在一種特例中可能傳播該例外:某字型的名稱符合已知家族,但其可見的寬度陣列所得的子集估計值大於該家族的完整計數數字。- 偵測作用於位元組表示。序列化於壓縮物件串流內的
/BaseFont項目不可見;請在掃描前先解壓縮這些串流。 /BaseFont鍵與值之間以「單一空格以外」的空白分隔的項目仍會被偵測到,但逐字型的視窗搜尋無法重新定位它們。此類項目回報編碼Unknown與子集字符數0。- 使用
#逸出位元組的 PDF 名稱會以原始逸出形式回報;逸出不會被解碼。 - 重複的
/BaseFont名稱會合併為單一項目。共用同一名稱的兩個相異字型物件,對此掃描器而言無法區分。 generateDesubsetPlan()對非子集輸入絕不失敗;isSubset設為false的項目只會被排除於targets之外。- 所有計數與
estimatedSizeIncrease皆為啟發式值。請勿將其視為實測值;僅供分流與容量規劃使用。 - 此模組不進行任何密碼學運算,因此沒有 FIPS 模式特有的行為。
一致性
標題為「一致性」的區段| 主張 | 標準 | 條款 |
|---|---|---|
子集偵測符合子集命名慣例:在 BaseFont 值前加上六個大寫字母後接 + 的標記。 | ISO 32000-2:2020 | §9.9.2 |
| 每一個相異的子集名稱都會獨立回報,遵循將多個子集視為個別實體的建議。 | ISO 32000-2:2020 | §9.9.2 |
所有條款皆為改寫;NextPDF 不重製規範性文字。這些是能力聲明,而非認證。NextPDF 未持有任何認證,亦不授予任何認證。此模組主張其能偵測命名慣例並具決定性回報;它不主張字符數或大小估計值的準確性。
開發備註
標題為「開發備註」的區段- 以
composer require nextpdf/pro:^3安裝。自nextpdf/pro1.9.0 起提供;目前為nextpdf/pro3.1.0。 FontDesubsetter為無狀態。建構一次即可跨文件與各項工作重複使用。- 當子集涵蓋率重要時,請將解壓縮後的位元組餵給
analyzeSubsets();否則封裝於物件串流中的字型字典會被遺漏。 - 在採取行動前,請依
SubsetInfo::isSubset分支;結果清單為了盤點目的刻意納入非子集字型。 - 在取得完整字型程式之前,請使用
DesubsetPlan::totalGlyphsNeeded()與estimatedSizeIncrease判斷去子集是否值得付出檔案大小的成本。 - 掃描的時間複雜度與輸入長度呈線性,並帶有逐字型的有界視窗搜尋。此模組不儲存任何內容,也不發出任何遙測。
發布邊界
標題為「發布邊界」的區段本頁僅記載外部可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表、runbook 檔名與工單前綴皆不在範圍內。
另請參閱
標題為「另請參閱」的區段- Font Tools(功能) — 安裝、快速上手與規劃工作流程範例。
- Optimizer — 深入參考 — 姊妹的體積縮減介面,含字型相關的最佳化。
- Core 字型模組 — 在 NextPDF Core 建立文件時的字型嵌入與子集化。