在Postcript中使用可执行数组将多个值压入堆栈

问题描述 投票:1回答:3

我正在用Postscript做一些表格,有时我需要将当前点保存到变量中,因此以后我可以方便地将x y值放在堆栈上以进行moveto。这不是那么简单。我正在寻找一个将x和y都存储到一个变量中的过程。

假设您现在是72720。我希望一个变量,例如CP,能够存储两者。当然,如果您想存储

/cp {72 720} def

并且您将创建一个过程,该过程在被调用时将使堆栈中包含72720。但是,如果要在执行期间存储任意位置该怎么办?以下代码不起作用。

/cp {currentpoint} def
72 720 moveto
cp 
100 100 moveto
cp

该代码每次都仅调用currentpoint,在堆栈上保留72 720 100 100。

您如何创建一个将当前点捕获到一个变量中的过程,该变量将在运行时确定的堆栈上放置两个值?

postscript
3个回答
2
投票

以下将在运行时创建一个过程,该过程将在调用时将两个值放到堆栈中:

72 720 moveto
/cp [ currentpoint ] cvx def
cp
100 100 moveto
cp

这将在堆栈上保留72 720 72 720。发生的情况是cp的定义首先用两个值填充数组。它可以执行,因此,在调用cp时,无论当前点的位置如何更改,每次调用时,两个存储的值都被压入堆栈。

当然,此实用程序不只是到达一个明确的点,而是在执行期间捕获一个点。如果代码片段是

72 720 moveto
(Begin with, end with) show
/cp [ currentpoint ] cvx def

% intervening code ...

cp moveto
(, whatever!) show

然后,此功能的用途更加明显。

请注意,要使其正常工作,必须存在一个当前点。在问题部分,可以执行过程{currentpoint},因为执行被推迟了。但是,如果在没有当前点的情况下调用currentpoint,将导致后记错误。接下来是一个简短的脚本程序来探索这一点。

%!
/fontsize 14 def
/lineheight 16 def

/Times-Roman findfont fontsize scalefont setfont

/newline 
   {72 currentpoint exch pop lineheight sub
    dup 72 lt {showpage pop 720} if
    moveto
    } def

/cp2 { currentpoint } def

72 720 moveto
/cp1 [ currentpoint ] cvx def
cp1
cp2
(Test line) show
cp1
cp2

144 500 moveto
cp1
cp2
/cp1 [ currentpoint ] cvx def
cp1
cp2

(Test line) stringwidth

newline 
(-top of stack-) show 
newline
count {30 string cvs show newline} repeat
(-bottom of stack-) show newline

showpage

我在互联网上搜索了许多参考文献以弄清楚这一点,但是什么也没看到。我曾试图将x和y值存储在单独的变量中,但是这种方法的精巧之处使我想出了这种方法。如果有人知道这是使用某个关键字解决的主题,请告诉我们。


1
投票

您可以做这样的事情。如果您打算定义自己的函数,则应首先定义自己的字典,然后开始将其放在字典堆栈的顶部

在字典中定义一个2元素数组cpa以容纳x,y定义/cp将当前点存储到数组中。定义/CP以从数组中还原当前点

    /mydict 100 dict def
    mydict begin

    /cpa {2 array} def
    /cp {/cpa currentpoint cpa astore def}  def
    /CP { cpa aload pop moveto } def

%test out the functions
    123 456 moveto %move to a point
    cp             %save that point

    986 654 moveto %move to a different point
    CP             %restore the saved point
    (Currentpoint ) == currentpoint exch == ==  %print out the current 

您可能还想阅读gsave / grestore并保存/恢复。这些也许是您真正追求的。


1
投票

虽然我在这里喜欢(并赞成)其他两个答案,但我对同一想法略有改动,这说明了一些有趣的小角落,IMO。

您可以定义相同的数组两次,使一个引用文字和另一个可执行文件。重用相同的数组而不是丢弃和分配新的数组要稍微优雅一点。

/cpa 2 array def           % literal array for storing
/cpx cpa cvx def           % executable version of same array for spilling on the stack

currentpoint cpa astore pop  % save currentpoint

cpx moveto                 % return to currentpoint

现在,如果您使用缩放,旋转,平移中的任何一个更改了当前的转换矩阵(CTM),这将不起作用。对于更通用的解决方案,您需要transform到设备坐标(相对于用户空间stable),然后再使用itransform即可。这导致以下结果。

/cpa 2 array def           % literal array for storing
/cpx cpa cvx def           % executable version of same array
/cps { currentpoint transform cpa astore pop } def   % save currentpoint
/cpr { cpx itransform moveto } def                   % return to currentpoint

即使CTM已更改,这也会使您返回相同的设备位置。

© www.soinside.com 2019 - 2024. All rights reserved.