通过计算SpaceMod并使用PostScript
来证明widthhow
中的一行是正确的:
/SpaceMod % calculated from line width and stringwidth
/h { 0 32 } def
/Times-Roman findfont
14 scalefont setfont
SpaceMod h (This line with single font is justified) widthshow
但是我们如何将这种方法用于具有不同字体的行?一个简单的例子就是在行中加上粗体部分
/Times-Roman findfont
14 scalefont setfont
X h (How to) widthshow
/Times-Roman-Bold findfont
14 scalefont setfont
X h justify this line) widthshow
/Times-Roman findfont
14 scalefont setfont
X h (with multi fonts) widthshow
问题是我们没有一个字符串可供整行获取stringwidth
。即使根据单个字符串计算它,我们如何计算/设置SpaceMod?
或者我们需要使用另一种方法来证明多行字体的行?
答案 0 :(得分:2)
蛮力..
/justifyshow {
/linerem exch def
dup length 3 idiv /nsub exch def
/instring exch def
instring aload pop
/spct 0 def
/setf {3 2 roll findfont 3 2 roll scalefont setfont } def
nsub {
setf dup
stringwidth pop linerem exch sub /linerem exch def
{32 eq { spct 1 add /spct exch def} if } forall
} repeat
/addsp linerem spct div def
instring aload pop
%cleanup
[ /spct /linerem /instring ] { userdict exch undef } forall
% comment following three lines to reverse argument order
/ct nsub def
nsub 1 sub { ct 1 sub /ct exch def ct 1 add 3 mul 3 roll } repeat
userdict /ct undef
%
nsub { setf addsp 0 32 4 -1 roll widthshow } repeat
} def
% usage [ fontn sizen stringn ... font1 size1 string1 ]
% linewidth justifyshow
100 100 moveto
[
/Helvetica 12 (hot to justify)
/HelveticaBold 24 ( large bold)
/Helvetica 12 ( in part of a line)
] 400 justifyshow
毫无疑问,这可以收紧一点......
编辑,正如我所说的那样收紧了一点。
% count spaces in a string
/stringspace {0 exch { 32 eq { 1 add } if} forall} def
% set font routine
/setf {3 2 roll findfont 3 2 roll scalefont setfont } def
/justifyshow {
% def array length leave line length and array on stack
exch dup length 3 idiv /nsub exch def
aload pop
% split input array into array of [ font size string ] arrays
/incc nsub 3 mul 1 add def
[ nsub { incc 1 roll [ 4 1 roll ] incc 3 sub /incc exch def } repeat ] /fstringlist exch def
% reverse sort string order (can comment out this line if needed )
[ nsub 1 sub -1 0 { fstringlist exch get} for ] /fstringlist exch def
% count spaces
0 fstringlist {aload pop 3 1 roll pop pop stringspace add } forall
% count total line length
0 fstringlist {aload pop setf stringwidth pop add } forall
% at this point the target length, actuial length and space count are on the stack
% calculate space to add
3 -1 roll sub neg exch div /addsp exch def
% show strings
fstringlist { aload pop setf addsp 0 32 4 -1 roll widthshow } forall } def
100 100 moveto
[
/Helvetica 12 (how to justify)
/HelveticaBold 24 ( large bold)
/Helvetica 12 ( in part of a line)
/Helvetica 50 ( !!!)
] 400
justifyshow