⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 postbgi.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
    int		id;			/* subroutine id if ch wasn't an opcode *//* * * Handles subroutine calls. Everything that follows the BCALL opcode (up to the * next opcode) is taken as a subroutine identifier - thus the loop that generates * the subroutine calls. * */    while ( (ch = get_char()) != EOF && (ch & MSB) )  {	id = ch & DMASK;	fprintf(fp_out, "%d %d S%d\n", hpos, vpos, id);	hgoto(hpos + displacement[id].dx);	/* adjust our position */	vgoto(vpos + displacement[id].dy);    }	/* End while */    ungetc(ch, fp_in);}   /* End of subr_call *//*****************************************************************************/vector(var, mode)    int		var;			/* coordinate that varies next? */    int		mode;			/* VISIBLE or INVISIBLE vectors */{    int		ch;			/* next character from *fp_in */    int		x, y;			/* line drawn to this point */    int		count = 0;		/* number of points so far *//* * * Handles plotting of all types of BGI vectors. If it's a manhattan vector var * specifies which coordinate will be changed by the next number in the input * file. * */    x = hpos;				/* set up the first point */    y = vpos;    while ( (ch = get_char()) != EOF  &&  ch & MSB )  {	if ( var == X_COORD )		/* next length is change in x */	    x += get_int(ch);	else if ( var == Y_COORD )	/* it's the change in y */	    y += get_int(ch);	else if ( var == LONGVECTOR )  {	/* long vector */	    x += get_int(ch);	    y += get_int(0);	} else {			/* must be a short vector */	    x += ((ch & MSBMAG) * ((ch & SGNB) ? -1 : 1));	    y += (((ch = get_data()) & MSBMAG) * ((ch & SGNB) ? -1 : 1));	}   /* End else */	if ( mode == VISIBLE )  {	/* draw the line segment */	    fprintf(fp_out, "%d %d\n", hpos - x, vpos - y);	    count++;	}   /* End if */	hgoto(x);			/* adjust the current BGI position */	vgoto(y);	if ( var == X_COORD )		/* vertical length comes next */	    var = Y_COORD;	else if ( var == Y_COORD )	/* change horizontal next */	    var = X_COORD;    }	/* End while */    if ( count > 0 )	fprintf(fp_out, "%d %d v\n", hpos, vpos);    ungetc(ch, fp_in);			/* it wasn't part of the vector */    position--;}   /* End of vector *//*****************************************************************************/rectangle(mode)    int		mode;			/* FILL or OUTLINE the rectangle */{    int		deltax;			/* displacement for horizontal side */    int		deltay;			/* same but for vertical sides *//* * * Draws a rectangle and either outlines or fills it, depending on the value of * mode. Would be clearer, and perhaps better, if {stroke} or {fill} were put on * the stack instead of 0 or 1. R could then define the path and just do an exec * to fill or stroke it. * */    deltax = get_int(0);		/* get the height and width */    deltay = get_int(0);    if ( mode == OUTLINE )	fprintf(fp_out, "0 %d %d %d %d R\n", deltax, deltay, hpos, vpos);    else fprintf(fp_out, "1 %d %d %d %d R\n", deltax, deltay, hpos, vpos);}   /* End of rectangle *//*****************************************************************************/trapezoid(){    int		kind;			/* which sides are parallel */    int		d[6];			/* true displacements - depends on kind *//* * * Handles filled trapeziods. A data byte of 0101 following the opcode means the * horizontal sides are parallel, 0102 means the vertical sides are parallel. * Filling is handled by eofill so we don't need to get things in the right order. * */    kind = get_data();    d[0] = get_int(0);    d[1] = 0;    d[2] = get_int(0);    d[3] = get_int(0);    d[4] = get_int(0);    d[5] = 0;    if ( kind == 2 )  {			/* parallel sides are vertical */	d[1] = d[0];	d[0] = 0;	d[5] = d[4];	d[4] = 0;    }	/* End if */    fprintf(fp_out, "%d %d %d %d %d %d %d %d T\n", d[4], d[5], d[2], d[3], d[0], d[1], hpos, vpos);}   /* End of trapezoid *//*****************************************************************************/point_plot(mode, ch)    int		mode;			/* plotting mode BPOINT or BPOINT1 */    int		ch;			/* will be placed at the points */{    int		c;			/* next character from input file */    int		x, y;			/* ch gets put here next */    int		deltax;			/* x increment for BPOINT1 mode *//* * * The two point plot modes are used to place a character at selected points. The * difference in the two modes, namely BPOINT and BPOINT1, is the way we get the * coordinates of the next point. In BPOINT1 the two bytes immediately following * ch select a constant horizontal change, while both coordinates are given for * all points in BPOINT mode. * */    if ( mode == BPOINT1 )  {		/* first integer is change in x */	deltax = get_int(0);	x = hpos - deltax;    }	/* End if */    while ( (c = get_char()) != EOF  &&  (c & MSB) )  {	if ( mode == BPOINT1 )  {	/* only read y coordinate */	    y = get_int(c);	    x += deltax;	} else {			/* get new x and y from input file */	    x = get_int(c);	    y = get_int(0);	}   /* End else */	hgoto(x);			/* adjust BGI position */	vgoto(y);	fprintf(fp_out, "%d %d\n", hpos, vpos);    }	/* End while */    putc('(', fp_out);    switch ( ch )  {	case '(':	case ')':	case '\\':		putc('\\', fp_out);	default:		putc(ch, fp_out);    }	/* End switch */    fprintf(fp_out, ")pp\n");    ungetc(c, fp_in);			/* it wasn't part of the point plot */    position--;}   /* End of point_plot *//*****************************************************************************/line_plot(){    int		c;			/* next input character from fp_in */    int		deltax;			/* change in x coordinate */    int		x0, y0;			/* starting point for next segment */    int		x1, y1;			/* endpoint of the line */    int		count = 0;		/* number of points so far *//* * * Essentially the same format as BPOINT1, except that in this case we connect * pairs of points by line segments. * */    deltax = get_int(0);		/* again the change in x is first */    x1 = hpos;				/* so it works first time through */    y1 = get_int(0);    while ( (c = get_char()) != EOF  &&  (c & MSB) )  {	x0 = x1;			/* line starts here */	y0 = y1;	x1 += deltax;			/* and ends at this point */    	y1 = get_int(c);	fprintf(fp_out, "%d %d\n", -deltax, y0 - y1);	count++;    }	/* End while */    hgoto(x1);				/* adjust current BGI position */    vgoto(y1);    if ( count > 0 )	fprintf(fp_out, "%d %d v\n", hpos, vpos);    ungetc(c, fp_in);			/* wasn't part of the line */    position--;}   /* End of line_plot *//*****************************************************************************/arc(mode)    int		mode;			/* FILL or OUTLINE the path */{    int		dx1, dy1;		/* displacements for first point */    int		dx2, dy2;		/* same for the second point */    int		radius;			/* of the arc */    int		angle1, angle2;		/* starting and ending angles *//* * * Called whenever we need to draw an arc. I'm ignoring filled slices for now. * */    dx1 = get_int(0);			/* displacements relative to center */    dy1 = get_int(0);    dx2 = get_int(0);    dy2 = get_int(0);    radius = get_int(0);		/* and the radius */    if ( radius == 0 )			/* nothing to do */	return;    angle1 = (atan2((double) dy1, (double) dx1) * 360) / (2 * PI) + .5;    angle2 = (atan2((double) dy2, (double) dx2) * 360) / (2 * PI) + .5;    fprintf(fp_out, "%d %d %d %d %d arcn stroke\n", hpos, vpos, radius, angle1, angle2);}   /* End of arc *//*****************************************************************************/pattern(){    double	red = 0;		/* color components */    double	green = 0;    double	blue = 0;    int		kind;			/* corse or fine pattern */    int		val;			/* next color data byte */    int		i;			/* loop index *//* * * Handles patterns by setting the current color based of the values assigned to * the next four data bytes. BGI supports two kinds of patterns (fine or coarse) * but I'm handling each in the same way - for now. In a fine pattern the four * data bytes assign a color to four individual pixels (upperleft first) while * in a coarse pattern the four colors are assigned to groups of four pixels, * for a total of 16. Again the first color goes to the group in the upper left * corner. The byte immediately following the BPAT opcode selects fine (040) or * coarse (041) patterns. The PostScript RGB color is assigned by averaging the * RED, GREEN, and BLUE components assigned to the four pixels (or groups of * pixels). Acceptable results, but there's no distinction between fine and * coarse patterns. * */    if ( (kind = get_char()) == EOF )	error(FATAL, "bad pattern command");    for ( i = 0; i < 4; i++ )  {	val = get_data();	red += get_color(val, RED);	green += get_color(val, GREEN);	blue += get_color(val, BLUE);    }	/* End for */    fprintf(fp_out, "%g %g %g c\n", red/4, green/4, blue/4);}   /* End of pattern *//*****************************************************************************/get_color(val, component)    int		val;			/* color data byte */    int		component;		/* RED, GREEN, or BLUE component */{    int		primary;		/* color mixing mode - bits 2 to 4 */    int		plane;			/* primary color plane - bits 5 to 7 */    unsigned	rgbcolor;		/* PostScript expects an RGB triple *//* * * Picks the requested color component (RED, GREEN, or BLUE) from val and returns * the result to the caller. BGI works with Cyan, Yellow, and Magenta so the one's * complement stuff (following the exclusive or'ing) recovers the RED, BLUE, and * GREEN components that PostScript's setrgbcolor operator needs. The PostScript * interpreter in the ColorScript 100 has a setcmycolor operator, but it's not * generally available so I've decided to stick with setrgbcolor. * */    primary = (val >> 3) & 07;    plane = val & 07;    rgbcolor = (~(primary ^ plane)) & 07;    if ( debug == ON )	fprintf(stderr, "val = %o, primary = %o, plane = %o, rgbcolor = %o\n",		val, primary, plane, rgbcolor);    switch ( component )  {	case RED:		return(rgbcolor>>2);	case GREEN:		return(rgbcolor&01);	case BLUE:		return((rgbcolor>>1)&01);	default:		error(FATAL, "unknown color component");		return(0);    }	/* End switch */}   /* End of get_color *//*****************************************************************************/set_color(val)    int		val;			/* color data byte */{/* * * Arranges to have the color set to the value requested in the BGI data byte val. * */    fprintf(fp_out, "%d %d %d c\n", get_color(val, RED), get_color(val, GREEN), get_color(val, BLUE));}   /* End of set_color *//*****************************************************************************/get_int(highbyte)    int		highbyte;		/* already read this byte */{    int		lowbyte;		/* this and highbyte make the int *//* * * Figures out the value on the integer (sign magnitude form) that's next in the * input file. If highbyte is nonzero we'll use it and the next byte to build the * integer, otherwise two bytes are read from fp_in. * */    if ( highbyte == 0 )		/* need to read the first byte */	highbyte = get_data();    lowbyte = get_data();		/* always need the second byte */    return(highbyte & SGNB ? -MAG(highbyte, lowbyte) : MAG(highbyte, lowbyte));}   /* End of get_int *//*****************************************************************************/get_data(){    int		val;			/* data value returned to caller *//* * * Called when we expect to find a single data character in the input file. The * data bit is turned off and the resulting value is returned to the caller. * */    if ( (val = get_char()) == EOF  ||  ! (val & MSB) )	error(FATAL, "missing data value");    return(val & DMASK);}   /* End of get_data *//*****************************************************************************/get_char(){    int		ch;			/* character we just read *//* * * Reads the next character from file *fp_in and returns the value to the caller. * This routine isn't really needed, but we may want to deal directly with some * screwball file formats so I thought it would probably be a good idea to isolate * all the input in one routine that could be easily changed. * */    if ( (ch = getc(fp_in)) != EOF )  {	position++;	ch &= CHMASK;    }	/* End if */    if ( debug == ON )	fprintf(stderr, "%o ", ch);    return(ch);}   /* End of get_char *//*****************************************************************************/redirect(pg)    int		pg;			/* next page we're printing */{    static FILE	*fp_null = NULL;	/* if output is turned off *//* * * If we're not supposed to print page pg, fp_out will be directed to /dev/null, * otherwise output goes to stdout. * */    if ( pg >= 0 && in_olist(pg) == ON )	fp_out = stdout;    else if ( (fp_out = fp_null) == NULL )	fp_out = fp_null = fopen("/dev/null", "w");}   /* End of redirect *//*****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -