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