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