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