13

我需要在 postscript 中确定字符串的高度(以给定的比例和字体)。

/Helvetic-Oblique findfont
10 scalefont
setfont
10 10 1 0 360 arc fill
10 10 moveto (test) dup stringwidth pop 2 div neg 0 rmoveto show

将在 (10,10) 水平(但尚未垂直)居中打印测试。(为了看到这一点,我还在 10,10 处显示了一个小圆圈)。我还需要确定字符串高度以使文本垂直居中,但我找不到它的函数。

4

4 回答 4

8

您熟悉您使用的 PostScript 代码吗?还是只是从某个地方盲目复制和粘贴?如果你想了解它,你应该在谷歌上搜索“PostScript Language Reference”或“Red Book”或“PLRM”。这些资源以 PDF 格式从 Adob​​e 提供。

您的 PostScript 片段使用以下步骤:

  1. (test)将字符串“test”放在堆栈的顶部。
  2. dup复制堆栈上最顶层的项目。(您现在将在堆栈上两次获得该字符串。)
  3. stringwidth. 执行此运算符后,将消耗最顶部的“测试”字符串,并将两个值添加到堆栈中:字符串的高度(最顶部)和字符串的宽度(从顶部开始的第二个)。[更新: 实际上,“字符串的高度”并不完全正确 - 它是完成绘制字符串后当前点的垂直偏移量...... ]
  4. 接下来,您使用pop. 这只是删除堆栈上的最高值。现在只有字符串的宽度保留在堆栈的顶部。
  5. 2 div将该值除以 2 并留下结果(字符串宽度的一半)。
  6. neg否定堆栈上的最高值。现在负值在堆栈的最顶端。
  7. 0将值“0”放在堆栈顶部。
  8. rmoveto然后消耗堆栈上的两个最高值并将当前点向左移动该距离(字符串宽度的一半)。
  9. show消耗第一个一直保留在堆栈底部的“测试”字符串并“显示”它。

那么考虑到字符串的高度有什么用呢?试试你的最后一行:

200 700 moveto (test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"

要了解我的更改,请查看The Red Book 中、 、 、charpathdiv运算exch符的含义。pathbboxrollsub

此命令使用 Ghostscript 从代码在 Windows 上创建 PDF 文件(更易于查看和检查结果):

 gswin32c.exe ^
      -o my.pdf ^
      -sDEVICE=pdfwrite ^
      -c "/Helvetic-Oblique findfont 10 scalefont setfont 200 700 1 0 360 arc fill 0 0 moveto (test test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"

在 Linux 上使用:

 gs \
      -o my.pdf \
      -sDEVICE=pdfwrite \
      -c "/Helvetic-Oblique findfont 10 scalefont setfont 200 700 1 0 360 arc fill 0 0 moveto (test test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"

更好的可读形式是:

  gswin32c ^
     -o my.pdf ^
     -sDEVICE=pdfwrite ^
     -c "/Helvetic-Oblique findfont 10 scalefont setfont" ^
     -c "200 700 1 0 360 arc fill 0 0 moveto (test test) dup" ^
     -c "true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll" ^
     -c "sub 2 div exch 200 700 moveto rmoveto show"

  gs \
     -o my.pdf \
     -sDEVICE=pdfwrite \
     -c "/Helvetic-Oblique findfont 10 scalefont setfont" \
     -c "200 700 1 0 360 arc fill 0 0 moveto (test test) dup" \
     -c "true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll" \
     -c "sub 2 div exch 200 700 moveto rmoveto show"
于 2010-09-06T23:23:17.480 回答
7

只需添加到pipitas答案:

/textheight { 
    gsave                                  % save graphic context
    {                            
        100 100 moveto                     % move to some point 
        (HÍpg) true charpath pathbbox      % gets text path bounding box (LLx LLy URx URy)
        exch pop 3 -1 roll pop             % keeps LLy and URy
        exch sub                           % URy - LLy
    }
    stopped                                % did the last block fail?
    {
        pop pop                            % get rid of "stopped" junk
        currentfont /FontMatrix get 3 get  % gets alternative text height
    }
    if
    grestore                               % restore graphic context
} bind def

/jumpTextLine { 
    textheight 1.25 mul                    % gets textheight and adds 1/4
    0 exch neg rmoveto                     % move down only in Y axis
} bind def

该方法要求已经设置了一些字体。它适用于选定的字体 ( setfont) 及其大小 ( scalefont)。

我使用 (HÍpg) 来获得最大的边界框,使用强调的大写字符和“下线”字符。结果已经足够好了。

另一种方法从dreamlax的答案中窃取——某些字体不支持charpath运算符。(请参阅如何在 PostScript 中获取字符串的高度度量?

保存和恢复图形上下文将当前点保持在原位,因此它不会影响文档的“流程”。

希望我有所帮助。

于 2011-08-19T13:31:20.390 回答
4

这是一个切题的答案,以补充 pipitas 的深入解释。

此过程定位并显示以指定点为中心的字符串。

/ceshow { % (string) fontsize fontname x y
    gsave
        moveto findfont exch scalefont setfont % s
        gsave
            dup false charpath flattenpath pathbbox % s x0 y0 x1 y1
        grestore
        3 -1 roll sub % s x0 x1 dy
        3 1 roll sub % s dy -dx
        2 div exch % s -dx/2 dy
        -2 div % s -dx/2 -dy/2
        rmoveto show
    grestore
} bind def
于 2011-09-15T03:04:25.290 回答
2

使用带有 dingbat 字体的上述程序,我得到了可怕的结果,然后我意识到他们假设文本将真正从当前点开始,在某些情况下,这非常不准确。

我的解决方案还依赖于pathbbox计算宽度和高度,但它也首先使用 X0 和 Y0 到达原点。

%-- to make things nicer
/hmoveto { 0 rmoveto } def
/vmoveto { 0 exch rmoveto } def
%-- cshow means something else...
/ccshow {
    dup %-- charpath consumes the string
    gsave
    newpath %-- else there's a strange line somewhere
    0 0 moveto
    true charpath flattenpath pathbbox
    grestore
    2 index sub -2 div vmoveto
    2 index sub -2 div hmoveto
    neg vmoveto
    neg hmoveto
    show
} def
于 2016-05-29T23:18:05.380 回答