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