PostScript中如何隐藏charpath轮廓?求Y轴绘制优雅方案
关于PostScript绘制Y轴的两个问题:隐藏charpath轮廓与优雅实现方案
我现在有一段用于生成图表Y轴的PostScript代码:
%!PS /Helvetica 20 selectfont 200 200 translate 0 50 200 { dup dup dup 0 exch moveto 20 0 rlineto stroke 0 exch moveto ( ) cvs true charpath pathbbox 3 1 roll 4 1 roll sub -2.4 div 3 1 roll sub -2 mul 10 sub exch rmoveto ( ) cvs show } for
我的需求是仅通过charpath获取文本的边界框来实现文本对齐,但charpath生成的轮廓会被显示出来,请问如何避免这个情况?另外,我也希望得到绘制Y轴的更优雅的解决方案。
一、防止charpath轮廓被显示的方法
charpath会将文本转换为当前路径,要避免这个路径被后续渲染,只需在调用charpath并获取到pathbbox后,立即用newpath清空当前路径即可。因为pathbbox仅读取路径的边界信息,不会修改路径状态,清空路径后就不会影响后续的绘图操作。
修改后的关键代码片段:
0 exch moveto ( ) cvs true charpath pathbbox % 获取边界框,此时路径仍存在 newpath % 清空路径,避免后续被渲染
二、更优雅的Y轴绘制方案
原代码存在重复调用dup、多次cvs转换的冗余问题,通过封装过程、简化栈操作、明确参数定义可以大幅优化:
优化后的完整代码
%!PS % 封装获取文本宽度和高度的过程 /TextBBox { gsave % 保存当前图形状态(字体、变换等) charpath % 将文本转为路径 pathbbox % 获取边界框:llx lly urx ury sub exch sub % 计算宽度(urx-llx)和高度(ury-lly) grestore % 恢复图形状态 } bind def % 初始化参数 /Helvetica 20 selectfont 200 200 translate % 坐标系原点移到(200,200) /yStart 0 def /yEnd 200 def /yStep 50 def /tickLength 20 def % Y轴刻度线长度 /textOffset 10 def % 文本与刻度线的偏移量 % 绘制Y轴主轴线 0 yStart moveto 0 yEnd lineto stroke % 绘制刻度和标签 yStart yStep yEnd { % 绘制刻度线 0 exch moveto tickLength 0 rlineto stroke % 生成刻度文本并计算对齐偏移 dup cvs % 将数值转为字符串 dup TextBBox % 获取文本宽度和高度 /textWidth exch def /textHeight exch def % 计算文本位置:左对齐,垂直居中于刻度线 tickLength textOffset add neg % X方向偏移:刻度线左侧+偏移量 exch textHeight -2 div add % Y方向偏移:垂直居中 moveto show % 绘制文本 } for
优化点说明
- 封装复用:将文本边界框计算封装为
TextBBox过程,代码更简洁可复用,同时用gsave/grestore避免影响全局路径状态。 - 参数清晰:将刻度长度、文本偏移等常量单独定义,后续调整参数更方便。
- 逻辑简化:避免原代码中复杂的栈旋转操作,对齐逻辑更直观易懂。
- 对齐精准:直接计算文本的垂直居中与左对齐位置,替代原代码中模糊的数值计算。
内容的提问来源于stack exchange,提问作者NicolasBourbaki
相关产品推荐
相关产品推荐

