CTM 矩阵与先前状态的乘法与 PDF 位置解析中的单位矩阵相乘?

CTM matrix multiplication with previous state vs with Identity matrix in PDF position parsing?

我在 CTM 矩阵计算上经历了不同的解决方案(其中一些是 and )。

我对内容流的了解是当“q”遇到我们需要将单位矩阵推入graphics_stack并与下一个位置运算符(cm, Tm、Td、TD)CTM。当遇到“Q”我们需要弹出最后一个矩阵

当“BT”在position_stack中遇到推入单位矩阵时的文本定位解析,并与下一个位置运算符(cm,Tm,Td,TD)保持相乘CTM。当遇到“ET”我们需要弹出最后一个矩阵。

有时我们需要与最后一个 CTM 矩阵相乘,有时只与单位矩阵相乘。这些情况是什么时候发生的?

案例 1:

从图1和图2的情况来看,只是将新矩阵从Td替换为Tm。从 2 到 3 又是最后一次 CTM 乘法。我怎么知道的?(目测我能看出来)

案例 2:

在这种情况下,矩阵的推送和计算将如何进行?

案例 3:

BT
TT_1 20 Tf
35.56 150.24533 Td _______________ 1
(some sample text) Tj
50.526 250.36 Td  ________________ 2
(second line new replace) Tj
0 -16.2 Td   _____________________ 3
(Line end.) Tj
ET

这种情况1和2只是替换,2和3之前的矩阵乘法。我怎么知道?

案例 4:

请至少解析这些位置到10。这个pdf

的源文件

案例 5:

上面一个需要计算l位置。我用 1 到 4 个数字突出显示。我需要计算每个 l 的位置,该怎么做? pdf

案例 6:

页面(pdf)旋转90度或180度或270度和315度时计算有什么变化?

这些是我看到的一些案例。我还会遇到哪些其他情况?解决此问题的通用方法是什么?

感兴趣的运营商

首先,我的印象是你混淆了两个不同的方面。您有 当前转换矩阵 (CTM),并且有 texttext 行矩阵 。 CTM受制于cmqQ。文本和文本行矩阵受 BTTmTd、...以及确定绘制文本的确切位置和方向您需要文本矩阵 绘制文本时 CTM 的乘积。

PDF 规范 ISO 32000 第 1 部分或第 2 部分中描述了这些运算符如何更改矩阵。

来自 ISO 32000-1 Table 57 – 图形状态运算符 –

  • cm:通过拼接指定矩阵
  • 修改当前变换矩阵(CTM)
  • q:保存当前图形状态包括CTM到图形状态栈
  • Q:恢复图形状态包括CTM通过从堆栈中移除最近保存的状态并使其成为当前状态

来自 ISO 32000-1 Table 107 – 文本对象运算符 –

  • BT:开始一个文本对象,初始化文本矩阵,Tm,和文本行矩阵,Tlm,到单位矩阵。

来自 ISO 32000-1 Table 108 – 文本定位运算符 –

  • tx ty Td:移动到下一行的开头,从当前行的开头偏移(tx, ty)。更准确地说,该运算符应执行这些分配:

  • a b c d e f Tm:设置文本矩阵,Tm,和文本行矩阵,Tlm:

此外,TDT*' "TmTlm[= 上运行431=] 以使用 Td 运算符指定的方式。

来自 ISO 32000-1 第 9.4.4 节 – 文本 Space 详细信息 –

每当绘制一个字形时,它从文本 space 的整个转换可以由文本渲染矩阵表示,Trm:

其中Tfs为当前字体大小,T h为当前水平缩放因子,Trise为当前文字上升值

绘制那个字形后,Tm根据字形位移更新

水平模式下tx为位移,ty为零,垂直模式下tx 为零,ty 为位移。适用值计算为

示例 1

在接下来的段落中,我使用四舍五入的值来专注于要点。

CTM以单位矩阵开始,由于这里没有cm操作,所以一直如此。 TmTlm 另一方面做变化:

