后记 - 案例陈述的替代方法

Postscript - alternative approach for case statement

我偶尔会涉猎一下 postscript,这是我喜欢的一种古怪的语言,但我还算不上专家。

要生成这样的图表:

我写了一些代码,如下所示:

  % fontsize on stack

  label (Up) eq 
    { /Symbol exch selectfont (5) show }
    { label (Down) eq 
      { /Symbol exch selectfont (7) show }
      { label (Left) eq
        { /Symbol exch selectfont (4) show }
        { label (Right) eq
          { /Symbol exch selectfont (6) show }
          { label (bs) eq
            { /Symbol exch selectfont (4) show }
            { /Helvetica exch selectfont 
              label length 3 lt 
                { label show }
                {
                  label (/)              % (page/up) (/)
                  search                 % (up) (/) (page) true
                  {                      % (up) (/) (page) 
                    /Helvetica keyHeight 4.6 div selectfont
                    3 1 roll             % (page) (up) (/)
                    pop                  % (page) (up)
                    currentpoint         % (page) (up) 438 745
                    3 2 roll             % (page) 438 745 (up)
                    show                 % (page) 438 745 
                    moveto               % (page)
                    0 keyHeight 0.25 mul % (page) 0 11
                    rmoveto              % (page) 
                    show }               % 
                  { show } ifelse
                } ifelse 
            } ifelse
          } ifelse
        } ifelse
      } ifelse
    } ifelse
    ...
    (End)key (Page/Down)key 0.5 gap (7)(Home)key2 (8)(Up)key2 ...

我不喜欢嵌套的 if 语句和重复,但这是对解决方案的第一次快速尝试。我的第一个想法是我会使用另一种语言的案例陈述。对于 Postscript,我想我应该为标签名称对和相应的八进制字符代码选择合适的数据结构。也许是嵌套数组。

  [ [(Up) (5)]  [(Down) (7)] ... ]

但我不确定如何迭代这个并且仍然优雅地跟踪我是否需要在没有名称匹配时执行默认过程。

有什么好听的成语吗?

好的,现在我回到我的办公桌前了。与其自己回答这个问题,不如让我为您指出一个很好的资源,John Deubert 的 Acumen Training Journal:

如果您查看 2001 年 4 月的 PostScript 技术期刊,您会看到 John 对如何使用字典实现 case 语句的清晰描述。我建议这比使用数组更好,主要原因有两个,首先是能够简单地添加默认情况,其次是 'get' 和 'known' 运算符这一事实,正如 John 指出的那样,通常在 PostScript 解释器中进行高度优化,因为它们的使用非常频繁。

您可以针对此处的特定用例采用的另一种方法是定义组合字体。看起来大部分文本都是用 Helvetica 显示的,但有 select 少数是从 Symbol 借来的。 example program here 表示您可以 select 一种字体并在自定义 Type-3 字体的 BuildChar 过程中使用它。它可能仍然需要一个 case 语句来实现,但让实际应用程序使用起来更好。

这是草稿。

%lo-font threshold hi-font  .  <<derived font>>
/splitfont {
    4 dict begin {hi-font threshold lo-font}{exch def}forall
        /width .9 def 
    (<< 
        /FontType 3
        /FontBBox [ 0 0 //width 1 ] 
        /FontMatrix matrix
        /Encoding StandardEncoding % Lying to the postscript interpreter
        /BuildChar {
            %//width 0 0 0 //width 1 setcachedevice
            dup //threshold lt
                { //lo-font }{ //hi-font } ifelse
            1 selectfont
            (?)dup 0 4 3 roll put 
            dup stringwidth
            setcharwidth %2 index false charpath pathbbox setcachedevice
            show
            pop
        }
    >>) cvx exec
    end 
} def 

/Helv+Symb /Helvetica 8#254 /Symbol splitfont definefont pop 

/Helv+Symb 20 selectfont
100 100 moveto
(Text in Helvetica + 4567) show