Skip to content

字型

TCPDF-Next 支援 TrueType、OpenType 及 Type1 字型,並提供自動子集化、CJK 渲染與雙向文字排版功能。字型可透過 Document 上的 addFont() 方法載入,或直接使用 FontManager 進行管理。

支援的字型格式

格式副檔名說明
TrueType.ttf完整的字形輪廓支援,最常見的字型格式
OpenType.otf同時支援 CFF 與 TrueType 輪廓變體
Type1.pfb + .afm傳統 PostScript 字型,需搭配度量檔案

核心字型

PDF 規範定義了 14 種標準字型(即「Base 14」),所有合規的 PDF 閱讀器都必須支援。使用這些字型無需嵌入,能有效縮小檔案大小。

字型家族樣式
HelveticaRegular、Bold、Italic、Bold Italic
TimesRegular、Bold、Italic、Bold Italic
CourierRegular、Bold、Italic、Bold Italic
SymbolRegular
ZapfDingbatsRegular
php
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 字型檔案,隨後即可直接使用。

php
$pdf = Document::create()
    ->addFont('NotoSansTC', '', '/path/to/NotoSansTC-Regular.ttf')
    ->addPage()
    ->setFont('NotoSansTC', '', 12)
    ->cell(0, 10, '繁體中文文字', newLine: true);

多樣式字型家族

將同一字型家族的各樣式變體以相同的家族名稱註冊。當你呼叫 setFont() 時帶入樣式字串,TCPDF-Next 會自動選擇對應的字型檔案。

php
$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 序列化過程中自動處理子集化。

php
// 字型子集化是自動進行的 — 只有使用到的字形會被嵌入
$pdf = Document::create()
    ->addPage()
    ->setFont('DejaVuSans', '', 12)
    ->cell(0, 10, 'Only these glyphs are embedded');
// 結果:更小的 PDF 檔案大小

為什麼子集化很重要

一套完整的 CJK 字型可能超過 15 MB。如果你的文件只用到少數幾個字元,子集化可以將嵌入的字型資料縮減至幾 KB。對於網頁傳輸和電子郵件附件來說,這是至關重要的最佳化。

停用子集化

在少數情況下(例如可編輯的表單欄位,使用者可能輸入任意字元),你可能需要完整的字型。在註冊字型時將 subset 參數設為 false 即可:

php
$pdf->addFont('NotoSans', '', '/fonts/NotoSans-Regular.ttf', subset: false);

CJK 支援

中文、日文及韓文文字需要具備大量字形集合的字型。TCPDF-Next 透過 CjkValidator 驗證 CJK 內容,並確保 PDF 輸出中的編碼正確無誤。

php
$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 混合的內容。

php
$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 文字,也使搜尋引擎能正確索引文件內容。它會在序列化過程中自動產生。

字型度量

FontInfoFontMetrics 類別公開了詳細的排版度量資料。

php
$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)以及逐字形的前進寬度 — 全部取自字型內部的表格。

完整範例

php
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');

以 LGPL-3.0-or-later 授權釋出。