您可以稍微更改坐标系,但最终很可能事情不会变得更优雅。
开始...
首先让我们澄清一些误解:
你假设
在 PDFBox 中,PDRectangle 对象的默认原点 (0,0) 似乎是页面的左下角。
并非所有情况都如此,只是经常如此。
包含显示页面区域(在纸上或屏幕上)的区域通常由相关页面的 CropBox 条目定义:
CropBox 矩形 (可选;可继承) 以默认用户空间单位表示的矩形,它应定义默认用户空间的可见区域。
当页面显示或打印时,其内容将被剪裁(裁剪)到这个矩形,然后以某种实现定义的方式叠加到输出介质上。
... 正 x 轴水平向右延伸,正 y 轴垂直向上延伸,就像在标准数学实践中一样(受页面字典中 Rotate 条目的更改)。
... 在 PostScript 中,默认用户空间的原点始终对应于输出介质的左下角。虽然这种约定在 PDF 文档中也很常见,但不是必需的;页面字典的 CropBox 条目可以指定默认用户空间的任何矩形在媒体上可见。
因此,原点 (0,0) 可以在任何地方,它可能在左下角、左上角、页面中间甚至在显示的页面区域之外。
通过 Rotate 条目,甚至可以旋转该区域(90°、180° 或 270°) .
将原点(您似乎已经观察到)放在左下方只是按照惯例。
此外,您似乎认为坐标系是恒定的。情况也并非如此,您可以通过一些操作彻底改变用户空间坐标系,您可以平移、旋转、镜像、倾斜和/或缩放它!
因此,即使一开始坐标系是通常的坐标系,原点在左下角,x 轴向右,y 轴向上,它可能会以某种方式在页面内容描述中更改为奇怪的东西。在页面中心右侧绘制矩形new PDRectangle(0, 0, 100, 100) 可能会产生一些菱形。
你能做什么...
如您所见,PDF 用户空间中的坐标是一个非常动态的问题。你可以做些什么来控制这种情况,取决于你使用矩形的上下文。
不幸的是,您对自己所做的事情的描述非常含糊。因此,这也会有些模糊。
页面内容中的坐标
如果你想在现有页面上绘制一些矩形,你首先需要一个页面内容流来写入,即PDPageContentStream实例,并且它应该以保证原始用户空间坐标的方式准备系统没有受到干扰。您可以通过使用带有三个布尔参数的构造函数将它们全部设置为true 来获得这样的实例:
PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true, true);
然后您可以对坐标系应用变换。您希望左上角为原点,y 值向下增加。如果页面的裁剪框告诉你左上角有坐标(xtl,ytl),那么,你申请
contentStream.concatenate2CTM(new AffineTransform(1, 0, 0, -1, xtl, ytl));
从这里你有一个你想要的坐标系,原点左上角和 y 坐标镜像。
但请注意一件事:如果您也打算绘制文本,那么不仅文本插入点 y 坐标会被镜像,而且文本本身也会被镜像,除非您通过添加一个镜像文本矩阵来抵消它!因此,如果您想添加很多文本,这可能不会像您想要的那样优雅。
注释坐标
如果您不想在内容流中使用矩形而是添加注释,则不受上述转换的约束,但也不能使用它。
因此,在这种情况下,您必须按原样获取裁剪框并相应地变换您的矩形。
为什么PDFBox文本提取坐标是原样
本质上是为了将文本行以正确的顺序放在一起并正确排序,您不希望出现这种奇怪的情况,而是需要一个简单的稳定坐标系。一些 PDFBox 开发人员为此选择了左上原点、y 递增向下的变体,因此 TextPosition 坐标已被标准化为该方案。
在我看来,更好的选择是使用默认的用户空间坐标,以便更轻松地重用坐标。因此,您可能想尝试使用textPosition.getTextMatrix().getTranslateX()、textPosition.getTextMatrix().getTranslateY() 来获得TextPosition textPosition