尤其是“居民姓名”字段、“电话”字段和“护理提供者地址”字段的出现显得很明显。 OP仅提到前两者。
让我们检查一下这些字段;所有屏幕截图均使用 MS Windows 上的 Adobe Reader DC 制作:
居民姓名字段
填写的居民姓名字段如下所示
虽然高度合适,但字形比应有的窄。其实这个效果在原始PDF中已经可以看到:
这种水平压缩是由字段小部件矩形与相应匹配的正常外观流边界框具有不同的纵横比引起的:
- 小部件矩形:
[ 45.72 601.44 118.924 615.24 ]
and [ 119.282 601.127 192.486 614.927 ]
,即两种情况下的 73.204*13.8。
- 外观边界框:
[ 0 0 147.24 13.8 ]
,即 147.24*13.8。
因此它们具有相同的高度,但外观边界框的宽度大约是小部件矩形的两倍。因此,当外观显示在小部件矩形中时,通常在外观流中绘制的文本会被压缩为其宽度的一半。
不幸的是,当设置字段的值时,PDFBox 按原样重新使用外观流,并且仅更新默认外观的详细信息,即字体名称、字体大小和颜色以及实际文本值,显然假设了外观的其他属性之所以如此,是有原因的。因此,PDFBox 输出也显示了这种水平压缩
为了使 PDFBox 创建正确的外观,需要在设置新值之前删除旧的外观。
电话字段
填写的电话字段如下所示
原始文件中也有类似的显示
尽管有足够的空间容纳整个单词,但仅显示前两个字母,这是由于这些字段的配置所致:它们被配置为最大长度为 2 个字符的梳状字段。
要在此处设置 PDFBox 完全显示且间隔不那么大的值,您必须删除最大长度(或至少必须使其不小于您的值的长度)并取消设置梳标志。
护理提供者地址字段
填充后它们看起来像这样:
最初它们看起来很相似:
这种垂直压缩再次是由具有与各自匹配的正常外观流边界框不同的纵横比的字段小部件矩形引起的:
- 小部件矩形:
[ 278.6 642.928 458.36 657.96 ]
,即 179.76*15.032。
- 外观边界框:
[ 0 0 179.76 58.56 ]
,即 179.76*58.56。
就像上面的“居民姓名”字段的情况一样,有必要在设置新值之前删除旧的外观,以使 PDFBox 创建正确的外观。
一个并发症
实际上,在填写护理提供者地址字段时还有一个额外的问题,删除旧的外观后,它们看起来像这样:
这是由于 PDFBox 的缺点造成的:这些字段被配置为多行文本字段。虽然用于单行文本字段的 PDFBox 根据内容正确计算字体大小,然后精细地确保文本垂直适合得很好,但对于多行字段,它的处理非常粗糙,它选择硬编码字体大小 12,并且不微调垂直位置,参见代码AppearanceGeneratorHelper
方法calculateFontSize(PDFont, PDRectangle)
and insertGeneratedAppearance(PDAnnotationWidget, PDAppearanceStream, OutputStream)
.
由于在您的表单中,这些地址字段无论如何都只有一行高,一个明显的解决方案是使这些字段成为单行字段,即清除多线 flag.
示例代码
使用 Java 可以像这样实现上面解释的解决方案:
final int FLAG_MULTILINE = 1 << 12;
final int FLAG_COMB = 1 << 24;
PDDocument doc = PDDocument.load(originalStream);
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
PDType0Font font = PDType0Font.load(doc, fontStream, false);
String font_name = acroForm.getDefaultResources().add(font).getName();
for (PDField field : acroForm.getFieldTree()) {
if (field instanceof PDTextField) {
PDTextField textField = (PDTextField) field;
textField.getCOSObject().removeItem(COSName.MAX_LEN);
textField.getCOSObject().setFlag(COSName.FF, FLAG_COMB | FLAG_MULTILINE, false);;
textField.setDefaultAppearance(String.format("/%s 0 Tf 0 g", font_name));
textField.getWidgets().forEach(w -> w.getAppearance().setNormalAppearance((PDAppearanceEntry)null));
textField.setValue("Test");
}
}
(填写表格 https://github.com/mkl-public/testarea-pdfbox2/blob/master/src/test/java/mkl/testarea/pdfbox2/form/FillInForm.java#L398 test testFill0DropOldAppearanceNoCombNoMaxNoMultiLine
)
示例代码输出的屏幕截图
Resident Name 字段值现在不再垂直压缩:
电话和护理提供者地址字段现在看起来也合适: