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