PostScript中如何对路径每个lineto线段单独描边
问题原因
PostScript 规范明确规定,pathforall 执行遍历的四个回调过程中,当前图形状态下的路径处于只读锁定状态,不允许执行任何修改、消耗路径的操作(包括stroke、fill、moveto、lineto这类路径构造/绘制操作),这就是你在lineto回调里直接写stroke不生效的根本原因。
你之前的写法里,所有颜色切换操作都是在遍历路径时执行的,路径遍历完成后才执行唯一的一次stroke,此时图形状态里只保留了最后一次设置的rgb颜色,自然整段路径都会用最后一个颜色绘制。
实现方案
要实现分段多色描边,核心思路是边遍历边手动构造单段路径、逐段描边,不要等整个路径遍历完再统一stroke:
- 遍历过程中单独维护一个「当前路径起点」的坐标变量
- 每遇到moveto操作时,只更新当前起点坐标,不构造路径
- 每遇到lineto操作时:
- 先切换到当前段需要的颜色
- 用
newpath清空临时路径,从保存的起点坐标moveto到当前lineto传入的终点坐标 - 立即执行stroke完成这一段的绘制
- 更新当前起点坐标为这次lineto的终点,供下一段使用
- curveto、closepath逻辑可以按同样的思路扩展,你的测试代码只用了直线段,优先处理直线场景即可
修正后的可运行代码
/Arial 12 selectfont /color 6 def /s 20 string def 1 setlinewidth % 维护当前段起点坐标 /cur_x 0 def /cur_y 0 def /#NextColor{ color 10 gt { 0 /color exch def } { color 4 add /color exch def color 8 div color 15 div color 19 div setrgbcolor color 8 div s cvs show ( ) show } ifelse } def 300 300 translate -72 -72 moveto 72 -72 lineto 72 72 lineto -72 72 lineto -72 -72 lineto -100 -100 lineto 100 -100 lineto 100 100 lineto -100 100 lineto -100 -100 lineto { % moveto回调:只更新当前起点,不绘制 /cur_y exch def /cur_x exch def } { % lineto回调:拿到终点坐标,单独画这一段 /end_y exch def /end_x exch def #NextColor newpath cur_x cur_y moveto end_x end_y lineto stroke % 更新起点为当前段终点 /cur_x end_x def /cur_y end_y def } {/curveto load} % 贝塞尔段可以按同样逻辑拆分扩展 {/closepath load} % 闭合段需要额外记录子路径起点做闭合 pathforall % 遍历完不需要再统一stroke,所有段已经逐段画完了
注意点
- 逐段绘制时记得每段画完都更新当前起点坐标,不然段之间会出现断连或者错连
- 如果需要处理曲线、闭合路径,只需要在对应回调里拿到控制点坐标,单独构造单段的曲线路径再stroke即可,逻辑和直线段一致
- 不要在pathforall的回调里操作原遍历的路径,所有绘制操作都用单独的临时路径(每次画之前newpath),就不会触发路径锁定的限制
内容的提问来源于stack exchange,提问作者aRA
相关产品推荐
相关产品推荐

