BSD 4_3_Tahoe release
[unix-history] / usr / src / usr.lib / lpr / vfilters / vplotf.c
CommitLineData
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
19char 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 25static 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 45static char *Sid = "@(#)\t5/16/83";
ec143a1b
RC
46
47int linmod = SOLID;
48int done1;
49char chrtab[][16];
50char *obuf;
51int bufsize;
52int lastx;
53int lasty;
54int radius, startx, starty, endx, endy;
55double topx;
56double topy;
57double botx;
58double boty;
59int centx = 0;
60int centy = 0;
61double delx;
62double dely;
63double del;
64
65int warned = 0; /* Indicates whether the warning message about
66 * unimplemented routines has been printed */
67
68int plotmd[] = {VPLOT};
69int prtmd[] = {VPRINT};
022ef3a0
RC
70int varian; /* 0 for versatec, 1 for varian. */
71int BYTES_PER_LINE; /* number of bytes per raster line. */
72int PAGE_LINES; /* number of raster lines per page. */
ec143a1b
RC
73int DevRange = 1536; /* output array size (square) in pixels */
74int DevRange8 = 1536/8; /* output array size in bytes */
ec143a1b
RC
75int lines; /* number of raster lines printed */
76char zeros[880]; /* one raster line */
77
78char *name, *host, *acctfile;
79
022ef3a0 80/* variables used to print from font file */
ec143a1b
RC
81int fontSet = 0; /* Has the font file been read */
82struct header header;
83struct dispatch dispatch[256];
84char *bits;
022ef3a0 85char *fontFile = "/usr/lib/vfont/R.8";
ec143a1b
RC
86
87main(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
164account(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
184getpict()
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
328plotch(ch)
329char 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
355InitFont()
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
400line(x0, y0, x1, y1)
401register 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
449circle(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 */
483point(x, y)
484register 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
494getinteger(f)
495FILE *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}