首先,当尝试根据其位置从 PDF 中提取文本时,仅提供 tx 和 ty 时,仅考虑文本矩阵(您使用已找到的Tm运算符设置的)是不够的。您还必须考虑当前的转换矩阵!
我假设当您引用默认用户空间坐标中给出的位置时。
为了避免在设备空间中指定对象的设备相关影响,PDF 定义了一个与设备无关的坐标系,该坐标系始终与当前页面具有相同的关系,而与发生打印或显示的输出设备无关。这种与设备无关的坐标系称为用户空间。
用户空间坐标系应初始化为文档每一页的默认状态。页面字典中的 CropBox 条目应指定与预期输出介质(显示窗口或打印页面)的可见区域相对应的用户空间矩形。正 x 轴水平向右延伸,正 y 轴垂直向上
(第 8.3.2.3 节,ISO 32000-1:2008)
由于我们只看到 x 和 y 坐标,我们将位置视为 R² 中的向量 (x, y)。然而,在内部,PDF 认为这个平面嵌入在 R³ 中,具有恒定的 z 坐标值 1,即 [x, y, 1]。这是因为 PDF 希望允许多种转换(平移、旋转、缩放、倾斜等),但另一方面又希望尽可能限制所需的数学运算。顺便说一句,在将我们的平面作为 [x, y, 1] 嵌入到 R³ 中之后,所有这些变换都可以通过矩阵乘法来实现:
在这里,您已经看到了您询问的数字 a、b、c、d、e 和 f。
现在,在考虑文本特定转换之前,您必须考虑当前(与文本无关)转换矩阵的操作。该矩阵由cm运算符操作:
abcdef cm通过连接指定的矩阵来修改当前的变换矩阵(CTM)(见 8.3.2,“坐标空间”)。尽管操作数指定了一个矩阵,但它们应写为六个单独的数字,而不是一个数组。
(第 8.4.4 节,ISO 32000-1:2008)
顺便说一句,这意味着您必须考虑当前正在运行的所有cm运算符,即自页面内容开始以来所有呈现的,除了通过恢复以前的图形状态而撤销的那些(参见运算符q和Q推送和恢复图形状态,第 8.4.2 节,ISO 32000-1:2008)。
只有现在您可以考虑文本特定的转换矩阵:
在文本对象的开头,Tm应为单位矩阵;因此,文本空间的原点最初应与用户空间的原点相同。表 108 中描述的文本定位操作符会改变Tm,从而控制随后绘制的字形的位置。此外,表 109 中描述的文本显示操作符会更新Tm(通过更改其 e 和 f 转换组件)以考虑每个绘制的字形的水平或垂直位移以及任何字符或单词间距参数文本状态。
此外,在文本对象中,符合标准的阅读器应跟踪文本行矩阵Tlm,该矩阵捕获文本行开头的 Tm 值。文本定位和文本显示操作符应在表 108 和 109 中提到的特定场合读取和设置 Tlm
(第 9.4.2 节,ISO 32000-1:2008)
因此,在文本对象内部,您必须跟踪文本矩阵,该矩阵主要使用您找到的Tm运算符设置,操作数如上所示排列在矩阵中,但也作为其他文本定位和文本的效果进行操作显示运算符。
并且还有额外的参数决定了文本的最终位置,文本状态参数Tfs(文本字体大小)、Th(水平缩放)和Trise(文本上升),cf. ISO 32000-1:2008第 9.3.1 节。
从概念上讲,从文本空间到设备空间[或在您的情况下到默认用户空间]的整个转换可以由文本渲染矩阵Trm 表示:
Trm是一个临时矩阵;从概念上讲,它是在文本显示操作期间绘制每个字形之前重新计算的。
(第 9.4.2 节,ISO 32000-1:2008)
因此,您的坐标 (x, y) 在概念上由文本空间坐标乘以Trm 得出:
[x, y, 1] = [xts, yts, 1] x Trm
其中 (xts, yts) 在字形原点是 (0, 0)。对于每个打印的字形,您都有一个字形位移来到达下一个字形原点的位置:
文本矩阵应由这些字形位移值更新,如下所示:
(第 9.4.4 节,ISO 32000-1:2008)
我引用了当前 PDF 规范ISO 32000-1:2008中的一些段落。我认为这比使用非常古老的 PDF 参考 1.4 更可取;此外,它被 Adobe 个人称为“本质上不规范”。
编辑 回答评论的一些澄清
设备空间和用户空间,它们有什么区别,设备空间不是指打印机/视频显示吗?和用户空间来克服每个设备的特殊性?就像用户页面是我看到的文档页面?
是的,设备空间是一个固定的坐标系,基本上由手头设备的属性决定。是的,用户空间是一个独立于目标设备的坐标系。但是不,它不是“您看到的文档页面”,因为您在某些设备上看到它(或在被某些设备处理之后)。
用户空间坐标系是一个独立的坐标系,其一点的坐标可以通过与当前变换矩阵(CTM)的矩阵乘法转换为设备坐标。
UserCoords x CTM = DeviceCoords
用户空间坐标系被初始化为页面字典中的CropBox条目通过相应地初始化CTM来指定与可见区域(见上文)对应的用户空间矩形的状态。
但是正如单词的选择已经表明(“当前变换矩阵”,“坐标系被初始化”),用户空间坐标系是一个动态的、不断变化的坐标系。
无论使用何种输出设备,默认用户空间都为 PDF 页面描述提供了一致、可靠的起点。如有必要,PDF 内容流可以通过应用坐标变换运算符cm来修改用户空间以更适合其需要(参见 8.4.4,“图形状态运算符”)。因此,内容流中看似绝对坐标的内容相对于当前页面并不是绝对的,因为它们是在一个坐标系中表示的,该坐标系可以左右滑动、缩小或扩大。坐标系变换不仅增强了设备独立性,而且本身就是一个有用的工具。
(第 8.3.2.3 节,ISO 32000-1:2008)
因此,当 aPdfReader
偶然发现一个cm运算符,其参数表示某个矩阵 M,CTM 会发生变化:
CTMnew = M x CTMold
以下运算符中存在的坐标和坐标根据这个新矩阵 CTMnew 进行解释:
UserCoords x CTMnew = DeviceCoords
所以现在用户空间坐标系可能与其以前的状态非常不同,缩放、旋转、倾斜等等。
您最感兴趣的坐标很可能是用户空间被初始化为的坐标系中的坐标,即CTM 被初始化为单位矩阵的虚拟设备的设备坐标系。
文本空间和字形空间在哪里开始和结束。
文本的坐标在文本空间中指定。从文本空间到用户空间的转换由文本矩阵结合图形状态下的几个文本相关参数定义(参见 9.4.2,“文本定位操作符”)。
文本矩阵 TM 在文本对象的开头被初始化为单位矩阵,但在执行文本操作期间会发生变化,当您使用Tm运算符时最明显,而当您使用其他运算符时则隐含。该矩阵由包含文本相关参数字体大小、水平缩放和文本上升的矩阵 TR 操作。有关详细信息,请参见上面的文本渲染矩阵 TRM。因此,
DeviceCoords = UserCoords x CTM = TextCoords x TR x TM x CTM
从字形空间到文本空间的转换应由字体矩阵定义。对于大多数类型的字体,该矩阵应预定义为将 1000 个字形空间单位映射到 1 个文本空间单位;对于 Type 3 字体,字体矩阵应在字体字典中明确给出(见 9.6.5,“Type 3 Fonts”)。
因此,这种转换取决于当前字体。字体字典中的字体矩阵 FM 的行为如下:
DeviceCoords = GlyphCoords x FM x TR x TM x CTM
您不想定位字形的单个段的设备坐标,因此这些坐标似乎不感兴趣。但是,字形宽度将在字形空间中解释。但是,除非您正在处理 Type 3 字体,否则这仅意味着您必须将它们除以 1000...
以及在字形绘制过程中参数 w0 和 w1 是如何演变的?他们最初是 (0,0)
w0 和 w1 表示字形的水平和垂直位移。在水平书写模式下,w0 是转换为文本模式的字形宽度(即通常仅除以 1000),w1 为 0。对于垂直书写模式,文本检查ISO 32000-1:2008中的第 9.2.4 和 9.7.4.3 节。
文本空间是否与第一个字形空间具有相同的起源?并使用计算出的 (tx,ty) 进行更新?
由于字形空间坐标仅乘以字体矩阵以产生文本空间坐标,并且在所有情况下字体矩阵,但对于 Type 3 字体仅压缩 1000 倍,见上文,字形原点映射到文本空间起源。
但是 tx 和 ty 用于更新文本矩阵本身。因此,文本规范坐标系会针对每个字形移动,并且对于每个(非类型 3)字形原点映射到原点……的文本空间坐标系略有变化。