You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何将.ttf字体嵌入现有PDF(支持Pdfbox/OpenPDF)

Java中嵌入TTF字体到现有PDF的实现方案

一、使用Apache Pdfbox实现

核心操作逻辑

  • 从输入流加载目标PDF,全程内存操作
  • 加载TTF字体并标记为需嵌入
  • 将字体注入PDF全局资源字典,确保出现在字体列表中

代码示例

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class PdfboxFontEmbedder {
    public byte[] embedFontToPdf(byte[] sourcePdfBytes, InputStream ttfFontStream) throws Exception {
        // 加载现有PDF到内存
        try (PDDocument document = PDDocument.load(new ByteArrayInputStream(sourcePdfBytes))) {
            // 加载TTF字体并设置嵌入属性
            PDTrueTypeFont embeddedFont = PDTrueTypeFont.load(document, ttfFontStream, true);
            embeddedFont.setEmbedded(true);
            embeddedFont.setSubset(false); // 嵌入完整字体,保证字体列表可见

            // 将字体添加到PDF全局资源
            PDResources resources = document.getDocumentCatalog().getResources();
            if (resources == null) {
                resources = new PDResources();
                document.getDocumentCatalog().setResources(resources);
            }
            // 自定义字体名称,避免和现有字体冲突
            resources.put("CustomEmbeddedFont", embeddedFont);

            // 输出为字节数组,无需保存到硬盘
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                document.save(baos);
                return baos.toByteArray();
            }
        }
    }
}

注意事项

  • 确认TTF字体允许嵌入,部分商用字体存在版权限制
  • setSubset(false)会嵌入完整字体,若需减小文件体积可设为true,不影响字体列表显示
  • 输入流由try-with-resources自动管理关闭,无需手动处理

二、使用OpenPDF实现

核心操作逻辑

  • 用PdfReader读取源PDF,通过ByteArrayOutputStream输出修改后的内容
  • 加载TTF字体时指定嵌入参数
  • 将字体添加到PDF的AcroForm字体字典,无AcroForm则创建资源字典

代码示例

import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

public class OpenPdfFontEmbedder {
    public byte[] embedFontToPdf(byte[] sourcePdfBytes, InputStream ttfFontStream) throws Exception {
        // 加载源PDF到内存
        PdfReader reader = new PdfReader(new ByteArrayInputStream(sourcePdfBytes));
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            // 初始化PdfStamper用于修改PDF
            PdfStamper stamper = new PdfStamper(reader, baos);
            
            // 加载TTF字体并设置嵌入属性
            BaseFont baseFont = BaseFont.createFont(
                "CustomEmbeddedFont", 
                BaseFont.IDENTITY_H, 
                BaseFont.EMBEDDED, 
                true, 
                ttfFontStream.readAllBytes(), 
                null
            );
            
            // 将字体添加到PDF资源,确保字体列表可见
            stamper.getAcroFields().addSubstitutionFont(baseFont);
            // 若PDF无表单字段,通过设置字体到内容流触发资源字典创建
            if (stamper.getAcroFields().getFields().isEmpty()) {
                stamper.getWriter().getDirectContent().setFontAndSize(baseFont, 12);
            }

            // 完成修改并输出字节数组
            stamper.close();
            reader.close();
            return baos.toByteArray();
        }
    }
}

注意事项

  • OpenPDF的BaseFont.createFont需传入字体字节数组,示例中直接读取输入流内容
  • 添加替代字体是确保字体被嵌入到文档资源的关键步骤
  • 无表单字段的PDF需手动触发资源字典创建,否则字体无法被注册

内容的提问来源于stack exchange,提问作者Schlomo Dumbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:33:25