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