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