PdfBox将字体嵌入现有文档

3

我有一个PDF文件,可以在Okular(或任何PDF查看器)中显示字体属性,类似于:

Name: Helvetica 
Type: Type1
File: /usr/share/fonts/truetype/liberation2/LiberationSans-regular.ttf
Embedded: No

我希望使用PDFBox 2xx嵌入Helvetica字体,而不需要修改文件内容(文字),以便它始终与文件一起使用。 这是否可能? 我尝试了以下方法:

PDDocument document = PDDocument.load(myFile);

InputStream stream = new FileInputStream(new File("/home/user/fonts_temp/Helvetica.ttf"));
PDFont fontToEmbed = PDType0Font.load(document, stream, true);              
PDResources resources = document.getPage(pageNumber).getResources();
resources.add(fontToEmbed);
//or use the font from pdfbox:
resources.add(PDType1Font.HELVETICA);

document.save(somewhere);
document.close();

我也尝试进行调用

COSName fontCosName = resources.add(PDType1Font.HELVETICA);
resources.put(fontCosName, font);

我做错了什么?

编辑:

@TilmanHausherr 谢谢你的提示!但是我还是缺少一些东西。目前我的代码看起来像这样:

PDFont helvetica = PDType0Font.load(document, new FileInputStream(new File("/path/Helvetica.ttf")), false);
...
PDResources resources = page.getResources();
for (COSName fontCosName : resources.getFontNames()){
    if(resources.getFont(fontCosName).getName().equals("Helvetica")) {
        resources.put(fontCosName, helvetica);
    }
}

最终结果显示Helvetica CID TrueType Fully Embedded,但该字体现在在PDF文件中根本不显示。我的意思是使用该字体的地方实际上是空白的,空白页......仍然有些东西不对劲。字体本身是从这里下载的。

你需要知道当前在资源中使用的名称,因此请使用resources.getFontNames()进行检查。另外不要进行子集操作,所以最后一个参数应该是false。 - Tilman Hausherr
2
我看到了...从0开始的代码有问题...尝试使用PDTrueTypeFont而不是PDType0Font。PDTrueTypeFont.load(document, file, WinAnsiEncoding.INSTANCE); - Tilman Hausherr
1
System.out.println(doc.getPage(0).getResources().getFont(COSName.getPDFName("F1")).getSubType()); 让我得到了“Type1”。但是在新文件中,它变成了“Type 0”。问题在于这个字体从1开始编号,而“旧”的truetype类从32开始编号,这也是标准14号字体的做法。您可以使用PDFDebugger查看字体,这样更清楚明了。 - Tilman Hausherr
这有点复杂...但这次它运行得很好。可能对于其他文件不起作用。如果您的任务是将文件转换为PDF/A格式,那么我建议购买商业产品。该解决方案可能仅适用于非嵌入式类型1。关于“如何在代码中区分”,您可以使用getSubType或类本身来实现。 - Tilman Hausherr
我尝试了一下,得到了"Type1",替换后得到了"TrueType"。System.out.println(doc.getPage(0).getResources().getFont(COSName.getPDFName("F1")).getSubType()); - Tilman Hausherr
显示剩余7条评论
1个回答

0

您需要知道当前在资源中使用的名称,因此请使用resources.getFontNames()进行检查。

2. 要替换标准14字体,请使用此字体对象:

PDTrueTypeFont.load(document, file, oldFont.getEncoding() /* or WinAnsiEncoding.INSTANCE which is usually right */ );

这样可以保证使用标准的14号字体相同的编码。(对于Zapf Dingbats和Symbol字体而言,它们的编码与众不同)


1
“这并不确保与标准14字体使用相同的编码。”标准14字体也可以与其他编码一起使用,甚至是自定义编码;只是很少有人这样做。基本上,您需要保留原始编码以确保相同的编码。 - mkl
我将那个答案标记为有效的,但实际上在问题后面的评论中有一个很棒的讨论。 - jeffest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接