我有一个可以接受文本输入的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部分,我想要包装文本/剪切它并添加一个省略号。我该怎么做?它有功能吗?
答案 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