BT

TmTlm都设置为单位矩阵

/GS0 gs
/T1_0 10 Tf

TmTlm[=无变化431=].

317 65 Td

这会将如上所述的平移矩阵从左侧乘以 Tlm 的前一个值并设置 TmTlm 结果:

             1  0  0     1 0 0       1  0  0
T  = T   =   0  1  0  *  0 1 0  =    0  1  0
 m    lm   317 65  1     0 0 1     317 65  1

由于之前的值是身份,这可能 看起来 像是 Td 转换矩阵的替代,但它实际上是一个乘法.

(F)Tj

这会绘制一个由文本渲染矩阵转换的字形

       10 × 1   0  0       1  0  0     1 0 0      10  0  0
T   =       0  10  0  *    0  1  0  *  0 1 0  =    0 10  0
 rm         0   0  1     317 65  1     0 0 1     317 65  1

此后Tm如上所述被更新。不幸的是我们没有字体的宽度T1_0,所以我们无法计算更新值。

1 0 0 1 370 87 Tm

设置文本矩阵,Tm,和文本行矩阵,Tlm,给定矩阵:

              1  0  0
T  = T   =    0  1  0
 m    lm    370 87  1

所以现在我们又知道了当前的Tm值。

-47 -22 Td

这会将如上所述的平移矩阵从左侧乘以 Tlm 的前一个值并设置 TmTlm 结果:

              1   0  0       1  0  0       1  0  0
T  = T   =    0   1  0  *    0  1  0  =    0  1  0
 m    lm    -47 -22  1     370 87  1     323 65  1
[(igure)-251(2.3:)-621(P)16...] TJ

这会在参数数组中绘制字符串,起始文本呈现矩阵为

       10 × 1   0  0       1  0  0     1 0 0      10  0  0
T   =       0  10  0  *    0  1  0  *  0 1 0  =    0 10  0
 rm         0   0  1     323 65  1     0 0 1     323 65  1

如上所述一次又一次地更新Tm

示例 2

在接下来的段落中,我使用四舍五入的值来专注于要点。

CTM 以单位矩阵开始。

q

这会保存当前的图形状态,包括当前的 CTM。不过,由于示例中没有 Q 操作,我们暂时可以忽略它。

.24 0 0 .24 91 740 cm

这将通过给定矩阵更新 CTM:

        0.24   0     0     1 0 0      0.24   0     0
CTM =   0      0.24  0  *  0 1 0  =   0      0.24  0
       91    740     1     0 0 1     91    740     1
BT

TmTlm都设置为单位矩阵

133 0 0 133 0 0 Tm

设置文本矩阵,Tm,和文本行矩阵,Tlm,给定矩阵:

            133   0  0
T  = T   =    0 133  0
 m    lm      0   0  1
/TT1.0 1 Tf
.002 Tc

CTM、TmT无变化lm.

[(The)1( )1(Long )1(Tai)1(l)]TJ

这会在参数数组中绘制字符串,起始文本呈现矩阵为

       1 × 1  0  0     133   0  0      0.24   0    0     32   0  0
T   =      0  1  0  *    0 133  0  *   0      0.24 0  =   0  32  0
 rm        0  0  1       0   0  1     91    740    1     91 740  1

如上所述一次又一次地更新Tm

示例 3

BT
TT_1 20 Tf
35.56 150.24533 Td _______________ 1
(some sample text) Tj
50.526 250.36 Td  ________________ 2
(second line new replace) Tj
0 -16.2 Td   _____________________ 3
(Line end.) Tj
ET

在接下来的段落中,我使用四舍五入的值来专注于要点。

CTM以单位矩阵开始,由于这里没有cm操作,所以一直如此。 TmTlm 另一方面做变化:

BT

TmTlm都设置为单位矩阵

TT_1 20 Tf

TmTlm[=无变化431=].

36 150 Td

这会将如上所述的平移矩阵从左侧乘以 Tlm 的前一个值并设置 TmTlm 结果:

            1   0  0     1 0 0      1   0  0
T  = T   =  0   1  0  *  0 1 0  =   0   1  0
 m    lm   36 150  1     0 0 1     36 150  1

由于之前的值是身份,这可能 看起来 像是 Td 转换矩阵的替代,但它实际上是一个乘法.

(some sample text) Tj

这会绘制由文本渲染矩阵转换的字形

       20 × 1   0  0      1   0  0     1 0 0     20   0  0
T   =       0  20  0  *   0   1  0  *  0 1 0  =   0  20  0
 rm         0   0  1     36 150  1     0 0 1     36 150  1

此后Tm如上所述被更新。不幸的是我们没有字体的宽度TT_1,所以我们无法计算更新值。

51 250 Td

这会将如上所述的平移矩阵从左侧乘以 Tlm 的前一个值并设置 TmTlm 结果:

            1   0  0      1   0  0      1   0  0
T  = T   =  0   1  0  *   0   1  0  =   0   1  0
 m    lm   51 250  1     36 150  1     87 400  1

所以现在我们又知道了当前的Tm值。

(second line new replace) Tj

这会绘制由文本渲染矩阵转换的字形

       20 × 1   0  0      1   0  0     1 0 0     20   0  0
T   =       0  20  0  *   0   1  0  *  0 1 0  =   0  20  0
 rm         0   0  1     87 400  1     0 0 1     87 400  1

此后Tm如上所述被更新。不幸的是我们没有字体的宽度TT_1,所以我们无法计算更新值。

0 -16 Td

这会将如上所述的平移矩阵从左侧乘以 Tlm 的前一个值并设置 TmTlm 结果:

            1   0  0      1   0  0      1   0  0
T  = T   =  0   1  0  *   0   1  0  =   0   1  0
 m    lm    0 -16  1     87 400  1     87 384  1

所以现在我们又知道了当前的Tm值。

(Line end.) Tj

这会绘制由文本渲染矩阵转换的字形

       20 × 1   0  0      1   0  0     1 0 0     20   0  0
T   =       0  20  0  *   0   1  0  *  0 1 0  =   0  20  0
 rm         0   0  1     87 384  1     0 0 1     87 384  1

此后Tm如上所述被更新。不幸的是我们没有字体的宽度TT_1,所以我们无法计算更新值。

示例 4

我们在 中讨论了示例 4 及其注释。

示例 5

q 0.1 0 0 0.1 0 0 cm
/R108 gs
0 g
q
...
Q
0 0 1 rg
q
...
Q
4.05 w
0 G
722.023 4082.13 m
722.023 4490.28 l
S
723.961 4488.25 m
2872.98 4488.25 l
S
404.1 w
0 0 0.199951 0 K
723.961 4284.18 m
2872.98 4284.18 l
S
4.05 w
0 G
720 4080.2 m
2876.94 4080.2 l
S
2874.91 4082.13 m
2874.91 4490.28 l
S
0 g
q 

为什么您在查看这些说明时显示的数字不准确?以上是从串流内容中复制粘贴过来的,不需要那样改数字...

q
0.1 0 0 0.1 0 0 cm

将 CTM 设置为

       0.1 0   0
CTM =  0   0.1 0
       0   0   1
/R108 gs
...
0 G

CTM 没有任何反应

722.023 4082.13 m
722.023 4490.28 l
S

我们必须将 CTM 应用于这些坐标

                      0.1 0   0
[722.023 4082.13]  *  0   0.1 0  = [72.2023 408.213]
                      0   0   1

                      0.1 0   0
[722.023 4490.28]  *  0   0.1 0  = [72.2023 449.028]
                      0   0   1

因此,从 72.2023,408.213 划线到 72.2023,449.028。

723.961 4488.25 m
2872.98 4488.25 l
S

和上面一样,从72.3961,448.825到287.298,448.825画了一条线。

404.1 w
0 0 0.199951 0 K
723.961 4284.18 m
2872.98 4284.18 l
S

