我希望能够运行一些任意的 PostScript 代码,并找出它的边界框是什么,以便在我再次运行时居中和/或缩放该 PostScript 代码。这需要在 PostScript 解释器的一次调用中全部发生。 (即发生在我可以发送到打印机的
.ps
文件中)
伪代码:
Run this PostScript code without drawing anything
<some arbitrary PostScript code>
Get the bounding box of the code that just ran
Do some computations to center it, and/or scale it if it's too big
Run the PostScript code with scaling/translation, and actually draw
<the same arbitrary PostScript code>
任意的PostScript代码可能会绘制多条路径,所以不是调用
pathbbox
那么简单。 (有没有办法将任意的 PostScript 代码块组合成一个路径,以便可以使用pathbbox
?)
这似乎类似于这个问题,不幸的是自 1992 年以来一直没有答案。
不可接受 答案是涉及多次调用 PostScript 解释器的任何答案。 (例如使用 GhostScript bbox 设备。)这必须作为普通的 PostScript 程序在任何(*)兼容的 PostScript 解释器上运行。
(*) 要求 PostScript Level 3 是可以接受的,但要求特定实现(例如 GhostScript)是不可接受的
这是“可能的”但并非微不足道,答案在很大程度上取决于准确性、性能和可靠性对您的重要性,以及您准备在该项目上投入多少时间以及您的 PostScript 编程水平能力。
理论上,您可以重新定义每个 PostScript 标记操作符(例如笔划、填充、图像、所有显示变体等),而不是绘制结果,确定由该操作标记的页面区域。对于某些运算符(例如 rectfill),这是微不足道的,对于其他运算符,它会更复杂,但仍然可以通过使用 charpath 和 pathforall 来确定任何 PostScript 操作标记的区域。
现在介绍你的第一点; pathbbox 本身是不够的,因为任何 PostScript 绘图操作都可以通过剪辑来绘制,而剪辑不一定是简单的矩形。
考虑这个使用矩形剪辑的简单示例:
%!
100 100 translate
0 0 0 setrgbcolor
-45 rotate
0 0 moveto
0 100 lineto
50 100 lineto
50 0 lineto
closepath
clip
newpath
90 rotate
0 -50 translate
0 1 0 setrgbcolor
0 0 moveto
0 100 lineto
50 100 lineto
50 0 lineto
closepath
fill
showpage
为了帮助可视化正在发生的事情,让我们将剪辑绘制为黑色笔划。看起来像这样:
如果我们将 pathboox 应用到填充路径,它将不会应用剪辑(并将使用 CTM 报告它的坐标),因此与实际呈现的结果相比,结果将是错误的(执行 pathbbox 然后撤消 CTM并转换为默认用户空间导致 bbox 为 64.64、64.64、170.71、170.71,而 bbox 设备以 72 dpi 返回的实际 bbox 为 100、64、171、136)。
您必须将当前剪辑与当前路径相交(如果正在绘制路径,则使用 clippath 检索当前剪辑和 currentpath 检索当前路径)或矩形路径(如果执行类似图像运算符的操作),然后工作出该交叉点的边界框,以确定 rendered.
的边界框有其他困难;当描边线时,您需要考虑线宽以确定标记的区域,线连接可以斜接,您需要确定斜接终止的位置,曲线可以延伸到基于简单矩形边界框的边缘在他们的端点上。
所有这些问题都在渲染时通过扫描转换路径来处理。基本上这意味着将复杂的形状转换为一系列填充的矩形。在极限情况下,矩形的高度是一条扫描线(即一个像素高)。裁剪只是相交矩形的一种情况。
当然,这确实会导致精度限制,因为矩形是设备分辨率。以 72 dpi 扫描转换浅曲线的结果可能与以 720 dpi 扫描转换的结果不同。这就是 Ghostscript bbox 设备使用高分辨率的原因。
现在 PostScript 是一种编程语言,所以显然您可以在 PostScript 中进行扫描转换和矩形交集。另一方面,它也是一种解释性语言,因此相对较慢;这就是性能限制的来源。对于复杂的 PostScript 输入,扫描转换和相交矩形列表可能需要相当长的时间(并且确实会占用相当多的内存来存储矩形列表)如果执行后记。
最后的可靠性;它并不常见,但真正任意的 PostScript 可以定义它自己的序言,直接从 systemdict 中读取运算符,而不是使用当前定义(例如
/myfill systemdict /fill load def
)。这样做的 PostScript 会逃避操作员的重新定义,然后操作员将不会运行“bbox”程序并阻止它工作。
所以有a解决方案;我并不声称它是唯一的,但我不知道有更好的解决方案可以纯粹在 PostScript 和任何 PostScript 解释器中工作。我认为这将是一项艰巨的任务。