字型
TCPDF-Next 支援 TrueType、OpenType 及 Type1 字型,並提供自動子集化、CJK 渲染與雙向文字排版功能。字型可透過 Document 上的 addFont() 方法載入,或直接使用 FontManager 進行管理。
支援的字型格式
| 格式 | 副檔名 | 說明 |
|---|---|---|
| TrueType | .ttf | 完整的字形輪廓支援,最常見的字型格式 |
| OpenType | .otf | 同時支援 CFF 與 TrueType 輪廓變體 |
| Type1 | .pfb + .afm | 傳統 PostScript 字型,需搭配度量檔案 |
核心字型
PDF 規範定義了 14 種標準字型(即「Base 14」),所有合規的 PDF 閱讀器都必須支援。使用這些字型無需嵌入,能有效縮小檔案大小。
| 字型家族 | 樣式 |
|---|---|
| Helvetica | Regular、Bold、Italic、Bold Italic |
| Times | Regular、Bold、Italic、Bold Italic |
| Courier | Regular、Bold、Italic、Bold Italic |
| Symbol | Regular |
| ZapfDingbats | Regular |
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, 'Helvetica — PDF 的主力字型', newLine: true)
->setFont('Times', 'I', 12)
->cell(0, 10, 'Times Italic — 經典襯線字型', newLine: true)
->setFont('Courier', 'B', 12)
->cell(0, 10, 'Courier Bold — 等寬字型', newLine: true);自訂字型載入
addFont()
註冊一個 TrueType 或 OpenType 字型檔案,隨後即可直接使用。
$pdf = Document::create()
->addFont('NotoSansTC', '', '/path/to/NotoSansTC-Regular.ttf')
->addPage()
->setFont('NotoSansTC', '', 12)
->cell(0, 10, '繁體中文文字', newLine: true);多樣式字型家族
將同一字型家族的各樣式變體以相同的家族名稱註冊。當你呼叫 setFont() 時帶入樣式字串,TCPDF-Next 會自動選擇對應的字型檔案。
$pdf = Document::create()
->addFont('Roboto', '', '/fonts/Roboto-Regular.ttf')
->addFont('Roboto', 'B', '/fonts/Roboto-Bold.ttf')
->addFont('Roboto', 'I', '/fonts/Roboto-Italic.ttf')
->addFont('Roboto', 'BI', '/fonts/Roboto-BoldItalic.ttf')
->addPage()
->setFont('Roboto', '', 11)
->cell(0, 10, 'Regular weight', newLine: true)
->setFont('Roboto', 'B', 11)
->cell(0, 10, 'Bold weight', newLine: true)
->setFont('Roboto', 'I', 11)
->cell(0, 10, 'Italic style', newLine: true)
->setFont('Roboto', 'BI', 11)
->cell(0, 10, 'Bold Italic', newLine: true);字型子集化
預設情況下,TCPDF-Next 只會嵌入文件中實際出現的字形。FontSubsetter 會在 PDF 序列化過程中自動處理子集化。
// 字型子集化是自動進行的 — 只有使用到的字形會被嵌入
$pdf = Document::create()
->addPage()
->setFont('DejaVuSans', '', 12)
->cell(0, 10, 'Only these glyphs are embedded');
// 結果:更小的 PDF 檔案大小為什麼子集化很重要
一套完整的 CJK 字型可能超過 15 MB。如果你的文件只用到少數幾個字元,子集化可以將嵌入的字型資料縮減至幾 KB。對於網頁傳輸和電子郵件附件來說,這是至關重要的最佳化。
停用子集化
在少數情況下(例如可編輯的表單欄位,使用者可能輸入任意字元),你可能需要完整的字型。在註冊字型時將 subset 參數設為 false 即可:
$pdf->addFont('NotoSans', '', '/fonts/NotoSans-Regular.ttf', subset: false);CJK 支援
中文、日文及韓文文字需要具備大量字形集合的字型。TCPDF-Next 透過 CjkValidator 驗證 CJK 內容,並確保 PDF 輸出中的編碼正確無誤。
$pdf = Document::create()
->addFont('NotoSansCJK', '', '/fonts/NotoSansCJKtc-Regular.otf')
->addPage()
->setFont('NotoSansCJK', '', 12)
->cell(0, 10, '中文:你好世界', newLine: true)
->cell(0, 10, '日本語:こんにちは世界', newLine: true)
->cell(0, 10, '한국어:안녕하세요 세계', newLine: true);CJK 字型一律會進行子集化(除非明確停用),因為檔案大小的節省非常可觀。
雙向文字 (BiDi)
BiDiResolver 實作了 Unicode 雙向演算法,能正確渲染阿拉伯文、希伯來文等從右到左書寫的文字,也支援 LTR/RTL 混合的內容。
$pdf = Document::create()
->addFont('NotoSansArabic', '', '/fonts/NotoSansArabic-Regular.ttf')
->addPage()
->setFont('NotoSansArabic', '', 14)
->cell(0, 10, 'مرحبا بالعالم', newLine: true) // 阿拉伯文
->write(10, 'Mixed: Hello مرحبا World'); // LTR + RTL 混合當文字中包含 RTL 字元時,BiDi 重排會自動套用,無需任何手動設定。
ToUnicode CMap
TCPDF-Next 會為每個嵌入的字型產生 ToUnicode CMap。這個映射表讓 PDF 閱讀器能在使用者複製貼上時擷取正確的 Unicode 文字,也使搜尋引擎能正確索引文件內容。它會在序列化過程中自動產生。
字型度量
FontInfo 與 FontMetrics 類別公開了詳細的排版度量資料。
$pdf->setFont('Helvetica', '', 12);
// 量測目前字型下特定字串的寬度
$width = $pdf->getStringWidth('Hello, World!');
// 利用度量資料進行精準排版
$cellWidth = $pdf->getStringWidth('Total:') + 4; // 加上 4mm 的內距
$pdf->cell($cellWidth, 8, 'Total:');度量資料涵蓋上升線(ascender)、下降線(descender)、行距(line gap)、大寫高度(cap height)、x 字高(x-height)以及逐字形的前進寬度 — 全部取自字型內部的表格。
完整範例
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
// 註冊字型
->addFont('Roboto', '', '/fonts/Roboto-Regular.ttf')
->addFont('Roboto', 'B', '/fonts/Roboto-Bold.ttf')
->addFont('NotoSansTC', '', '/fonts/NotoSansTC-Regular.ttf')
->addPage()
// 英文標題
->setFont('Roboto', 'B', 18)
->cell(0, 12, 'Multilingual Invoice', newLine: true)
->ln(3)
// 英文內文
->setFont('Roboto', '', 11)
->cell(0, 8, 'Customer: Acme Corporation', newLine: true)
->cell(0, 8, 'Date: 2026-02-16', newLine: true)
->ln(5)
// 中文區段
->setFont('NotoSansTC', '', 11)
->cell(0, 8, '客戶名稱:台灣科技有限公司', newLine: true)
->cell(0, 8, '發票日期:2026年2月16日', newLine: true)
->save('multilingual-invoice.pdf');