过去很多人会把 PDF 里的 emoji 当成装饰问题。现在不是了。
在面向客户的文档里,emoji 经常承载真实信息:
- 收据里用 ✅ 表示已支付,用 🎁 表示奖励,用 ⭐ 表示评分,用 🔥 表示限时优惠。
- 物流通知里用 📦、🚚、🙏 快速表达打包、发货和感谢。
- 客服记录里会包含 WhatsApp、LINE、KakaoTalk 或微信消息,emoji 可能就是证据的一部分。
- 证书、徽章、优惠券、门票或会员卡里,🏆、🎓、🎉、💯 经常直接参与视觉表达。
如果这些 emoji 消失、变成方框,或者让 PDF 额外膨胀几百 KB,这份文档就不再忠实于原始内容。对高频生成系统来说,这不仅是视觉问题,也会变成产品、存储、传输,甚至合规归档问题。
难点在于,“支持 emoji”不是一个简单的勾选项。PDF 生成器可以依赖浏览器或操作系统字体,可以要求调用方配置 emoji 字体,也可以把 emoji 转成图片或矢量图形,还可以尝试嵌入彩色字体数据。这些方案都可能可用,但代价完全不同。
关键矛盾:支持能力和文件体积
彩色 emoji 难处理,是因为它们不是普通黑白字形。PDF Association 对这个问题有过清楚解释:OpenType 彩色字体存在多种互不相同的格式,但这些彩色字体格式并不能像传统轮廓字体那样直接、简单地成为 PDF 的原生内容。
因此,生成器必须选择一种表示方式:
- 使用浏览器或操作系统提供的彩色字体;
- 嵌入或子集化彩色 emoji 字体数据;
- 把 emoji 转成图片或矢量图形;
- 或者退回到单色字形、缺字方框或纯文本。
一两个 emoji 时差异可能不明显。但如果是一张 emoji 密集的收据、优惠券、聊天导出或客服归档,差异就会很快放大。
一个小型测试:50 个常见 emoji
我们在 2026 年 5 月 20 日做了一个本地 smoke test,使用同一份单页 A4 样本:
- 一版只包含普通文本;
- 一版在正文中包含 50 个常见 emoji;
- Chrome 148 headless print-to-PDF;
- gPdf 本地生成,使用同一组 50 个常见 emoji。
这不是所有文档、所有版本、所有环境的通用 benchmark。它只是用一个可复现的小样本,观察当文档里出现大量不同彩色 emoji 时,文件体积会怎样变化。
| 生成器 | 普通 PDF | 同页含 50 个 emoji | 增量 | 倍数 |
|---|---|---|---|---|
| Chrome 148 print-to-PDF | 31,250 bytes | 435,630 bytes | +404,380 bytes | 13.94x |
| gPdf local generation | 8,766 bytes | 43,466 bytes | +34,700 bytes | 4.96x |
Chrome 输出中嵌入了 AppleColorEmoji Type 3 子集。这是一种有效的可见性方案,但在这个样本里,文件体积增长非常明显。
gPdf 输出没有嵌入完整彩色 emoji 字体。含 emoji 的版本当然会比纯文本版本更大,因为彩色图形必须有地方存放。差别在于,输出主要随文档实际使用的 emoji 图形增长,而不是走一条宽泛的浏览器或操作系统字体路径。
采购时真正该问的不是“一个笑脸能不能在我电脑上显示”,而是:
当生产文档里有几十个不同 emoji,并且由真实服务端环境生成 PDF 时,会发生什么?
其他 PDF 生成器如何处理 emoji
诚实的对比不是“别人都不支持”。不少成熟 PDF 工具已经支持彩色 emoji。关键问题是:它们如何支持,以及这对部署、确定性和输出体积意味着什么。
Puppeteer、Chrome 和 Chromium 类 API
Puppeteer 使用 Chrome 的 PDF 输出路径。官方文档把 page.pdf() 描述为使用 print CSS media type 生成页面 PDF,并说明默认会等待字体加载。你的源内容如果本来就是网页,这很有用。
对 emoji 密集的结构化文档来说,代价是输出依赖浏览器和字体环境。我们的本地样本里,Chrome 正确显示了 emoji,但文件从 31 KB 增长到 436 KB。
这并不说明 Puppeteer 错了。它首先是浏览器自动化工具。需要捕获现有网页时,它很合适。需要生成紧凑、可重复的收据、标签、票据、对账单或客服记录时,浏览器路径可能偏重。
DocRaptor 和 Prince
DocRaptor 包装的是 Prince,而 Prince 是很强的 HTML-to-PDF 引擎。输入确实是 HTML/CSS,并且需要复杂分页媒体能力时,它特别合适。
DocRaptor 自己的 Pipeline 9 / Prince 14 公告明确列出了彩色 emoji 支持。Prince 14 release notes 也列出了 SVG-in-OpenType、CBLC/CBDT 彩色 emoji 字体、Apple sbix 和 emoji tag sequence 支持。所以正确说法不是“DocRaptor 不能渲染 emoji”。
更准确的边界是:DocRaptor/Prince 是高质量 HTML-to-PDF 路径;gPdf 是结构化 JSON-to-PDF 路径。当输入本来已经是业务数据,并且文档 emoji 较多时,gPdf 避免把问题推入通用 HTML/CSS 渲染器。
PDFreactor
PDFreactor 也支持彩色 emoji。它的手册说明默认使用彩色 emoji,并支持 CBDT、SBIX、OpenType-SVG 等彩色字体格式。
同一份手册也说明了彩色字体限制:使用 OpenType-SVG 时 PDF 体积会更大,并且该路径不支持选择或复制。这正是团队在把“emoji 支持”当成 yes/no 功能前应该理解的取舍。
iText 和 pdfHTML
iText 可以在文档拥有能绘制这些字符的字体程序时生成 emoji。官方 pdfHTML emoji 指南展示的模式是:把支持 emoji 的字体加入 FontProvider,再执行转换。
这对希望掌控 SDK 细节的团队很强。但也意味着字体配置、测试、部署和长期维护要由应用团队负责。
为什么覆盖范围重要
很容易测错东西。能显示 😂,不等于能处理真实用户发来的 emoji。
现实里的 emoji 包括:
- variation selector,也就是文本呈现和 emoji 呈现的区别;
- 肤色修饰符;
- zero-width-joiner 组合;
- 国旗和 tag sequence;
- emoji 与中文、阿拉伯文、拉丁文等多脚本混排;
- 老旧 PDF 查看器和企业文档流水线。
对客户文档来说,一致性就是产品体验。客服记录不应该因为服务器不同而显示不同 emoji。收据不应该在 macOS 上显示状态符号、在 Linux 容器里变成方框。平台也不应该要求每个商户安装同一套 emoji 字体栈。
gPdf 的产品立场很简单:生成 PDF 时,彩色 emoji 应该稳定工作;客户不应该被要求安装 emoji 字体、调试浏览器运行时,或者默认接受很大的输出文件。
哪些文档最需要 emoji
emoji 密集 PDF 并不只出现在消费营销场景,也经常出现在运营系统里。
| 文档类型 | 为什么 emoji 重要 |
|---|---|
| 收据和券码 | 支付状态、奖励、评分和促销提示是客户体验的一部分。 |
| 物流和预约确认 | 已确认、已打包、已发货、已送达等状态更容易扫读。 |
| 客服记录 | 聊天导出如果移除 emoji,会丢失语气和证据细节。 |
| 社群和社交归档 | emoji 是对话内容,不是装饰。 |
| 证书和成就徽章 | 奖杯、毕业帽和庆祝符号常常是设计的一部分。 |
| 多语言客户 PDF | emoji 可以跨语言快速表达状态。 |
这就是文件体积重要的原因。一次多 400 KB 听起来不大。每月 100,000 张收据时,它会变成存储、带宽、邮件送达率、移动端下载时间和归档成本。聊天导出规模更大时,问题会更明显。
gPdf 适合的工作负载
gPdf 不是完整浏览器,也不是所有 HTML-to-PDF 引擎的替代品。如果源文档是任意网页、复杂编辑排版,或者带 JavaScript 图表的实时 dashboard,应该使用浏览器或成熟 HTML-to-PDF 引擎。
gPdf 适合另一类场景:
- 输入本来就是结构化数据;
- 输出需要可预测;
- 系统需要高频生成;
- PDF 必须保持紧凑;
- 同一 payload 在不同环境里应稳定生成;
- emoji、CJK、条码、PDF/A 和 metadata 都是产品需求,而不是事后补丁。
在这种工作负载下,emoji 支持应该足够“无感”。你应该能把状态、情绪和客户语言线索放进文档,而不是把 PDF 生成变成字体安装项目。
评估 PDF 供应商时该问什么
评估 emoji 支持时,不要只看截图:
- 能否生成包含 50 个不同常见 emoji 的 PDF?
- 有无 emoji 时文件体积分别是多少?
- 输出是否依赖操作系统字体?
- 是否要求客户安装或注册 emoji 字体?
- ZWJ 组合、国旗和 variation selector 会怎样?
- 运行时升级后输出是否稳定?
- emoji 行为是否有文档说明,还是只是宿主环境的副作用?
这些答案能说明 emoji 支持到底是产品能力,还是运行时碰巧带来的结果。
Sources
- PDF Association: OpenType color fonts in PDF
- Puppeteer: Page.pdf()
- Puppeteer: PDF generation guide
- DocRaptor: Pipeline 9 with color emoji and Prince 14
- Prince 14 release notes
- PDFreactor manual: color fonts and emojis
- iText pdfHTML: using emojis
- Twemoji: license and attribution
说明:gPdf 使用 Twemoji 图形。Twemoji 图形版权归 2019 Twitter, Inc 及其他贡献者所有,并以 CC BY 4.0 授权。