如何使用postscript对文本进行包装或省略?

时间:2014-10-20 02:47:30

标签: postscript textwrapping ellipsis

我有一个可以接受文本输入的postscript代码。我想在文本达到特定长度时包装文本或添加省略号,但我不知道该怎么做。

%%% A4 size
<< /PageSize [595 842] >> setpagedevice
clippath pathbbox /ury exch def /urx exch def /lly exch def /llx exch def

%%% Unit
/cm { 72 2.54 div mul } bind def

%%% Temporary
/Fix_long 4.2 cm def
/Fix_short 3.2 cm def
%%% Set Image Scale
/SetFixScale { 2 copy gt { Fix_long Fix_short }{ Fix_short Fix_long  }ifelse scale } bind def

%%% Set put coordinate
/SetXAdjust { 2 copy gt 
{ X_Step Fix_long sub 2 div floor }
{ Fix_long Fix_short sub 2 div} ifelse /XAdjust exch def 
} bind def
 /YAdjust 2 cm def
%%% Temporary
/Row 4 def
/Column 3 def
/X_Step urx llx sub Row div floor def
/Y_Step ury lly sub Column div floor  def
/Row_pos 0 def
/Column_pos 1 def
/SetPutPosition { 
llx X_Step Row_pos mul add 
ury Y_Step Column_pos mul sub translate
DrawFrame
DrawFileName
XAdjust YAdjust translate
Row 1 sub Row_pos eq { /Row_pos 0 def /Column_pos Column_pos 1 add def }{ /Row_pos Row_pos 1 add def } ifelse  
Column_pos Column gt { /Column_pos 1 def } if
} bind def

/DrawFrame { gsave .5 setlinewidth 0 0 X_Step Y_Step rectstroke grestore } bind def
/DrawFileName { 15 15 moveto 4 -1 roll show } bind def

在/ DrwaFileName部分,我想要包装文本/剪切它并添加一个省略号。我该怎么做?它有功能吗?

1 个答案:

答案 0 :(得分:3)

没有内置函数,所以你必须做一些字符串处理。至少有两种方法取决于您想要测量“长度”的方式。

对于更简单的情况,我们将“length”视为字符数。 postscript运算符length将返回字符串中的字符数。所以从你的功能开始,

/DrawFileName { 15 15 moveto 4 -1 roll   show } bind def
%                                      ^
% we'll insert our code here, ---------|
% where the string is on top of the stack,
% replacing the call to show

首先根据我们想要允许的最大尺寸检查现有长度。

dup length 10 gt {
}{
    show
} ifelse

如果长度不大于10, else -clause只需调用show。接下来我们将填写然后 -clause来修剪字符串。

dup length 10 gt {
    0 10 getinterval
    show
}{
    show
} ifelse

嗯,我不打算谈论优化,但我们现在可以考虑这个因素。在添加省略号部分之前。这两种情况都会调用show,因此我们只需在ifelse结构之外调用一次。

dup length 10 gt {
    0 10 getinterval
}{
} ifelse
show

当然,现在我们不需要ifelse,因为 else -clause是空的。

dup length 10 gt {
    0 10 getinterval
} if
show

那更好。现在,对于省略号,我们可以使用putinterval运算符从一个字符串复制到另一个字符串。

dup length 10 gt {
    0 10 getinterval
    dup 7 (...) putinterval
} if
show

编辑:当然,由于postscript是一种图形语言,我们可能会对页面上字符串的排版长度感兴趣。为此,stringwidth运算符返回currentpoint调用show后将移动的金额。因此,如果您只是将show的调用替换为stringwidth rmoveto,则会留下适当大小的间隙,但不会设置任何文本。所以,回到开始,将呼叫替换为show,即。假设我们的代码片段开头的堆栈顶部有一个字符串。

dup stringwidth pop 50 gt {
} if
show

对于西方字母,stringwidth返回的 dy 值将始终为0.由于上下文是文件名,因此这似乎是一个安全的假设。我们只需pop,然后将 dx 结果与50个用户空间点进行比较。

现在,如果它太长了怎么办?在哪里切?这是需要考虑的事情。做一个思考的脸。 Hmmph。如果我们认为我们也在这里添加省略号,我们想从字段宽度中减去它,并将字符串剁到它的左边。所以我的计划是逐字符循环字符串并检查并显示每个字符串,将省略号字符串留在堆栈中以获得最终show。这是部分填写。

dup stringwidth pop 50 gt {      % str
    50 (...) stringwidth pop sub % str Max      new maximum length
    exch                         % Max str
    { % Max c                               forall yields the integer value
        ( ) dup 0 4 3 roll put   % Max (c)    put it back in a string
        dup stringwidth pop      % Max (c) dx 
        2 index 2 copy lt        % Max (c) dx Max dx<Max?
        {                        % Max (c) dx Max      dx<Max
        }{                       % Max (c) dx Max      dx>=Max
        } ifelse
    } forall
    (...)
} if
show

循环遍历每个字符,检查字符串宽度,与最大值进行比较。如果小于max,我们希望继续显示字符串,并从max减去宽度。 如果不是,我们想要清理堆栈并退出循环。

dup stringwidth pop 50 gt {      % str
    50 (...) stringwidth pop sub % str Max      new maximum length
    exch                         % Max str
    { % Max c                               forall yields the integer value
        ( ) dup 0 4 3 roll put   % Max (c)    put it back in a string
        dup stringwidth pop      % Max (c) dx 
        2 index 2 copy lt        % Max (c) dx Max dx<Max?
        {                        % Max (c) dx Max      dx<Max
            exch sub             % Max (c) Max-dx
            3 1 roll exch pop    % Max-dx (c)
            show                 % Max-dx
        }{                       % Max (c) dx Max      dx>=Max
            pop pop pop pop exit
        } ifelse
    } forall
    (...)   % place (...) on stack for show
} if
show

我认为这应该可以胜任。

对于包装文字,我们已经把自己画成了一个角落。字符串的其余部分需要由剩余的迭代收集,然后重新组装成一个字符串,然后再重复整个混乱。让我考虑一下。 ...

或者它可以将当前点重新定位在循环中间。使用X坐标和Y增量(或者减少,实际上,因为我们可能正在向下移动页面)。像

这样的东西
currentpoint exch pop % currentY
X exch                % X currentY
dY sub                % X currentY-dY
moveto