-
Notifications
You must be signed in to change notification settings - Fork 375
/
Copy pathPSL_text.ps
260 lines (248 loc) · 9.62 KB
/
PSL_text.ps
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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
%-----------------------------------------------------------------------------
%- P. Wessel, version 1
%- Text justification for paragraphs. Invented via PostScript docs a long time ago.
%- Kept as separate file because it is easier to edit and see the logic here.
%- Knows about flush l,c,r and justified.
%- Knows about all GMT @ escapes, composites (but not in paragraph mode)
%- and underlining. No hyphenation. 1 page only.
%+ NOTE: No longer used directly as we build a static string in PSL_strings.h.
%+ However, this file is the original source as it may be simpler to see and
%+ edit the logic in this file than in the formatted static string.
%-----------------------------------------------------------------------------
/PSL_setfont { % Set Font, size, and color (if needed)
% Expects two arguments: Word flag and word index
/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 number
fn PSL_lastfn eq fz PSL_lastfz eq and not { % If fonts or sizes differ we must update
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 % Get color
fc PSL_lastfc ne { % Not the same, must update color
/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 { % Turn underline on before plotting text
/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
% Expects two arguments: Word flag and word index
/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 number
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, then 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 { % Related to underline showing text
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 {
% Expects one argument: the word index from stack
/k exch def % Gets word index
/flag PSL_flag k get def
k flag PSL_setfont
/sshow {ashow} def
PSL_col 0 eq { % First word on a new line
/PSL_t 0 def % 0 spaces before this word
flag 4 and 4 eq { % Flag says we must skip one TAB (here 4 spaces)
pr_char 0 ( ) ashow
} if
}
{ % Need to find spaces before this word
/f PSL_flag k 1 sub get def % f is the 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 (flagged with 8)
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
% Expects a word index from the stack
/k1 exch def % Get word index from stack
/k2 k1 1 add def % Index to the 2nd composite character
/char1 PSL_word k1 get def % First character
/char2 PSL_word k2 get def % Second character
/flag2 PSL_flag k2 get def % Second character flag
/w1 char1 stringwidth pop def % Width of first character
flag2 64 and 64 eq { % Here, 64 means we have a font change before the 2nd composite character
/fn2 PSL_fnt k2 get def % Get the other font array number
fz PSL_fontname fn2 get Y % Set font and size for the 2nd composite character
} if
/w2 char2 stringwidth pop def % Width of second character
/delta w1 w2 sub 2 div PSL_scale mul def % Adjust and center based on w1, w2
delta 0.0 gt {
/dx1 0 def
/dx2 delta def
}
{
/dx1 delta neg def
/dx2 0 def
} ifelse
dx1 0 G currentpoint
flag2 64 and 64 eq { % Must switch back to first composite character font and set it
/fn1 PSL_fnt k1 get def % Get initial font
fz PSL_fontname fn1 get Y % Set font and size
} if
pr_char 0 char1 PSL_show M % Place first character
delta 0 G % Adjust relative x to position for overprinting
flag2 64 and 64 eq { % Get 2nd font again
fz PSL_fontname fn2 get Y % Set font and size
} if
pr_char 0 char2 ashow % Place 2nd character
dx2 0 G % Adjust relative x to position after this composite glyph
}!
% 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 or place it:
/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 in the array
/i exch def % The current loop index
/thisflag PSL_flag i get def % Number of space chars to follow this word
i 0 eq { % At the first word
/PSL_t 0 def
/lastflag 0 def
}
{ /lastflag PSL_flag i 1 sub get def % Can get the previous flag
/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