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