在不同的 PDF 查看器中具有不同输出的 PDF带阴影

问题描述

考虑以下 PostScript 文件

[1 0 0.5 0.866 150 550] concat
<< 
   /ShadingType 2 
   /Coords [ 0 0 100 100] 
   /BBox [ 0 0 100 100] 
   /ColorSpace [ /DeviceRGB ] 
   /Function 
      << 
         /FunctionType 0 
         /Domain [0 1] 
         /Range [0 1 0 1 0 1] 
         /BitsPerSample 8 
         /Size [2] 
         /DataSource <FFA0A0FFE0E0> 
      >>
   /Extend [false false] 
>> 
shfill

考虑我们使用 GhostScript (ps2pdf) 或 Adob​​e Distiller 将该文件转换为 PDF。

生成的 PDF 在不同的 PDF 查看器中的呈现方式不同:

  • 在 Adob​​e Reader 或 Firefox(使用 PDF.js)中,我们有一个平行四边形(不是矩形)。
  • 在 SumatraPDF(使用 MuPDF)和 Chrome(使用 PDFium)中,我们有一个矩形。

谁是对的?

解决方法

在我看来 Adob​​e Acrobat 是正确的,但规范也可以有不同的解读。

您的 PDF 包含以下内容流:

/GS1 gs
q
1 0 .5 .866 150 550 cm
/Sh1 sh
Q

即首先改变当前变换矩阵,将其剪切和挤压一点,然后绘制阴影Sh1。该阴影依次定义为

<</BBox[0 0 100 100]/ColorSpace/DeviceRGB/Coords[0 0 100 100]/Function 15 0 R/ShadingType 2>>

即带有 100×100 方形边界框(解释为临时附加剪切路径)和沿其 (0,0) 到 (100,100) 对角线的轴向阴影,与您的 postscript 定义相匹配。

着色运算符 sh 指定为

操作数 操作员 说明
名称 sh (PDF 1.3) 根据当前的剪切路径绘制由着色字典描述的形状和颜色着色。图形状态中的当前颜色既不使用也不更改。该效果与使用阴影图案作为当前颜色绘制路径的效果不同。 name 是当前资源字典的着色子字典中着色字典资源的名称(参见 7.8.3,“资源字典”)。着色字典中的所有坐标都相对于当前用户空间进行解释。 (相比之下,当在类型 2 模式中使用着色字典时,坐标在模式空间中表示。)所有颜色都在着色字典的 ColorSpace 条目标识的颜色空间中解释(请参阅“表 77 — 所有着色字典共有的条目”)。 Background 条目(如果存在)将被忽略。
此运算符应仅应用于有界或几何定义的阴影。如果应用于无界阴影,它会在整个裁剪区域绘制阴影的渐变填充,这可能很耗时。

(ISO 32000-2:2017,表 76 — 着色运算符)

特别是:着色字典中的所有坐标都是相对于当前用户空间进行解释的。

因此,方形边界框/临时剪辑路径被当前变换矩阵挤压和剪切为非矩形平行四边形,如 Adob​​e Acrobat 中所示:

Screenshot

我在上面提到,规范也可以有不同的解读:如果将 BBox 条目视为两个点的坐标,即框的左下角和右上角,并且使结果成为一个盒子之前应用转换,一个人会得到一个被压扁的、拉长的矩形,可以在 Chrome 中查看:

Screenshot

但是这里的 BBox 被指定为 一个由四个数字组成的数组,分别给出了着色边界框的左、下、右和上坐标(同上,表 77 —所有着色字典共有的条目),而不是作为对角线两个端点的坐标。因此,我更喜欢 Adob​​e 实现的第一种解释。

我还没有 ISO 32000-2:2020 的副本,所以也许这已经以某种方式澄清了。


如果在填充指令期间将用作当前颜色的图案中使用阴影,则情况会有所不同。在这种情况下,规范说:

一个图案的外观是根据它自己的内部坐标系来描述的。每个模式都有一个模式矩阵,这是一个变换矩阵,将模式的内部坐标系映射到模式的父内容流(模式所在的内容流)的默认坐标系被定义为资源)。模式矩阵与父内容流矩阵的串联建立了模式坐标空间,模式中的所有图形对象都应在其中进行解释。

(ISO 32000-2:2017,第 8.7.2 节 — 模式的一般属性)

在这种情况下,带有对角轴阴影的方形边界框将不受当前变换矩阵的影响。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...