Apache PDFBox表单填充TrueType文本间距问题

时间:2016-04-28 21:47:15

标签: pdf fonts pdfbox

我正在使用Apache PDFBox填写PDF表单。我使用的是名为“Impact”的TrueType字体(不是默认字体),非常标准的票价。在模板中,我有一个名为“Title”的字段,其中分配了Impact字体。我使用下面的代码来获取该模板,并使用包含多个单词的值填充该字段。

问题是当您查看创建的PDF时,单词之间有很大的空格。如果在Acrobat中打开PDF并单击该字段,则文本会更改,并且大间距会消失。以任何方式编辑字段将永久纠正问题,但我生成的表单在事后不会被更改。

我尝试过使用默认字体(本例中为Helvetica)的相同实验,但上述问题不存在。我可以创建一个空白表单并添加一个字段并设置自定义字体并复制问题。

我已经读过类似的问题在2.0.0 PDFBOX-2062中得到了解决,但是它用于更改字体大小,而不是自定义字体。

我正在使用PDFBox版本2.0.1。

public static void main(String[] args) throws IOException {

    String formTemplate = "/BLANK.pdf";
    String outputPDF = "/FillFormField.pdf";

    // load the documents
    PDDocument pdfDocument = PDDocument.load(new File(formTemplate));

    // get the document catalog
    PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();

    // as there might not be an AcroForm entry a null check is necessary
    if (acroForm != null)
    {
        PDTextField field = (PDTextField) acroForm.getField( "Title" );
        field.setValue("Low Mileage Beauty");
    }

    // Save and close the filled out form.
    pdfDocument.save(outputPDF);
    pdfDocument.close();

}

1 个答案:

答案 0 :(得分:2)

问题是由两个因素共同造成的:

  • 撰写文本和
  • 时的PDFBox怪癖
  • 源PDF中不符合要求的字体对象。

PDFBox Quirk

将文本写入内容流时,PDFBox会将每个Unicode代码点转换为名称,并在从反转字体编码生成的地图中查找该名称。

手头的字体编码是 MacRomanEncoding 。在该编码中(以及类似于 WinAnsiEncoding ),有两个名称空间的映射,参见PDF规范ISO 32000-1的附录D2,表中给出的一个:

acroForm.setNeedAppearances(true)

和脚注6中的一个:

  
      
  1. SPACE字符也应在MacRomanEncoding中编码为312,并在240 in   WinAnsiEncoding。此重复代码应表示不间断的空间;它应该是印刷的   与(U + 003A)SPACE相同。
  2.   

反转字体编码只能有一个名为 space 的值,偶然恰好是八进制312(=十进制202)。

由于两个空格字形预计在印刷上相同,因此这个怪癖应该是无害的。但是:

PDF中的不符合字体

PDF中的字体影响定义为普通空格字形的宽度176和不间断空格字形的宽度。因此,它们在印刷上的印象非常不同。

由于PDF中的影响被定义为具有 MacRomanEncoding (此处不感兴趣的微小变化),但这两个字形是必需的(“应”表示要求)印刷相同的,参见上面引用的脚注。

如何处理此

正如@Tilman在评论中已经建议的那样,第一个快速选择

  

设置{{1}}

这将设置一个标志,指示PDF查看器应重新创建外观内容流。但是,这可能不适用于某些预览器。

下一个选项是修复包含不符合字体定义的源PDF。

最终PDFBox可能想要摆脱这个怪癖。虽然它在排版方面应该没有区别,但选择不破坏的变体是诱人的命运。