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