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