📄 postbgi.c
字号:
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 + -