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 许可证发布。