gpt4 book ai didi

java - setValue之后,PDFBox不一致的PDTextField自动调整大小行为

转载 作者:行者123 更新时间:2023-12-02 09:42:41 26 4
gpt4 key购买 nike

我正在使用Apache PDFBox在PDF文档上配置PDTextField,使用以下命令将Lato加载到文档中:

font = PDType0Font.load(
@j_pd_document,
java.io.FileInputStream.new('/path/to/Lato-Regular.ttf')
) # => Lato-Regular

font_name = pd_default_resources.add(font).get_name # => F4


然后,将font_name传递给 default_appearance_stringPDTextField,如下所示:

j_text_field.set_default_appearance("/#{font_name} 0 Tf 0 g") # where font_name is
# passed in from above


现在,当我继续在 setValue上调用 PDTextField时,就会出现此问题。因为我将 font_size中的 defaultAppearanceString设置为 0,所以根据库的 example,文本应自行缩放以适合文本框的给定区域。但是,此“按比例缩放”的行为在某些字段中不一致:它并不总是选择最大的字体大小以适合 PDTextField。可能还有其他配置可能使这种情况发生吗?以下是我注意到此问题发生的PDF。

未填充,已加载字体:
http://www.filedropper.com/0postfontload

用不一致的文本框文本大小填充:
http://www.filedropper.com/file_327

旁注:我正在通过 jruby使用PDFBox,这只是允许Ruby调用Java库的集成层。该库可用的所有java方法;像 thisExampleMethod这样的java方法将对ruby this_example_method进行一对一转换。



更新

为了回应评论,第二个上载文件示例中出现的外观不正确是:


第一页“居民姓名”字段(两个文本字段的文本对于给定的输入字段大小而言太小)
第二页“电话”字段(四个文本字段的文本溢出给定的输入字段大小)

最佳答案

尤其是“居民姓名”字段,“电话”字段和“护理提供者地址”字段的外观很明显。 OP仅提及前两个。

让我们检查这些字段;所有屏幕截图都是使用MS Windows上的Adobe Reader DC制作的:

居民姓名字段

填写的“居民姓名”字段如下所示

screen shot

虽然高度合适,但字形比它们应该的窄。实际上,这种效果已经可以在原始PDF中看到:

screen shot

这种水平压缩是由字段小部件矩形引起的,这些矩形的长宽比与分别匹配的正常外观流边界框不同:


小部件矩形:[ 45.72 601.44 118.924 615.24 ][ 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创建适当的外观,必须在设置新值之前删除旧外观。

电话字段

填写的“电话”字段如下所示

screen shot

同样在原始文件中有类似的显示

screen shot

即使整个单词有足够的空间,也仅显示前两个字母,这是由于以下字段的配置所致:它们被配置为梳形字段,最大长度为2个字符。

要在此处设置的值与PDFBox完全显示且没有这样的间距,您必须删除最大长度(或者至少必须使其不小于值的长度)并取消设置梳理标志。

护理提供者地址字段

填写后,它们看起来像这样:

screen shot

最初它们看起来相似:

screen shot

垂直压缩再次由字段小部件矩形引起,这些字段小部件矩形的长宽比与分别匹配的正常外观流边界框不同:


小部件矩形:[ 278.6 642.928 458.36 657.96 ],即179.76 * 15.032。
外观边界框:[ 0 0 179.76 58.56 ],即179.76 * 58.56。


就像上面的“居民名称”字段一样,必须在设置新值之前删除旧外观,以使PDFBox创建合适的外观。

并发症

实际上,在删除护理人员的旧外观后,填写护理提供者地址字段时,还有一个其他问题:

screen shot

这是由于PDFBox的缺点:这些字段被配置为多行文本字段。虽然用于单行文本字段的PDFBox会根据内容正确计算字体大小,随后又很好地确保文本在垂直方向上非常合适,但是对于多行字段,它的处理非常粗糙,它选择了12的硬编码字体大小,但是微调垂直位置,请参见AppearanceGeneratorHelper方法calculateFontSize(PDFont, PDRectangle)insertGeneratedAppearance(PDAnnotationWidget, PDAppearanceStream, OutputStream)的代码。

由于在您的表单中这些地址字段始终只有一行高,因此一种明显的解决方案是将这些字段设置为单行字段,即清除多行标志。

范例程式码

使用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");
}
}


FillInForm测试 testFill0DropOldAppearanceNoCombNoMaxNoMultiLine

示例代码输出的屏幕截图

现在,“居民名称”字段值不再垂直压缩:

screen shot

“电话和护理提供者地址”字段现在看起来也很合适:

screen shot

关于java - setValue之后,PDFBox不一致的PDTextField自动调整大小行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56938135/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com