如何识别哪些剪辑路径应用于路径或填写PDF矢量图形?

so2*_*so2 1 pdf svg clipping xpdf

我试图从PDF文件中提取矢量图形并创建相应的SVG文件.我正在使用SVGOutputDev(https://github.com/immateriel/pdf2svg/blob/master/SVGOutputDev.cc)和xpdf库来实现此目的.现在SVGOutputDev还没有实现剪辑路径提取,我正在尝试实现相同的.虽然我能够自己提取剪辑路径定义,但我无法确定哪些定义适用于普通笔划或填充区域.例如,请参阅http://pastebin.com/jTdzv3YZ我从一页PDF中提取的SVG,以及在提取过程中看到的PDF图形命令序列的相应转储.从该SVG可以看出,存在多个剪辑路径和一个矩形填充区域.即使有被定义的填充的矩形前定义的多个剪辑的路径,仅圆形夹路径定义之前矩形定义应该与矩形相关联(通过PDF页面在各种PDF阅读器上呈现的方式,在白色背景中仅显示2个黑色圆圈).问题是如何知道哪些剪辑路径与PDF中定义的常规填充/描边区域相关联?仅供参考,我浏览了PDF规范文档的相关部分但对我来说并不是很清楚("剪切路径操作可能出现在最后一个路径构造操作符之后和路径绘制操作符之前终止路径对象.虽然剪切路径操作符出现在绘制操作符之前,它不会在它出现的位置改变剪切路径.而是修改后续绘制操作符的效果").

mkl*_*mkl 5

问题是如何知道哪些剪辑路径与PDF中定义的常规填充/描边区域相关联?

简而言之:除了在Q(恢复状态)运算符期间无效的那些之外,在执行填充或描边操作时定义的所有剪辑路径区域的交集也适用.

因此,您对样本文件的分析

即使在定义填充矩形之前定义了多个剪辑路径,但只有在矩形定义之前定义的圆形剪辑路径才会与矩形相关联(通过各种PDF阅读器的PDF页面呈现方式,显示白色背景中只有2个黑色圆圈)

错误:不是最后一个剪辑区域,而是矩形定义之前所有剪辑区域的交集定义了当前剪辑区域.由于每个剪辑区域都包含在前一个剪辑区域中,因此交叉点的结果确实由这两个圆圈组成.

在文档中:

图形状态应包含当前剪切路径,该路径限制受绘制操作符影响的页面区域.该路径的封闭子路径应定义可绘制的区域.

初始剪切路径应包括整个页面.

[剪切路径操作符]通过将当前剪切路径与当前路径相交来修改当前剪切路径,使用[非零绕组编号规则/奇偶规则]来确定哪些区域位于剪切路径内.

无法在不参考当前剪切路径的情况下放大当前剪切路径或设置新的剪切路径.但是,由于剪切路径是图形状态的一部分,因此可以通过封闭剪切路径的修改以及在一对q和Q运算符之间绘制这些对象来将其效果本地化到特定的图形对象(见8.4.2, "图形状态堆栈").执行Q运算符会导致剪切路径恢复为修改剪切路径之前q运算符保存的值.

(当前PDF规范ISO 32000-1中的8.5.4节)

实际操作:让我们看看你的文档页面的内容流(有一个Mediabox [0,0,595,842]):

q
q
Run Code Online (Sandbox Code Playgroud)

两次推动图形状态.

0 842 m 
0 0 l
595 0 l
595 842 l
h
W
n
Run Code Online (Sandbox Code Playgroud)

定义与整个媒体框等效的剪辑路径.

1 w
2 J
0 j
10 M
[]0 d
Run Code Online (Sandbox Code Playgroud)

定义常规图形状态属性(线宽,线帽样式,线连接样式,斜接限制和虚线模式).

q
Run Code Online (Sandbox Code Playgroud)

再次推送图形状态,这次使用显式设置的剪辑路径和其他图形属性.

0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
Run Code Online (Sandbox Code Playgroud)

定义一个剪辑路径,其中包含一个与整个媒体框一样宽的矩形,但会切掉124个用户空间单位高度的顶部和底部条纹.由于此剪辑路径完全包含在之前设置的剪辑路径中,因此此交叉点等于此剪辑路径.因此,当前有效的剪辑区域是这个较小的矩形.

0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
Run Code Online (Sandbox Code Playgroud)

定义与前一个相同的剪辑路径.因此,相交它们不会改变任何东西.

148.75 668.92 m
93.98 668.92 49.58 624.52 49.58 569.75 c
49.58 514.98 93.98 470.58 148.75 470.58 c
203.52 470.58 247.92 514.98 247.92 569.75 c
247.92 624.52 203.52 668.92 148.75 668.92 c
h
347.08 470.58 m
292.32 470.58 247.92 426.18 247.92 371.42 c
247.92 316.65 292.32 272.25 347.08 272.25 c
401.85 272.25 446.25 316.65 446.25 371.42 c
446.25 426.18 401.85 470.58 347.08 470.58 c
h
W
n
Run Code Online (Sandbox Code Playgroud)

定义由两个圆形子路径组成的剪辑路径.这两个圆圈不相交; 因此,我们不必处理"非零绕数规则"和"偶数规则"之间的差异.此外,圆圈包含在当前剪辑区域内.因此,新剪辑区域由这两个圆圈组成.

0 0 0 rg
49.58 668.92 m
545.42 668.92 l
545.42 173.08 l
49.58 173.08 l
49.58 668.92 l
h
f
Run Code Online (Sandbox Code Playgroud)

这将绘制一个填充的黑色矩形,其中包含当前剪切区域.因此,整个剪切区域(即两个圆圈)被涂成黑色.

Q
q
Run Code Online (Sandbox Code Playgroud)

这会将图形状态恢复到最后一个推送状态.即任何后续操作的剪切路径是包含整个媒体盒的第一个操作.再次按下此图形状态.

0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Run Code Online (Sandbox Code Playgroud)

再次定义顶部和底部的剪切路径剪切条...

Q
q
Run Code Online (Sandbox Code Playgroud)

...并立即通过恢复状态操作; 国家再次受到推动.

0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
Run Code Online (Sandbox Code Playgroud)

再一次......

0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
Run Code Online (Sandbox Code Playgroud)

... 然后再次.

0 842 m
0 0 l
595 0 l
595 842 l
h
W
n
Run Code Online (Sandbox Code Playgroud)

这又一次定义了一个环绕整个媒体盒的剪切路径.因为这是当前的剪切路径,所以没有任何因交叉而改变.

Q
Q
Q
Run Code Online (Sandbox Code Playgroud)

之前被推入堆栈的所有图形状态将再次被删除.