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