同样,从 72.3961,428.418 到 287.298,428.418 画了一条线。这里唯一值得注意的是这条线很宽,大约。 40 个单位,所以这条“线”实际上看起来更像是一个填充的矩形,代表具有洛伦兹力特征的文本框背景。

4.05 w
0 G
720 4080.2 m
2876.94 4080.2 l
S

绘制了另一条线,再次变窄,因此看起来像一条线,这次是从 72,408.02 到 287.694 408.02。

2874.91 4082.13 m
2874.91 4490.28 l
S

最后一行,这次是从 287.491,408.213 到 287.491,449.028。

例4解决方案:

CTM 以单位矩阵开始。

q

这将保存当前图形状态(图形状态 = Identity ---- 1)。

1 0 0 1 62.692 277.671 cm

这将通过给定矩阵更新 CTM:

        1      0      0     1 0 0      1      0      0
CTM =   0      0      0  *  0 1 0  =   0      1      0    ----- 2
        62.692 277.67 1     0 0 1     62.692  277.67 1

CTM 更新为以上结果

q

将 CTM 保存推送到图形状态(图形状态 = 1、2)

q

再次将相同的 CTM 矩阵推送到图形状态(图形状态 = 1、2、2)

1 0 0 1 286.59 207.54 cm

通过当前矩阵更新 CTM。

      1      0      0   1      0      0        1      0      0
CTM = 0      1      0 * 0      0      0    =   0      1      0    ----- 3
      286.49 207.54 1  62.692 277.67 1        349.18 485.21  1

CTM 已更新为上述结果矩阵。

q

将 CTM 保存推送到图形状态(图形状态 = 1、2、2、3)

.75 .75 .75 RG
n
11.33 19.84 171.67 232.146 re
S

这不会改变位置矩阵。

Q

将 CTM 分配给最后一个可用图形状态 CTM = 3。Q 将从图形堆栈中删除最后一个图形状态。(图形状态 = 1、2、2)

1 0 0 1 17.007 23.52 cm 

通过当前矩阵更新 CTM。

      1      0      0   0      1      0        0      1      0
CTM = 0      1      0 * 0      0      0    =   0      1      0    ----- 4
      17.007 23.52  1  349.18 485.21  1        366.18 508.73 1

CTM 已更新为上述结果矩阵。

q

将最后一个 CTM 推送到图形状态(图形状态 = 1、2、2、4) 跳过 rg, RG

BT

将 Tm 和 Tlm 分配给单位矩阵。

1 0 0 1 0 5.6 Tm

这会将文本矩阵 Tm 和文本行矩阵 Tlm 设置为给定矩阵:

              1   0    0
T  = T   =    0   1    0
 m    lm      0   5.6  1

Tm 和 Tlm 已更新。

46.22 0 Td

根据上面的Td矩阵翻译矩阵。

             1   0  0     1 0   0       1     0  0
T  = T   =   0   1  0  *  0 1   0  =    0     1  0
 m    lm   46.22 0  1     0 5.6 1       46.22 5.6  1

用上面的矩阵更新 Tm 和 Tlm。下一个Tf你可以走了

12 TL

此设置图形状态前导文本参数,对 Tm 或 Tlm 没有直接影响。

(William Shakespeare) Tj

这将逐个绘制字符串字形,这是此文本渲染矩阵转换的第一个字形

       8 × 1   0  0       1    0   0     1     0      0      8     0       0
T   =       0  8  0  *    0    1   0  *  0     1      0  =   0     8       0
 rm         0  0  1     46.22 5.6  1    366.18 508.73 1     412.4 514.33  1

当字符串逐字形呈现时,Tm 会按照 ISO 32000-1 第 9.4.4 节中的描述进行更新,Trm 也是如此。

T*

由于当前行距为12,T*相当于0 -12 Td,所以:

             1   0  0     1     0   0       1       0   0
T  = T   =   0   1  0  *  0     1   0  =    0       1   0
 m    lm     0  -12 1     46.22 5.6 1       46.22 -6.4  1