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

2024-04-10

我正在使用 Apache PDFBox 进行配置PDTextField位于我加载的 PDF 文档上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_string为了PDTextField像这样:

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

当我继续调用时,现在出现问题setValue on the PDTextField。因为我设置了font_size in the defaultAppearanceString to 0,根据图书馆的example https://svn.apache.org/repos/asf/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateSimpleForm.java,文本应自行缩放以适合文本框的给定区域。然而,这种“缩放到适合”的行为对于某些字段来说是不一致的:它并不总是选择最大的字体大小来适应PDTextField。是否有任何进一步的配置可以允许这种情况发生?以下是我注意到发生此问题的 PDF。

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

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

边注:我正在使用 PDFBoxjruby它只是一个允许 Ruby 调用 Java 库的集成层。该库的所有 java 方法均可用;像这样的java方法thisExampleMethod将一对一翻译成 rubythis_example_method.


Updates

针对评论,第二个上传文件示例中不正确的外观是:

  • 第一页居民姓名字段(两个文本字段的文本对于给定的输入字段大小来说太小)
  • 第二页电话字段(四个文本字段的文本超出给定输入字段大小)

尤其是“居民姓名”字段、“电话”字段和“护理提供者地址”字段的出现显得很明显。 OP仅提到前两者。

让我们检查一下这些字段;所有屏幕截图均使用 MS Windows 上的 Adob​​e 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 字段值现在不再垂直压缩:

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PDFBox setValue 后的 PDTextField 自动调整大小行为不一致 的相关文章

  • 在Maven中生成Version.java文件

    我有一个使用 Ant 脚本构建的 Java 项目 我正在尝试将项目转换为 Maven 其中一项任务生成一个名为 Version java 的 Java 源文件 其中包含编译时间戳的静态字符串表示形式 如下所示 package com foo
  • Java将字符串解析为double

    如何解析字符串中的这个 Double 00034800 变成 Double 值 最后两位数字实际上是小数点 所以我正在寻找的结果是348 00 是否有这样的格式可以与十进制格式一起使用 Well String s 00034800 doub
  • 同一服务器上的许多应用程序具有相同的 JMX Mbean 类

    我有超过 5 个 Spring Web 应用程序 它们都在使用另一个通用库 这个公共库有它自己的 MBean 由于强制的唯一 objectName 约束 我的应用程序无法部署在同一服务器上 我使用 MBean 的方式是这样的 Managed
  • 在Windows Server 2003下如何在本地系统帐户下运行jvisualvm.exe?

    我在带有 Java 1 6 u 20 的 Windows Server 2003 下将 GlassFish 3 0 1 作为 Windows 服务运行 总体上我很满意 我希望能够在这个 JVM 上使用 VisualVM 并使用无法在 Tom
  • 以相反的顺序打印任何集合中的项目?

    我在 使用 Java 进行数据结构和问题解决 一书中遇到以下问题 编写一个例程 使用 Collections API 以相反的顺序打印任何 Collection 中的项目 不要使用 ListIterator 我不会把它放在这里 因为我想让有
  • getCurrentSession 在网络中休眠

    我正在使用 hibernate 和 jsp servlet 编写一个基于 Web 的应用程序 我读过有关sessionFactory getCurrentSession and sessionFactory openSession方法 我知
  • 为什么 jar 执行的通配符在 docker CMD 中不起作用?

    我有一个Dockerfile与以下CMD启动我的 Spring Boot 应用程序 FROM java 8 jre CMD java jar app file jar 当我尝试从创建的图像启动容器时 我得到 Error Unable to
  • ThreeTen 向后移植与 JSR-310 的比较

    由于某些原因 我们现在无法使用 java 8 我们仍然停留在 java 7 上 不过 我想使用新的JSR 310 date time APIs现在 使用官方向后移植 ThreeTen http www threeten org threet
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • 如何更改 Swagger-ui URL 前缀?

    我正在使用 Springfox Swagger2 和 Spring boot 1 5 9 我可以通过此链接访问 swagger UI http localhost 8090 swagger ui html http localhost 80
  • 为什么解析这个 JSON 会抛出错误?

    我正在尝试解析这个 JSONObject query yahoo count 1 results rate Name USD INR id USDINR Time 12 19pm Date 10 31 2015 Bid 65 405 Ask
  • 如何使用双重调度来分析图形基元的交集?

    我正在分析图形基元 矩形 直线 圆形等 的交互并计算重叠 相对方向 合并等 这被引用为双重调度的一个主要示例 例如维基百科 http en wikipedia org wiki Double dispatch 自适应碰撞算法通常要求 不同的
  • 如何在 IntelliJ IDEA 中运行 akka actor

    来自 Akka 网站文档 然后 这个主要方法将创建所需的基础设施 运行演员 启动给定的主要演员并安排 一旦主要参与者终止 整个应用程序就会关闭 因此 您将能够使用类似于以下的命令运行上面的代码 下列的 java classpath akka
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • Tomcat 6 未从 WEB-INF/lib 加载 jar

    我正在尝试找出我的 tomcat 环境中的配置问题 我们的生产服务器正在运行 tomcat 安装并从共享 NFS 挂载读取战争 然而 当我尝试使用独立的盒子 及其配置 进行同样的战争时 我收到下面发布的错误 有趣的是 如果我将 WEB IN
  • java实现excel价格、收益率函数[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 Apache 允许 Glassfish 和 PHP 在同一服务器中协同工作

    是否可以建立从 Java 到 php 文件的桥梁 我有一个用 Java 编写的应用程序 我需要执行http piwik org http piwik org 这是用 PHP 编写的 在服务器中 我正在运行 PHP 但无法从浏览器访问 php
  • Java 中清除嵌套 Map 的好方法

    public class MyCache AbstractMap
  • 什么是 Java2D 处理程序线程?

    我创建了一个使用 Hibernate 的示例 java 应用程序 当我进行线程转储时 我观察到一个名为 Java2D Disposer 的奇怪线程 有人能告诉我该线程的功能吗 AWT 系统中的某些实体需要最终确定以释放资源 最突出的例子是j
  • GAE 无法部署到 App Engine

    我正在尝试从 Eclipse 发布 Web 应用程序 我在 GAE 上创建了四个项目 可以通过登录我的帐户并查看控制台来查看它们 我已经改变了appengine web xml到项目的应用程序 ID 如果我将其更改为 GAE 上第一个创建的

随机推荐

  • 如何使用函数指针数组?

    我应该如何在 C 中使用函数指针数组 我怎样才能初始化它们 你有一个很好的例子这里 函数指针数组 http www java2s com Code C Function Arrayoffunctionpointer htm 与语法详细 ht
  • Webpack url 和文件加载器不适用于 Angular 2 所需的组件样式

    我正在使用 Angular 2 sass 和 webpack 构建一个应用程序 但我在每个组件内所需的 sass 文件上的 url 上遇到了麻烦 使用 require 它不会将这些文件复制到资产文件夹中 也不会将 url 修改为构建的 cs
  • 如何使用宏引用数据文件?

    我有各种 Stata 数据文件 它们位于不同的文件夹中 我也有一个单do使用这些文件的文件 一次一个 有没有办法使用宏来引用我的特定数据集do file 例如 local datafile C filepath mydata dta 我们的
  • 如何缩小java堆空间? [复制]

    这个问题在这里已经有答案了 我有一个 Java 控制台应用程序 它使用 DOM 处理大型 xml 文件 基本上 它根据从数据库获取的数据创建 xml 文件 现在 正如您猜测的那样 它使用了大量内存 但令我惊讶的是 它与错误代码无关 而是与
  • Jetpack Compose 失败,并显示 NoClassDefFoundError: 无法解析:Landroidx/compose/runtime/MutableStateKt;

    我构建了一个应用程序来使用 Jetpack compose 在 alpha 11 之前一切都工作正常 但由于我尝试将其更新到 alpha 12 甚至 beta 1 该应用程序在运行时失败并出现错误NoClassDefFoundError F
  • 如何设置占位符文本的颜色和字体样式

    我想将颜色设置为占位符 将字体样式更改为粗体 并增加大小 我怎样才能实现这个目标 我应该为占位符提供样式 还是有其他方法可以实现此目的 我想设置颜色并更改字体样式以在所有浏览器中工作 以在下面的结果中选择大小
  • 为什么点击事件总是不触发?

    如果您重新审视这个问题 我已将所有更新移至底部 因此它实际上作为一个问题读起来更好 问题 我在使用处理浏览器事件时遇到了一些奇怪的问题D3 不幸的是 这位于一个相当大的应用程序中 并且因为我完全不知道原因是什么 所以我正在努力寻找一个小的可
  • 修改栈上的返回地址

    我研究了缓冲区溢出漏洞的基础知识 并尝试了解堆栈是如何工作的 为此 我想编写一个简单的程序 将返回地址的地址更改为某个值 有人可以帮助我计算基指针的大小以获得第一个参数的偏移量吗 void foo void char ret char pt
  • C# 帮助:在 C# 中对对象列表进行排序 [重复]

    这个问题在这里已经有答案了 可能的重复 使用预定义的排序值列表对对象进行排序 https stackoverflow com questions 652337 sort objects using predefined list of so
  • 根据求解器的决定执行 get-model 或 unsat-core

    我想知道 SMT LIB 2 0 脚本中是否有可能访问求解器的最后一个可满足性决策 sat unsat 例如 以下代码 set option produce unsat cores true set option produce model
  • 选择树形布局中子节点的所有路径和父节点

    我正在跟进this http bl ocks org d3noob 8375092学习 d3 js 树布局的教程 我正在研究它 单击子节点时 我尝试选择所有祖先节点以及连接它们的路径 我已经更改了默认值click教程中的函数看起来像这样 f
  • jQuery - jQGrid - 展开、折叠网格行上的子网格单击

    Here https stackoverflow com questions 3345401有一个关于当我们单击一行时如何扩展子网格的答案 onSelectRow function rowId jqgrid id expandSubGrid
  • 我应该检查什么:cpu 时间还是 wall time?

    我有两种算法来完成相同的任务 要检查它们的性能 我应该检查什么 cpu 时间还是 wall time 我认为这是CPU时间 对吗 我正在对我的代码进行并行处理 要检查我的并行性能 我应该检查什么 cpu 时间还是 wall time 我想现
  • 使用.Net检测灰度图像

    我正在将文档扫描为 JPG 图像 扫描仪必须将所有页面扫描为彩色或将所有页面扫描为黑白 由于我的许多页面都是彩色的 因此我必须将所有页面扫描为彩色 扫描完成后 我想使用 Net 检查图像并尝试检测哪些图像是黑白的 以便我可以将这些图像转换为
  • 为什么这个 Java 程序会终止,尽管它显然不应该(也没有)终止?

    今天我实验室的一项敏感操作完全出错了 电子显微镜上的执行器超出了其边界 在发生一系列事件后 我损失了 1200 万美元的设备 我已将故障模块中超过 40K 行的范围缩小为 import java util class A static Po
  • GTK+ (2.0) - GtkEntry 上的“点击”信号?

    我正在使用 GTK 2 0 测试一些信号 我正在寻找一种在单击 GtkEntry 时发出信号的方法 if widgets info i action IG INPUT widget gt frame i gtk entry new with
  • 使用 SimpleAudioEngine 按顺序播放声音

    我正在使用 cocos2d 2 构建一个 iOS 应用程序 并使用 SimpleAudioEngine 来播放一些效果 有没有办法在前一个声音完成后按顺序播放多个声音 例如在我的代码中 SimpleAudioEngine sharedEng
  • scala 代码导致 eclipse 中的 playframework-2.0 错误

    我正在尝试todolist tutorial of playframework 2 0在日食 Ieclipsified代码并导入它 以便eclipse helios 可以正确检测到 play api 但是我遇到了问题scala part 我
  • 将自定义对象存储在 NSUserDefaults 的 NSMutableArray 中

    我最近尝试将 iPhone 应用程序的搜索结果存储在 NSUserDefaults 集合中 我还使用它来成功保存用户注册信息 但由于某种原因 尝试存储自定义位置类的 NSMutableArray 总是返回空 我尝试将 NSMutableAr
  • PDFBox setValue 后的 PDTextField 自动调整大小行为不一致

    我正在使用 Apache PDFBox 进行配置PDTextField位于我加载的 PDF 文档上Lato使用以下命令添加到文档中 font PDType0Font load j pd document java io FileInputS