Commit | Line | Data |
---|---|---|
012f1c1f DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
9b0a4950 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
a399f6c8 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
012f1c1f DF |
16 | */ |
17 | ||
c936af6c | 18 | #ifndef lint |
9b0a4950 KB |
19 | char copyright[] = |
20 | "@(#) Copyright (c) 1983 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
22 | #endif /* not lint */ | |
23 | ||
24 | #ifndef lint | |
ca67e7b4 | 25 | static char sccsid[] = "@(#)vplotf.c 5.4 (Berkeley) 6/30/88"; |
9b0a4950 | 26 | #endif /* not lint */ |
c936af6c | 27 | |
ec143a1b RC |
28 | /* |
29 | * Lpd filter to read standard graphics input and produce a plot on the | |
30 | * Varian or Versatec | |
31 | */ | |
32 | ||
33 | #include <stdio.h> | |
34 | #include <vfont.h> | |
35 | #include <sys/vcmd.h> | |
36 | ||
37 | #define mapx(x) ((DevRange*((x)-botx)/del)+centx) | |
38 | #define mapy(y) ((DevRange*(del-(y)+boty)/del)-centy) | |
39 | #define SOLID -1 | |
40 | #define DOTTED 014 | |
41 | #define SHORTDASHED 034 | |
42 | #define DOTDASHED 054 | |
43 | #define LONGDASHED 074 | |
44 | ||
022ef3a0 | 45 | static char *Sid = "@(#)\t5/16/83"; |
ec143a1b RC |
46 | |
47 | int linmod = SOLID; | |
48 | int done1; | |
49 | char chrtab[][16]; | |
50 | char *obuf; | |
51 | int bufsize; | |
52 | int lastx; | |
53 | int lasty; | |
54 | int radius, startx, starty, endx, endy; | |
55 | double topx; | |
56 | double topy; | |
57 | double botx; | |
58 | double boty; | |
59 | int centx = 0; | |
60 | int centy = 0; | |
61 | double delx; | |
62 | double dely; | |
63 | double del; | |
64 | ||
65 | int warned = 0; /* Indicates whether the warning message about | |
66 | * unimplemented routines has been printed */ | |
67 | ||
68 | int plotmd[] = {VPLOT}; | |
69 | int prtmd[] = {VPRINT}; | |
022ef3a0 RC |
70 | int varian; /* 0 for versatec, 1 for varian. */ |
71 | int BYTES_PER_LINE; /* number of bytes per raster line. */ | |
72 | int PAGE_LINES; /* number of raster lines per page. */ | |
ec143a1b RC |
73 | int DevRange = 1536; /* output array size (square) in pixels */ |
74 | int DevRange8 = 1536/8; /* output array size in bytes */ | |
ec143a1b RC |
75 | int lines; /* number of raster lines printed */ |
76 | char zeros[880]; /* one raster line */ | |
77 | ||
78 | char *name, *host, *acctfile; | |
79 | ||
022ef3a0 | 80 | /* variables used to print from font file */ |
ec143a1b RC |
81 | int fontSet = 0; /* Has the font file been read */ |
82 | struct header header; | |
83 | struct dispatch dispatch[256]; | |
84 | char *bits; | |
022ef3a0 | 85 | char *fontFile = "/usr/lib/vfont/R.8"; |
ec143a1b RC |
86 | |
87 | main(argc, argv) | |
88 | int argc; | |
89 | char *argv[]; | |
90 | { | |
91 | register char *cp, *arg; | |
92 | register n, again; | |
93 | ||
ec143a1b RC |
94 | while (--argc) { |
95 | if (**++argv == '-') { | |
96 | switch (argv[0][1]) { | |
022ef3a0 RC |
97 | case 'x': |
98 | BYTES_PER_LINE = atoi(&argv[0][2]) / 8; | |
99 | if (varian = BYTES_PER_LINE == 264) { | |
100 | DevRange = 1536; | |
101 | DevRange8 = 1536/8; | |
102 | } else { | |
103 | DevRange = 2048; | |
104 | DevRange8 = 2048/8; | |
105 | } | |
106 | break; | |
107 | ||
108 | case 'y': | |
109 | PAGE_LINES = atoi(&argv[0][2]); | |
110 | break; | |
111 | ||
ec143a1b RC |
112 | case 'n': |
113 | argc--; | |
114 | name = *++argv; | |
115 | break; | |
116 | ||
117 | case 'h': | |
118 | argc--; | |
119 | host = *++argv; | |
120 | } | |
121 | } else | |
122 | acctfile = *argv; | |
123 | } | |
124 | ||
125 | /* init constants for scaling */ | |
126 | topx = topy = DevRange; | |
127 | botx = boty = 0; | |
128 | delx = dely = del = DevRange; | |
129 | centx = (DevRange - mapx(topx))/2; | |
130 | centy = mapy(topy)/2; | |
131 | ||
132 | if ((obuf = (char *) malloc(bufsize = DevRange * DevRange8)) == NULL) { | |
133 | fprintf(stderr, "vplotf: ran out of memory\n"); | |
134 | exit(2); | |
135 | } | |
136 | ||
137 | do { | |
138 | arg = &obuf[bufsize]; | |
139 | for (cp = obuf; cp < arg; ) | |
140 | *cp++ = 0; | |
141 | ||
142 | again = getpict(); | |
143 | ||
144 | ioctl(1, VSETSTATE, plotmd); | |
022ef3a0 | 145 | n = BYTES_PER_LINE - DevRange8; |
ec143a1b RC |
146 | for (cp = obuf; cp < arg; cp += DevRange8) { |
147 | if (write(1, cp, DevRange8) != DevRange8) | |
148 | exit(1); | |
149 | if (n && write(1, zeros, n) != n) | |
150 | exit(1); | |
151 | lines++; | |
152 | } | |
153 | ioctl(1, VSETSTATE, prtmd); | |
154 | if (varian) | |
155 | write(1, "\f", 2); | |
156 | else | |
157 | write(1, "\n\n\n\n\n", 6); | |
158 | } while (again); | |
159 | ||
160 | account(name, host, *argv); | |
161 | exit(0); | |
162 | } | |
163 | ||
164 | account(who, from, acctfile) | |
165 | char *who, *from, *acctfile; | |
166 | { | |
167 | register FILE *a; | |
168 | ||
169 | if (who == NULL || acctfile == NULL) | |
170 | return; | |
171 | if (access(acctfile, 02) || (a = fopen(acctfile, "a")) == NULL) | |
172 | return; | |
173 | /* | |
174 | * Varian accounting is done by 8.5 inch pages; | |
175 | * Versatec accounting is by the (12 inch) foot. | |
176 | */ | |
984a125c | 177 | fprintf(a, "t%6.2f\t", (double)lines / (double)PAGE_LINES); |
ec143a1b RC |
178 | if (from != NULL) |
179 | fprintf(a, "%s:", from); | |
180 | fprintf(a, "%s\n", who); | |
181 | fclose(a); | |
182 | } | |
183 | ||
184 | getpict() | |
185 | { | |
186 | register x1, y1; | |
187 | ||
188 | for (;;) switch (x1 = getc(stdin)) { | |
189 | ||
190 | case '\n': | |
191 | continue; | |
192 | ||
193 | case 's': | |
194 | botx = getinteger(stdin); | |
195 | boty = getinteger(stdin); | |
196 | topx = getinteger(stdin); | |
197 | topy = getinteger(stdin); | |
198 | delx = topx-botx; | |
199 | dely = topy-boty; | |
200 | if (dely/delx > 1536./2048.) | |
201 | del = dely; | |
202 | else | |
203 | del = delx; | |
204 | centx = 0; | |
205 | centx = (DevRange - mapx(topx))/2; | |
206 | centy = 0; | |
207 | centy = mapy(topy) / 2; | |
208 | continue; | |
209 | ||
210 | case 'b': | |
211 | x1 = getc(stdin); | |
212 | continue; | |
213 | ||
214 | case 'l': | |
215 | done1 |= 01; | |
216 | x1 = mapx(getinteger(stdin)); | |
217 | y1 = mapy(getinteger(stdin)); | |
218 | lastx = mapx(getinteger(stdin)); | |
219 | lasty = mapy(getinteger(stdin)); | |
220 | line(x1, y1, lastx, lasty); | |
221 | continue; | |
222 | ||
223 | case 'c': | |
224 | x1 = mapx(getinteger(stdin)); | |
225 | y1 = mapy(getinteger(stdin)); | |
226 | radius = mapx(getinteger(stdin)); | |
227 | circle(x1, y1, radius); | |
228 | continue; | |
229 | ||
230 | case 'a': | |
231 | x1 = mapx(getinteger(stdin)); | |
232 | y1 = mapy(getinteger(stdin)); | |
233 | startx = mapx(getinteger(stdin)); | |
234 | starty = mapy(getinteger(stdin)); | |
235 | endx = mapx(getinteger(stdin)); | |
236 | endy = mapy(getinteger(stdin)); | |
237 | if (!warned) { | |
238 | fprintf(stderr,"Arcs are unimplemented\n"); | |
239 | warned++; | |
240 | } | |
241 | continue; | |
242 | ||
243 | case 'm': | |
244 | lastx = mapx(getinteger(stdin)); | |
245 | lasty = mapy(getinteger(stdin)); | |
246 | continue; | |
247 | ||
248 | case 't': | |
249 | lastx = lastx - 6; | |
250 | lasty = lasty + 6; | |
251 | done1 |= 01; | |
252 | while ((x1 = getc(stdin)) != '\n') | |
253 | plotch(x1); | |
254 | continue; | |
255 | ||
256 | case 'e': | |
257 | if (done1) | |
258 | return(1); | |
259 | continue; | |
260 | ||
261 | case 'p': | |
262 | done1 |= 01; | |
263 | lastx = mapx(getinteger(stdin)); | |
264 | lasty = mapy(getinteger(stdin)); | |
265 | point(lastx, lasty); | |
266 | point(lastx+1, lasty); | |
267 | point(lastx, lasty+1); | |
268 | point(lastx+1, lasty+1); | |
269 | continue; | |
270 | ||
271 | case 'n': | |
272 | done1 |= 01; | |
273 | x1 = mapx(getinteger(stdin)); | |
274 | y1 = mapy(getinteger(stdin)); | |
275 | line(lastx, lasty, x1, y1); | |
276 | lastx = x1; | |
277 | lasty = y1; | |
278 | continue; | |
279 | ||
280 | case 'f': | |
281 | getinteger(stdin); | |
282 | getc(stdin); | |
283 | switch (getc(stdin)) { | |
284 | case 't': | |
285 | linmod = DOTTED; | |
286 | break; | |
287 | default: | |
288 | case 'i': | |
289 | linmod = SOLID; | |
290 | break; | |
291 | case 'g': | |
292 | linmod = LONGDASHED; | |
293 | break; | |
294 | case 'r': | |
295 | linmod = SHORTDASHED; | |
296 | break; | |
297 | case 'd': | |
298 | linmod = DOTDASHED; | |
299 | break; | |
300 | } | |
301 | while ((x1 = getc(stdin)) != '\n') | |
302 | if (x1 == EOF) | |
303 | return(0); | |
304 | continue; | |
305 | ||
306 | case 'd': | |
307 | getinteger(stdin); | |
308 | getinteger(stdin); | |
309 | getinteger(stdin); | |
310 | x1 = getinteger(stdin); | |
311 | while (--x1 >= 0) | |
312 | getinteger(stdin); | |
313 | continue; | |
314 | ||
315 | case 0: /* ignore null characters */ | |
316 | continue; | |
317 | ||
318 | case 255: | |
319 | case EOF: | |
320 | return(0); | |
321 | ||
322 | default: | |
323 | fprintf(stderr, "Input format error %c(%o)\n",x1,x1); | |
324 | exit(2); | |
325 | } | |
326 | } | |
327 | ||
328 | plotch(ch) | |
329 | char ch; | |
330 | { | |
331 | register int i,j,k; | |
332 | register char *ptr,c; | |
333 | int nbytes; | |
334 | ||
335 | if (!fontSet) | |
336 | InitFont(); /* Read font if not already read */ | |
337 | ||
338 | ptr = bits + dispatch[ch].addr; | |
339 | ||
340 | for (i = dispatch[ch].up; i > -dispatch[ch].down; --i) { | |
341 | nbytes = (dispatch[ch].right + dispatch[ch].left + 7)/8; | |
342 | for (j = 0; j < nbytes; j++) { | |
343 | c = *ptr++; | |
344 | for (k = 7; k >= 0; k--) | |
345 | if ((c >> k) & 1) | |
346 | point(lastx+7-k+j*8-dispatch[ch].left, lasty-i); | |
347 | } | |
348 | } | |
349 | if (ch != ' ') | |
350 | lastx += dispatch[ch].width; | |
351 | else | |
352 | lastx += dispatch['a'].width; | |
353 | } | |
354 | ||
355 | InitFont() | |
356 | { | |
357 | char *s; | |
358 | int fonts; | |
359 | int i; | |
360 | ||
361 | fontSet = 1; | |
362 | /* Get the font file */ | |
363 | s = fontFile; | |
364 | if ((fonts = open(s, 0)) == -1) { | |
365 | perror(s); | |
366 | fprintf(stderr, "Can't get font file"); | |
367 | exit(2); | |
368 | } | |
369 | /* Get the header and check magic number */ | |
370 | if (read(fonts, &header, sizeof(header)) != sizeof(header)) { | |
371 | perror(s); | |
372 | fprintf(stderr, "Bad read in font file"); | |
373 | exit(2); | |
374 | } | |
375 | if (header.magic != 0436) { | |
376 | fprintf(stderr,"Bad magic numer in font file"); | |
377 | exit(2); | |
378 | } | |
379 | /* Get dispatches */ | |
380 | if (read(fonts, dispatch, sizeof(dispatch)) != sizeof(dispatch)) { | |
381 | perror(s); | |
382 | fprintf(stderr, "Bad read in font file"); | |
383 | exit(2); | |
384 | } | |
385 | /* Allocate space for bit map and read in bits */ | |
386 | bits = (char *) malloc(header.size); | |
387 | if (read(fonts, bits, header.size) != header.size) { | |
388 | perror(s); | |
389 | fprintf(stderr,"Can't read bit map in font file"); | |
390 | exit(2); | |
391 | } | |
392 | /* Close font file */ | |
393 | if (close(fonts) != 0) { | |
394 | perror(s); | |
395 | fprintf(stderr,"Can't close font file"); | |
396 | exit(2); | |
397 | } | |
398 | } | |
399 | ||
400 | line(x0, y0, x1, y1) | |
401 | register x0, y0; | |
402 | { | |
403 | int dx, dy; | |
404 | int xinc, yinc; | |
405 | register res1; | |
406 | int res2; | |
407 | int slope; | |
408 | ||
409 | xinc = 1; | |
410 | yinc = 1; | |
411 | if ((dx = x1-x0) < 0) { | |
412 | xinc = -1; | |
413 | dx = -dx; | |
414 | } | |
415 | if ((dy = y1-y0) < 0) { | |
416 | yinc = -1; | |
417 | dy = -dy; | |
418 | } | |
419 | slope = xinc*yinc; | |
420 | res1 = 0; | |
421 | res2 = 0; | |
422 | if (dx >= dy) while (x0 != x1) { | |
423 | if ((x0+slope*y0) & linmod) | |
424 | point(x0, y0); | |
425 | if (res1 > res2) { | |
426 | res2 += dx - res1; | |
427 | res1 = 0; | |
428 | y0 += yinc; | |
429 | } | |
430 | res1 += dy; | |
431 | x0 += xinc; | |
432 | } else while (y0 != y1) { | |
433 | if ((x0+slope*y0) & linmod) | |
434 | point(x0, y0); | |
435 | if (res1 > res2) { | |
436 | res2 += dy - res1; | |
437 | res1 = 0; | |
438 | x0 += xinc; | |
439 | } | |
440 | res1 += dx; | |
441 | y0 += yinc; | |
442 | } | |
443 | if ((x1+slope*y1) & linmod) | |
444 | point(x1, y1); | |
445 | } | |
446 | ||
b99a502f | 447 | #define labs(a) ((a) >= 0 ? (a) : -(a)) |
ec143a1b RC |
448 | |
449 | circle(x,y,c) | |
450 | { | |
451 | register dx, dy; | |
452 | long ep; | |
453 | int de; | |
454 | ||
455 | dx = 0; | |
456 | ep = 0; | |
457 | for (dy=c; dy>=dx; dy--) { | |
458 | for (;;) { | |
459 | point(x+dx, y+dy); | |
460 | point(x-dx, y+dy); | |
461 | point(x+dx, y-dy); | |
462 | point(x-dx, y-dy); | |
463 | point(x+dy, y+dx); | |
464 | point(x-dy, y+dx); | |
465 | point(x+dy, y-dx); | |
466 | point(x-dy, y-dx); | |
467 | ep += 2*dx + 1; | |
468 | de = -2*dy + 1; | |
469 | dx++; | |
470 | if (labs(ep) >= labs(ep+de)) { | |
471 | ep += de; | |
472 | break; | |
473 | } | |
474 | } | |
475 | } | |
476 | } | |
477 | ||
478 | /* | |
479 | * Points should be in the range 0 <= x (or y) <= DevRange. | |
480 | * The origin is the top left-hand corner with increasing x towards the | |
481 | * right and increasing y going down. | |
482 | */ | |
483 | point(x, y) | |
484 | register unsigned x, y; | |
485 | { | |
486 | register unsigned byte; | |
487 | ||
488 | if (x < DevRange && y < DevRange) { | |
489 | byte = y * DevRange8 + (x >> 3); | |
490 | obuf[byte] |= 1 << (7 - (x & 07)); | |
491 | } | |
492 | } | |
493 | ||
494 | getinteger(f) | |
495 | FILE *f; | |
496 | { | |
497 | register int low, high, result; | |
498 | ||
499 | low = getc(f); | |
500 | high = getc(f); | |
501 | result = ((high << 8) | low); | |
502 | if (high > 127) | |
503 | result |= ~0xffff; | |
504 | return(result); | |
505 | } |