Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | structure Postscript: POSTSCRIPT = | |
9 | struct | |
10 | ||
11 | nonfix mod div | |
12 | ||
13 | structure Char = | |
14 | struct | |
15 | open Char | |
16 | ||
17 | fun escapePostscript c = | |
18 | if isPrint c | |
19 | then (case c of | |
20 | #"\\" => "\\\\" | |
21 | | #"(" => "\\(" | |
22 | | #")" => "\\)" | |
23 | | _ => toString c) | |
24 | else escapeC c | |
25 | end | |
26 | ||
27 | structure String = | |
28 | struct | |
29 | open String | |
30 | ||
31 | fun escapePostscript s = translate(s, Char.escapePostscript) | |
32 | end | |
33 | ||
34 | ||
35 | datatype t = | |
36 | (* Atoms *) | |
37 | int of real | |
38 | | real of real | |
39 | | string of string | |
40 | | literal of string | |
41 | (* Operators *) | |
42 | | abs | |
43 | | add | |
44 | | arc | |
45 | | arcn | |
46 | | arct | |
47 | | arcto | |
48 | | ashow | |
49 | | atan | |
50 | | awidthshow | |
51 | | ceiling | |
52 | | charpath | |
53 | | clear | |
54 | | cleartomark | |
55 | | clip | |
56 | | clippath | |
57 | | cliprestor | |
58 | | clipsave | |
59 | | closepath | |
60 | | colorimage | |
61 | | composefont | |
62 | | copy | |
63 | | copypage | |
64 | | cos | |
65 | | count | |
66 | | counttomark | |
67 | | cshow | |
68 | | currentcolor | |
69 | | currentcolorspace | |
70 | | currentdash | |
71 | | currentfont | |
72 | | currentglobal | |
73 | | currentgray | |
74 | | currentgstate | |
75 | | currenthsbcolor | |
76 | | currentlinecap | |
77 | | currentlinejoin | |
78 | | currentlinewidth | |
79 | | currentmiterlimit | |
80 | | currentmykcolor | |
81 | | currentpagedevice | |
82 | | currentpoint | |
83 | | currentrgbcolor | |
84 | | currentstrokeadjust | |
85 | | curveto | |
86 | | definefont | |
87 | | defineuserobject | |
88 | | div | |
89 | | dup | |
90 | | eoclip | |
91 | | eofill | |
92 | | erasepage | |
93 | | exch | |
94 | | execuserobject | |
95 | | exp | |
96 | | fill | |
97 | | findfont | |
98 | | flattenpath | |
99 | | floor | |
100 | | font | |
101 | | forall | |
102 | | gcheck | |
103 | | glyphshow | |
104 | | grestore | |
105 | | grestoreall | |
106 | | gsave | |
107 | | gstate | |
108 | | idiv | |
109 | | image | |
110 | | imagemask | |
111 | | index | |
112 | | initclip | |
113 | | initgraphics | |
114 | | kshow | |
115 | | lineto | |
116 | | ln | |
117 | | log | |
118 | | makefont | |
119 | | mark | |
120 | | mod | |
121 | | moveto | |
122 | | mul | |
123 | | neg | |
124 | | newpath | |
125 | | nulldevice | |
126 | | pathbbox | |
127 | | pathforall | |
128 | | pop | |
129 | | rand | |
130 | | rcurveto | |
131 | | rectclip | |
132 | | rectfill | |
133 | | rectstroke | |
134 | | restore | |
135 | | reversepath | |
136 | | rlineto | |
137 | | rmoveto | |
138 | | roll | |
139 | | rootfont | |
140 | | round | |
141 | | rrand | |
142 | | save | |
143 | | scalefont | |
144 | | selectfont | |
145 | | setbbox | |
146 | | setcolor | |
147 | | setcolorspace | |
148 | | setdash | |
149 | | setfont | |
150 | | setglobal | |
151 | | setgray | |
152 | | setgstate | |
153 | | sethsbcolor | |
154 | | setlinecap | |
155 | | setlinejoin | |
156 | | setlinewidth | |
157 | | setmiterlimit | |
158 | | setmykcolor | |
159 | | setpagedevice | |
160 | | setrgbcolor | |
161 | | setstrokeadjust | |
162 | | shfill | |
163 | | show | |
164 | | showpage | |
165 | | sin | |
166 | | sqrt | |
167 | | srand | |
168 | | startjob | |
169 | | stringwidth | |
170 | | stroke | |
171 | | strokepath | |
172 | | sub | |
173 | | truncate | |
174 | | uappend | |
175 | | ucache | |
176 | | ueofill | |
177 | | ufill | |
178 | | undefinefont | |
179 | | undefineuserobject | |
180 | | upath | |
181 | | userobjects | |
182 | | ustroke | |
183 | | ustrokepath | |
184 | | widthshow | |
185 | | xshow | |
186 | | xyshow | |
187 | | yshow | |
188 | ||
189 | fun tildeToMinus s = | |
190 | String.translate(s, fn #"~" => "-" | c => Char.toString c) | |
191 | ||
192 | val toString = | |
193 | fn int r => tildeToMinus(Int.toString(Real.round r)) | |
194 | | real r => tildeToMinus(Real.toString r) | |
195 | | string s => concat["(", String.escapePostscript s, ")"] | |
196 | | literal s => concat["/", s] | |
197 | | abs => "abs" | |
198 | | add => "add" | |
199 | | arc => "arc" | |
200 | | arcn => "arcn" | |
201 | | arct => "arct" | |
202 | | arcto => "arcto" | |
203 | | ashow => "ashow" | |
204 | | atan => "atan" | |
205 | | awidthshow => "awidthshow" | |
206 | | ceiling => "ceiling" | |
207 | | charpath => "charpath" | |
208 | | clear => "clear" | |
209 | | cleartomark => "cleartomark" | |
210 | | clip => "clip" | |
211 | | clippath => "clippath" | |
212 | | cliprestor => "cliprestor" | |
213 | | clipsave => "clipsave" | |
214 | | closepath => "closepath" | |
215 | | colorimage => "colorimage" | |
216 | | composefont => "composefont" | |
217 | | copy => "copy" | |
218 | | copypage => "copypage" | |
219 | | cos => "cos" | |
220 | | count => "count" | |
221 | | counttomark => "counttomark" | |
222 | | cshow => "cshow" | |
223 | | currentcolor => "currentcolor" | |
224 | | currentcolorspace => "currentcolorspace" | |
225 | | currentdash => "currentdash" | |
226 | | currentfont => "currentfont" | |
227 | | currentglobal => "currentglobal" | |
228 | | currentgray => "currentgray" | |
229 | | currentgstate => "currentgstate" | |
230 | | currenthsbcolor => "currenthsbcolor" | |
231 | | currentlinecap => "currentlinecap" | |
232 | | currentlinejoin => "currentlinejoin" | |
233 | | currentlinewidth => "currentlinewidth" | |
234 | | currentmiterlimit => "currentmiterlimit" | |
235 | | currentmykcolor => "currentmykcolor" | |
236 | | currentpagedevice => "currentpagedevice" | |
237 | | currentpoint => "currentpoint" | |
238 | | currentrgbcolor => "currentrgbcolor" | |
239 | | currentstrokeadjust => "currentstrokeadjust" | |
240 | | curveto => "curveto" | |
241 | | definefont => "definefont" | |
242 | | defineuserobject => "defineuserobject" | |
243 | | div => "div" | |
244 | | dup => "dup" | |
245 | | eoclip => "eoclip" | |
246 | | eofill => "eofill" | |
247 | | erasepage => "erasepage" | |
248 | | exch => "exch" | |
249 | | execuserobject => "execuserobject" | |
250 | | exp => "exp" | |
251 | | fill => "fill" | |
252 | | findfont => "findfont" | |
253 | | flattenpath => "flattenpath" | |
254 | | floor => "floor" | |
255 | | font => "font" | |
256 | | forall => "forall" | |
257 | | gcheck => "gcheck" | |
258 | | glyphshow => "glyphshow" | |
259 | | grestore => "grestore" | |
260 | | grestoreall => "grestoreall" | |
261 | | gsave => "gsave" | |
262 | | gstate => "gstate" | |
263 | | idiv => "idiv" | |
264 | | image => "image" | |
265 | | imagemask => "imagemask" | |
266 | | index => "index" | |
267 | | initclip => "initclip" | |
268 | | initgraphics => "initgraphics" | |
269 | | kshow => "kshow" | |
270 | | lineto => "lineto" | |
271 | | ln => "ln" | |
272 | | log => "log" | |
273 | | makefont => "makefont" | |
274 | | mark => "mark" | |
275 | | mod => "mod" | |
276 | | moveto => "moveto" | |
277 | | mul => "mul" | |
278 | | neg => "neg" | |
279 | | newpath => "newpath" | |
280 | | nulldevice => "nulldevice" | |
281 | | pathbbox => "pathbbox" | |
282 | | pathforall => "pathforall" | |
283 | | pop => "pop" | |
284 | | rand => "rand" | |
285 | | rcurveto => "rcurveto" | |
286 | | rectclip => "rectclip" | |
287 | | rectfill => "rectfill" | |
288 | | rectstroke => "rectstroke" | |
289 | | restore => "restore" | |
290 | | reversepath => "reversepath" | |
291 | | rlineto => "rlineto" | |
292 | | rmoveto => "rmoveto" | |
293 | | roll => "roll" | |
294 | | rootfont => "rootfont" | |
295 | | round => "round" | |
296 | | rrand => "rrand" | |
297 | | save => "save" | |
298 | | scalefont => "scalefont" | |
299 | | selectfont => "selectfont" | |
300 | | setbbox => "setbbox" | |
301 | | setcolor => "setcolor" | |
302 | | setcolorspace => "setcolorspace" | |
303 | | setdash => "setdash" | |
304 | | setfont => "setfont" | |
305 | | setglobal => "setglobal" | |
306 | | setgray => "setgray" | |
307 | | setgstate => "setgstate" | |
308 | | sethsbcolor => "sethsbcolor" | |
309 | | setlinecap => "setlinecap" | |
310 | | setlinejoin => "setlinejoin" | |
311 | | setlinewidth => "setlinewidth" | |
312 | | setmiterlimit => "setmiterlimit" | |
313 | | setmykcolor => "setmykcolor" | |
314 | | setpagedevice => "setpagedevice" | |
315 | | setrgbcolor => "setrgbcolor" | |
316 | | setstrokeadjust => "setstrokeadjust" | |
317 | | shfill => "shfill" | |
318 | | show => "show" | |
319 | | showpage => "showpage" | |
320 | | sin => "sin" | |
321 | | sqrt => "sqrt" | |
322 | | srand => "srand" | |
323 | | startjob => "startjob" | |
324 | | stringwidth => "stringwidth" | |
325 | | stroke => "stroke" | |
326 | | strokepath => "strokepath" | |
327 | | sub => "sub" | |
328 | | truncate => "truncate" | |
329 | | uappend => "uappend" | |
330 | | ucache => "ucache" | |
331 | | ueofill => "ueofill" | |
332 | | ufill => "ufill" | |
333 | | undefinefont => "undefinefont" | |
334 | | undefineuserobject => "undefineuserobject" | |
335 | | upath => "upath" | |
336 | | userobjects => "userobjects" | |
337 | | ustroke => "ustroke" | |
338 | | ustrokepath => "ustrokepath" | |
339 | | widthshow => "widthshow" | |
340 | | xshow => "xshow" | |
341 | | xyshow => "xyshow" | |
342 | | yshow => "yshow" | |
343 | ||
344 | fun programString(os: t list): string = | |
345 | let | |
346 | fun loop(os: t list, | |
347 | lineLen: int, | |
348 | line: string list, | |
349 | lines: string list): string = | |
350 | let | |
351 | fun newLine() = concat("\n" :: rev line) :: lines | |
352 | in case os of | |
353 | [] => concat(rev(newLine())) | |
354 | | oper :: os => | |
355 | let | |
356 | val oper = toString oper | |
357 | val m = String.size oper | |
358 | val lineLen = m + 1 + lineLen | |
359 | in if lineLen > 80 | |
360 | then loop(os, m + 1, [" ", oper], newLine()) | |
361 | else loop(os, lineLen, " " :: oper :: line, lines) | |
362 | end | |
363 | end | |
364 | in loop(os, 0, [], ["%!PS\n"]) | |
365 | end | |
366 | ||
367 | val pointsPerInch = 72.0 | |
368 | fun inches(x: real): real = x * pointsPerInch | |
369 | val pageWidth = inches 8.5 | |
370 | val pageHeight = inches 11.0 | |
371 | val margin = inches 0.2 | |
372 | val dateHeight = inches 0.3 | |
373 | val userHeight = inches 1.2 | |
374 | val width = pageWidth - 2.0 * margin | |
375 | val dateRatio = 0.6 | |
376 | val dateBase = pageHeight - margin - dateHeight * (1.0 + dateRatio) / 2.0 | |
377 | val userRatio = 0.6 | |
378 | val userBase = | |
379 | pageHeight - margin - dateHeight - userHeight * (1.0 + userRatio) / 2.0 | |
380 | ||
381 | fun makeHeader{ | |
382 | host: string, | |
383 | job: string, | |
384 | user: string | |
385 | }: string = | |
386 | let val now = Date.now() | |
387 | val time = string(concat["Time: ", Date.fmt(now, "%I:%M:%S %p")]) | |
388 | in programString | |
389 | [save, | |
390 | (* Draw boxes *) | |
391 | real 0.0, setgray, | |
392 | int margin, int (pageHeight - margin), moveto, | |
393 | int width, int 0.0, rlineto, | |
394 | int 0.0, int (~(dateHeight + userHeight)), rlineto, | |
395 | int (~width), int 0.0, rlineto, closepath, | |
396 | int 1.0, setlinewidth, stroke, | |
397 | int margin, int (pageHeight - margin - dateHeight), moveto, | |
398 | int width, int 0.0, rlineto, | |
399 | int 2.0, setlinewidth, stroke, | |
400 | (* Set the font for dates *) | |
401 | literal "Helvetica", findfont, | |
402 | int (dateHeight * dateRatio * 1.3), | |
403 | scalefont, setfont, | |
404 | (* Show the date *) | |
405 | int (2.0 * margin), | |
406 | int dateBase, | |
407 | moveto, | |
408 | string(concat["Date: ", Date.fmt(now, "%m/%d/%y")]), | |
409 | show, | |
410 | (* Show the job name *) | |
411 | int (pageWidth / 2.0), string job, stringwidth, pop, int 2.0, div, sub, | |
412 | int dateBase, moveto, | |
413 | string job, show, | |
414 | (* Show the time *) | |
415 | int (pageWidth - 2.0 * margin), | |
416 | time, | |
417 | stringwidth, pop, sub, | |
418 | int dateBase, moveto, | |
419 | time, show, | |
420 | (* Show the user *) | |
421 | literal "Helvetica", findfont, | |
422 | int (userHeight * userRatio * 1.3), | |
423 | scalefont, setfont, | |
424 | int (pageWidth / 2.0), string user, stringwidth, pop, int 2.0, div, sub, | |
425 | int userBase, moveto, | |
426 | real 0.3, setgray, | |
427 | string user, show, | |
428 | (* Finish *) | |
429 | restore, | |
430 | showpage] | |
431 | end | |
432 | ||
433 | end |