Import Upstream version 20180207
[hcoop/debian/mlton.git] / lib / mlton / basic / postscript.sml
CommitLineData
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
8structure Postscript: POSTSCRIPT =
9struct
10
11nonfix mod div
12
13structure 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
27structure String =
28 struct
29 open String
30
31 fun escapePostscript s = translate(s, Char.escapePostscript)
32 end
33
34
35datatype 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
189fun tildeToMinus s =
190 String.translate(s, fn #"~" => "-" | c => Char.toString c)
191
192val 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
344fun 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
367val pointsPerInch = 72.0
368fun inches(x: real): real = x * pointsPerInch
369val pageWidth = inches 8.5
370val pageHeight = inches 11.0
371val margin = inches 0.2
372val dateHeight = inches 0.3
373val userHeight = inches 1.2
374val width = pageWidth - 2.0 * margin
375val dateRatio = 0.6
376val dateBase = pageHeight - margin - dateHeight * (1.0 + dateRatio) / 2.0
377val userRatio = 0.6
378val userBase =
379 pageHeight - margin - dateHeight - userHeight * (1.0 + userRatio) / 2.0
380
381fun 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
433end