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