【问题标题】:how to get the current position,position of a curve using pdfbox如何使用pdfbox获取当前位置,曲线的位置
【发布时间】:2013-12-17 14:14:41
【问题描述】:

我正在尝试使用 pdfbox 获得三次贝塞尔曲线的位置。 我试图拦截“c”操作并试图通过从列表中提取曲线的参数来获取它们。我这里有两个问题。首先当前位置始终为 (0,0)。获取我使用的当前位置

float x = getGraphicsState().getCurrentTransformationMatrix().getXPosition();
float y = getGraphicsState().getCurrentTransformationMatrix().getYPosition();

当前的变换矩阵总是一个单位矩阵。我应该做一个AffineTransform 吗?但去哪里? 第二个是“c”操作的参数大于页面尺寸。我应该将它们除以 x 和 y 比例吗?

【问题讨论】:

  • 曲线从上一个 moveTo、lineTo 或曲线绘制操作停止的地方开始。因此,您必须跟踪所有这些操作。此外,正如您似乎已经做的那样,您必须密切关注当前的转换矩阵。
  • 曲线命令“c”例如定义了绘制曲线的参数。唯一没有定义的是起点。我想我可以从当前的变换矩阵中得到它。并且绘制曲线的参数在“pt”r8 中给出?我的方法错了吗?

标签: java pdf pdf-generation pdfbox


【解决方案1】:

背景

通过尝试考虑当前的变换矩阵,您做了一件必要的事情,但还有另一个数据需要考虑,当前路径当前点。参照。 specification:

当前正在构建的路径称为当前路径。在 PDF 中(与 PostScript 不同),当前路径不是图形状态的一部分,并且不会与其他图形状态参数一起保存和恢复。 PDF 路径应该是严格的内部对象,没有明确的表示。当前路径绘制完成后,将不再定义;在使用 mre 运算符开始新路径之前,没有当前路径。

最近添加到当前路径的段的尾随端点称为当前点。如果当前路径为空,则当前点未定义。大多数将段添加到当前路径的运算符都从当前点开始;如果当前点未定义,则会产生错误。

[...]

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 

mcS 操作在原点周围绘制一个直径为 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 操作。相反,您必须使用 mre 运算符 找到路径构建过程的开始位置,并跟踪当前点。当您到达您感兴趣的曲线时,它会从当前变换的点开始,并在显式给定的变换曲线终点结束。

根据您的代码,转换矩阵可能由框架提供,或者您可能还必须跟踪它。

如果您通过使用从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 页)

【讨论】:

  • 如果我使用扩展 PDFStreamEngine 的类截取命令“c”,当前变换矩阵在绘制曲线之前包含 x 和 y 位置?所以我不需要拦截改变当前转换矩阵的其他运算符,调用超类方法的后备逻辑不会做吗?我的意思是我需要明确拦截“cm”命令。我认为它将由超类逻辑处理,当我调用 getgraphicstate.getCTM 时,我会得到 (300,300),因为这已经被超类方法处理了?
  • 我应该将这个 processOperator 的参数除以 xscale 和 yscale 吗?...它们超出了页面尺寸
  • 如果我使用扩展 PDFStreamEngine 的类截取命令“c”,当前变换矩阵包含绘制曲线之前的 x 和 y 位置? - 一般 没有。请参阅我的答案中的示例:矩阵中的 x 和 y 是 300, 300 但绘制前的位置是 330, 300, 300, 330、270、300300、270
  • 我是否应该将此 processOperator 的参数除以 xscale 和 yscale - 不,您应该与当前的转换矩阵相乘,如我的回答所示。如果不涉及旋转或剪切,这实质上意味着与 xscale 和 yscale 相乘。
  • 我发现了我的错误。我正在拦截路径构造命令,我正在读取形状但我没有设置当前的转换矩阵。因此,在图形恢复之前,当前点不会改变
猜你喜欢
  • 2011-07-15
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
相关资源
最近更新 更多