背景
通过尝试考虑当前的变换矩阵,您做了一件必要的事情,但还有另一个数据需要考虑,当前路径的当前点。参照。 specification:
当前正在构建的路径称为当前路径。在 PDF 中(与 PostScript 不同),当前路径不是图形状态的一部分,并且不会与其他图形状态参数一起保存和恢复。 PDF 路径应该是严格的内部对象,没有明确的表示。当前路径绘制完成后,将不再定义;在使用 m 或 re 运算符开始新路径之前,没有当前路径。
最近添加到当前路径的段的尾随端点称为当前点。如果当前路径为空,则当前点未定义。大多数将段添加到当前路径的运算符都从当前点开始;如果当前点未定义,则会产生错误。
[...]
x1 y1 x2 y2 x3 y3 c 将三次贝塞尔曲线附加到当前路径。曲线
应从当前点延伸到点 (x3, y3),使用 (x1, y1) 和 (x2, y2) 作为贝塞尔控制点(见 8.5.2.2,“三次贝塞尔曲线”)。新的当前点应为 (x3, y3)。
(第 8.5.2 节路径构造运算符,第 132 页)
例如看看这个
3 0 0 3 300 300 cm
10 0 m
10 5.52 5.52 10 0 10 c
-5.52 10 -10 5.52 -10 0 c
-10 -5.52 -5.52 -10 0 -10 c
5.52 -10 10 -5.52 10 0 c
S
m、c 和 S 操作在原点周围绘制一个直径为 10 的圆:
-
10 0 m将当前点移动到(10, 0);
-
10 5.52 5.52 10 0 10 c 添加从当前点到(0, 10)的四分之一圆路径元素;现在当前点是 (0, 10);
-
-5.52 10 -10 5.52 -10 0 c 添加从当前点到(-10, 0)的四分之一圆路径元素;现在当前点是 (-10, 0);
-
-10 -5.52 -5.52 -10 0 -10 c 添加从当前点到(0, -10)的四分之一圆路径元素;现在当前点是 (0, -10);
-
5.52 -10 10 -5.52 10 0 c 添加从当前点到(10, 0)完成圆的四分之一圆路径元素;现在当前点是 (10, 0);
-
S 沿着由给定路径元素定义的路径绘制,即圆线。
但是由于之前由 3 0 0 3 300 300 cm 设置的变换矩阵,它按因子 3 缩放并将缩放的内容移动到 (300, 300),因此实际上是在周围绘制了圆(300, 300),半径为 30。
您通过乘法获得最终坐标,例如对于第一个圆的起点(10, 0):
┌ 3 0 0 ┐
[ 10 0 1 ] x │ 0 3 0 │ = [ 330 300 1]
└ 300 300 1 ┘
实际上是 (330, 300)。
你的任务
因此,要找到曲线的坐标,您需要注意的不仅仅是 c 操作。相反,您必须使用 m 或 re 运算符 找到路径构建过程的开始位置,并跟踪当前点。当您到达您感兴趣的曲线时,它会从当前变换的点开始,并在显式给定的变换曲线终点结束。
根据您的代码,转换矩阵可能由框架提供,或者您可能还必须跟踪它。
如果您通过使用从PDFStreamEngine 派生的某个类来拦截“c”操作,则可以通过注册适当的OperatorProcessors 让该引擎跟踪当前的转换矩阵。
另一方面,如果您处理 PDFStreamParser.getTokens() 返回的列表,则必须手动跟踪它。
在这两种情况下,重要的操作是:
— q 将当前图形状态保存在图形状态堆栈中(参见
8.4.2,“图形状态堆栈”)。
— Q 通过从堆栈中删除最近保存的状态并使其成为当前状态来恢复图形状态(参见 8.4.2,“图形状态堆栈” )。
a b c d e f cm 通过连接指定的矩阵来修改当前的变换矩阵(CTM)(见 8.3.2,“坐标空间”)。尽管操作数指定了一个矩阵,但它们应写为六个单独的数字,而不是一个数组。
(第 8.4.4 节图形状态运算符,第 127 页)