1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
%- $Id$
%-----------------------------------------------------------------------------
%- P. Wessel, version 1
%- Text justification for paragraphs.
%- Kept as separate file until stable.
%- Knows about flush l,c,r and justified.
%- Knows about all GMT @ escapes, composites,
%- and underlining. No hyphenation. 1 page only.
%-----------------------------------------------------------------------------
/PSL_setfont { % Set Font, size, and color if needed
/f exch def % Gets word flag from stack
/k1 exch def % Gets word index from stack
/fz PSL_size k1 get def % Get font size
/fn PSL_fnt k1 get def % Get font
fn PSL_lastfn eq fz PSL_lastfz eq and not {
fz PSL_fontname fn get Y % Set font and size
/PSL_lastfn fn def
/PSL_lastfz fz def
} if
/fc PSL_color k1 get def
fc PSL_lastfc ne {
/PSL_c fc 3 mul def
0 1 2 {PSL_c add PSL_rgb exch get} for C % Get and set color
/PSL_lastfc fc def
} if
f 32 and 32 eq { % Underline
/PSL_UL fz 0.075 mul def
fz 0.025 mul W
/PSL_show {PSL_ushow} def
}
{
/PSL_show {ashow} def
} ifelse
}!
/PSL_setfont2 { % Only set font and size
/f exch def % Gets word flag from stack
/k1 exch def % Gets word index from stack
/fz PSL_size k1 get def % Get font size
/fn PSL_fnt k1 get def % Get font
fn PSL_lastfn eq fz PSL_lastfz eq and not {
fz PSL_fontname fn get Y % Set font and size
/PSL_lastfn fn def
/PSL_lastfz fz def
} if
}!
/PSL_wordheight { % Gets word from stack, and calculates any adjustment to box height
0 0 M false charpath flattenpath pathbbox /up exch def pop /down exch def pop newpath
down PSL_ymin lt {/PSL_ymin down def} if
up PSL_ymax gt {/PSL_ymax up def} if
}!
/PSL_ushow {
currentpoint /y0 exch def /x0 exch def
ashow
currentpoint pop /x1 exch def
x0 y0 PSL_UL sub M x1 y0 PSL_UL sub L S
x1 y0 M
}!
% Set font, size, and color. Adjust baseline if needed. Place space and word
/PSL_placeword {
/k exch def % Gets word index from stack
/flag PSL_flag k get def
k flag PSL_setfont
/sshow {ashow} def
PSL_col 0 eq { % First word on a line
/PSL_t 0 def % 0 spaces before this word
flag 4 and 4 eq { % Must skip one TAB
pr_char 0 ( ) ashow
} if
}
{ % Need to find spaces before this word
/f PSL_flag k 1 sub get def % f is flag for previous word
/PSL_t f 3 and def % PSL_t is index into PSL_spaces and PSL_spacewidths for previous word
f 32 and 32 eq flag 32 and 32 eq and {/sshow {PSL_ushow} def} if
} ifelse
/thisword_bshift PSL_bshift k get def % The baseline shift
thisword_bshift 0.0 ne {0 thisword_bshift G} if % Shift baseline
flag 8 and 8 eq { % First composite char
pr_char 0 PSL_spaces PSL_t get sshow
k PSL_composite
} if
flag 24 and 0 eq { % Anything but composite chars
pr_char 0 PSL_spaces PSL_t get sshow pr_char 0 PSL_word k get PSL_show
PSL_width k get 0 gt {/PSL_col PSL_col 1 add def} if
} if
thisword_bshift 0.0 ne {0 thisword_bshift neg G} if % Shift baseline
}!
/PSL_composite { % Place a composite character
/k1 exch def % Get word index from stack
/k2 k1 1 add def
/char1 PSL_word k1 get def
/char2 PSL_word k2 get def
/w1 char1 stringwidth pop def
/w2 char2 stringwidth pop def
/delta w1 w2 sub 2 div PSL_scale mul def
delta 0.0 gt {
/dx1 0 def
/dx2 delta def
}
{ /dx1 delta neg def
/dx2 0 def
} ifelse
dx1 0 G currentpoint
pr_char 0 char1 PSL_show M
delta 0 G
pr_char 0 char2 ashow
dx2 0 G
}!
% Determine how much to expand text and also justify left/center/right
/PSL_expand {
/k1 exch def % Get word index from stack
/extra PSL_parwidth previous_linewidth sub comp_width add def
PSL_CRLF k1 PSL_n1 eq or {/spread 0 def} {/spread extra def} ifelse
/PSL_scale previous_linewidth 0.0 gt {PSL_parwidth previous_linewidth div} {1.0} ifelse def
/ndiv lsum ncomp sub def
ndiv 0 eq {/ndiv 1 def} if
PSL_parjust 4 eq {/pr_char spread ndiv div def} {/pr_char 0 def} ifelse
PSL_parjust 2 eq {extra 2 div 0 G} if
PSL_parjust 3 eq {extra 0 G} if
/PSL_col 0 def
}!
% Calculate text paragraph height:
/PSL_textjustifier {
/PSL_mode exch def % From stack. 0 -> calculate height, no text is placed, 1 -> place text
/PSL_col 0 def
/PSL_ybase 0 def
/PSL_parheight 0 def
/PSL_ymin 0 def
/PSL_ymax 0 def
/PSL_top 0 def
/PSL_bottom 0 def
/last_font PSL_fnt 0 get def % The previous font number
/last_size PSL_size 0 get def % The previous font size
/last_color PSL_color 0 get def % The previous color index
/previous_linewidth 0 def
/stop 0 def
/start 0 def
/lsum 0 def
/line 0 def
/ncomp 0 def
/comp_width 0 def
0 1 PSL_n1 { % Loop over all the words
/i exch def % The current loop index
/thisflag PSL_flag i get def % # of space chars to follow this word
i 0 eq {
/PSL_t 0 def
/lastflag 0 def
}
{ /lastflag PSL_flag i 1 sub get def
/PSL_t lastflag 3 and def
} ifelse
% PSL_t is index into PSL_spaces and PSL_spacewidths
i thisflag PSL_setfont2 % Get and set font and size
/thisword_width PSL_width i get def
/comp_add 0 def
/compw_add 0 def
/PSL_tabwidth ( ) stringwidth pop def % Get width of the TAB
/PSL_spacewidths PSL_spaces {stringwidth pop} forall 3 array astore def % and the spaces
/ccount PSL_count i get def % # of characters in this word
thisflag 4 and 4 eq { % Had leading tab
/thisword_width thisword_width PSL_tabwidth add def
/ccount ccount 4 add def
} if
lastflag 8 and 8 eq {/PSL_t 0 def /comp_add 1 def /compw_add thisword_width def} if
/new_linewidth previous_linewidth thisword_width add PSL_spacewidths PSL_t get add def % Width of line if word added
/PSL_CRLF thisword_width 0.0 eq thisflag 16 and 0 eq and def
/special thisflag 16 and 16 eq {true} {thisword_width 0.0 gt} ifelse def
new_linewidth PSL_parwidth le special and
{ % Word will fit on current line
PSL_col 0 eq {
/PSL_ymin 0 def
/PSL_ymax 0 def
} if
/stop stop 1 add def % Include this word
/PSL_col PSL_col 1 add def % Column place of next word
/previous_linewidth new_linewidth def % Update the unadjusted line width
/lsum lsum ccount add PSL_t add def % Update character count
/ncomp ncomp comp_add add def
/comp_width comp_width compw_add add def
}
{ % Must process current line and move to next
1 PSL_mode eq { % Write out the first word on this line
% Determine how much to expand text and also justify left/center/right
start PSL_expand
start PSL_placeword
}
{PSL_word start get PSL_wordheight
} ifelse
/last stop 1 sub def
/start start 1 add def
1 PSL_mode eq { % Write out the remaining words on this line
start 1 last {PSL_placeword} for
}
{start 1 last {PSL_word exch get PSL_wordheight} for
line 0 eq { /PSL_top PSL_ymax def} if % First outputline
} ifelse
/start stop def
/PSL_ybase PSL_ybase PSL_linespace sub def
1 PSL_mode eq {0 PSL_ybase M} if % CR/LF
/stop stop 1 add def % Include this word
/previous_linewidth thisword_width def
/lsum ccount def
/ncomp comp_add def
/comp_width compw_add def
/PSL_col 0 def
/line line 1 add def
} ifelse
} for
/last stop 1 sub def
last PSL_n lt { % One or more words left hanging on last line
/PSL_CRLF true def
1 PSL_mode eq {
% Determine how much to expand text and also justify left/center/right
start PSL_expand
start PSL_placeword
/start start 1 add def
start 1 last {PSL_placeword} for
}
{ /PSL_ymin 0 def
PSL_word start get PSL_wordheight
/start start 1 add def
start 1 last {PSL_word exch get PSL_wordheight} for
line 0 eq { % First outputline
/PSL_top PSL_ymax def
} if
} ifelse
} if
/PSL_bottom PSL_ymin def
/PSL_parheight PSL_ybase neg PSL_top add PSL_bottom sub def
} def % PSL_textjustifier
|