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