【问题标题】:How to determine string height in PostScript?如何确定 PostScript 中的字符串高度?
【发布时间】:2016-05-30 07:30:15
【问题描述】:

我需要确定 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 处显示了一个小圆圈)。我还需要确定字符串高度以使文本垂直居中,但我找不到它的函数。

【问题讨论】:

    标签: postscript ghostscript


    【解决方案1】:

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

    您的 PostScript sn-p 使用以下步骤:

    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"
    

    要了解我的更改,请查看红皮书中 charpathdivexchpathbboxrollsub 运算符的含义。

    此命令使用 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"
    

    【讨论】:

    • charpath 的文档说它不包括图像或掩码的字形的任何部分。是否有包含这些类型肢体的增强功能?
    【解决方案2】:

    只是添加到 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 运算符。 (见How can you get the height metric of a string in PostScript?

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

    希望我有所帮助。

    【讨论】:

    • 此外,您可以使用currentfont /FontBBox get 作为边界框,而不是使用charpath pathbbox 来获取它...在我的情况下,它在GhostScript 下完美运行;然而,当被打印机解释时,结果并不好。
    【解决方案3】:

    这是一个切题的答案,以补充 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
    

    【讨论】:

      【解决方案4】:

      我使用 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
      

      【讨论】:

        猜你喜欢
        • 2012-01-07
        • 1970-01-01
        • 1970-01-01
        • 2021-04-20
        • 1970-01-01
        • 2013-05-24
        • 1970-01-01
        • 2021-02-18
        • 2011-09-08
        相关资源
        最近更新 更多