|  | #include	<stdio.h> | 
|  | #include	<math.h> | 
|  | #include	"pic.h" | 
|  | #include	"y.tab.h" | 
|  |  | 
|  | void | 
|  | print(void) | 
|  | { | 
|  | obj *p; | 
|  | int i, j, k, m; | 
|  | double x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy; | 
|  |  | 
|  | for (i = 0; i < nobj; i++) { | 
|  | p = objlist[i]; | 
|  | ox = p->o_x; | 
|  | oy = p->o_y; | 
|  | x1 = 0; | 
|  | if (p->o_count >= 1) | 
|  | x1 = p->o_val[0]; | 
|  | y1 = 0; | 
|  | if (p->o_count >= 2) | 
|  | y1 = p->o_val[1]; | 
|  | m = p->o_mode; | 
|  | switch (p->o_type) { | 
|  | case TROFF: | 
|  | troff(text[p->o_nt1].t_val); | 
|  | break; | 
|  | case BOX: | 
|  | case BLOCK: | 
|  | x0 = ox - x1 / 2; | 
|  | y0 = oy - y1 / 2; | 
|  | x1 = ox + x1 / 2; | 
|  | y1 = oy + y1 / 2; | 
|  | if (p->o_attr & FILLBIT) { | 
|  | move(x0, y0); | 
|  | fillstart(p->o_fillval); | 
|  | } | 
|  | if (p->o_attr & INVIS || p->o_type == BLOCK) | 
|  | ;	/* nothing at all */ | 
|  | else if (p->o_attr & (DOTBIT|DASHBIT)) | 
|  | dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval); | 
|  | else | 
|  | box(x0, y0, x1, y1); | 
|  | if (p->o_attr & FILLBIT) | 
|  | fillend(); | 
|  | move(ox, oy); | 
|  | dotext(p);	/* if there are any text strings */ | 
|  | if (ishor(m)) | 
|  | move(isright(m) ? x1 : x0, oy);	/* right side */ | 
|  | else | 
|  | move(ox, isdown(m) ? y0 : y1);	/* bottom */ | 
|  | break; | 
|  | case BLOCKEND: | 
|  | break; | 
|  | case CIRCLE: | 
|  | if (p->o_attr & FILLBIT) | 
|  | fillstart(p->o_fillval); | 
|  | if ((p->o_attr & INVIS) == 0) | 
|  | circle(ox, oy, x1); | 
|  | if (p->o_attr & FILLBIT) | 
|  | fillend(); | 
|  | move(ox, oy); | 
|  | dotext(p); | 
|  | if (ishor(m)) | 
|  | move(ox + isright(m) ? x1 : -x1, oy); | 
|  | else | 
|  | move(ox, oy + isup(m) ? x1 : -x1); | 
|  | break; | 
|  | case ELLIPSE: | 
|  | if (p->o_attr & FILLBIT) | 
|  | fillstart(p->o_fillval); | 
|  | if ((p->o_attr & INVIS) == 0) | 
|  | ellipse(ox, oy, x1, y1); | 
|  | if (p->o_attr & FILLBIT) | 
|  | fillend(); | 
|  | move(ox, oy); | 
|  | dotext(p); | 
|  | if (ishor(m)) | 
|  | move(ox + isright(m) ? x1 : -x1, oy); | 
|  | else | 
|  | move(ox, oy - isdown(m) ? y1 : -y1); | 
|  | break; | 
|  | case ARC: | 
|  | move(ox, oy); | 
|  | dotext(p); | 
|  | if (p->o_attr & HEAD1) | 
|  | arrow(x1 - (y1 - oy), y1 + (x1 - ox), | 
|  | x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead); | 
|  | if (p->o_attr & INVIS) | 
|  | /* probably wrong when it's cw */ | 
|  | move(x1, y1); | 
|  | else | 
|  | arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]); | 
|  | if (p->o_attr & HEAD2) | 
|  | arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox), | 
|  | p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5], -p->o_val[5]/p->o_val[6]/2, p->o_nhead); | 
|  | if (p->o_attr & CW_ARC) | 
|  | move(x1, y1);	/* because drawn backwards */ | 
|  | break; | 
|  | case LINE: | 
|  | case ARROW: | 
|  | case SPLINE: | 
|  | move((ox + x1)/2, (oy + y1)/2);	/* center */ | 
|  | dotext(p); | 
|  | if (p->o_attr & HEAD1) | 
|  | arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); | 
|  | if (p->o_attr & INVIS) | 
|  | move(x1, y1); | 
|  | else if (p->o_type == SPLINE) | 
|  | spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval); | 
|  | else { | 
|  | dx = ox; | 
|  | dy = oy; | 
|  | for (k=0, j=5; k < p->o_val[4]; k++, j += 2) { | 
|  | ndx = dx + p->o_val[j]; | 
|  | ndy = dy + p->o_val[j+1]; | 
|  | if (p->o_attr & (DOTBIT|DASHBIT)) | 
|  | dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval); | 
|  | else | 
|  | line(dx, dy, ndx, ndy); | 
|  | dx = ndx; | 
|  | dy = ndy; | 
|  | } | 
|  | } | 
|  | if (p->o_attr & HEAD2) { | 
|  | dx = ox; | 
|  | dy = oy; | 
|  | for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) { | 
|  | dx += p->o_val[j]; | 
|  | dy += p->o_val[j+1]; | 
|  | } | 
|  | arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead); | 
|  | } | 
|  | break; | 
|  | case MOVE: | 
|  | case TEXT: | 
|  | move(ox, oy); | 
|  | dotext(p); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #ifndef NOEXPANDDASH | 
|  | void | 
|  | dotline(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted line */ | 
|  | { | 
|  | static double prevval = 0.05;	/* 20 per inch by default */ | 
|  | int i, numdots; | 
|  | double a, b, dx, dy; | 
|  |  | 
|  | if (ddval == 0) | 
|  | ddval = prevval; | 
|  | prevval = ddval; | 
|  | /* don't save dot/dash value */ | 
|  | dx = x1 - x0; | 
|  | dy = y1 - y0; | 
|  | if (ddtype & DOTBIT) { | 
|  | numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5; | 
|  | if (numdots > 0) | 
|  | for (i = 0; i <= numdots; i++) { | 
|  | a = (double) i / (double) numdots; | 
|  | move(x0 + (a * dx), y0 + (a * dy)); | 
|  | dot(); | 
|  | } | 
|  | } else if (ddtype & DASHBIT) { | 
|  | double d, dashsize, spacesize; | 
|  | d = sqrt(dx*dx + dy*dy); | 
|  | if (d <= 2 * prevval) { | 
|  | line(x0, y0, x1, y1); | 
|  | return; | 
|  | } | 
|  | numdots = d / (2 * prevval) + 1;	/* ceiling */ | 
|  | dashsize = prevval; | 
|  | spacesize = (d - numdots * dashsize) / (numdots - 1); | 
|  | b = 0; | 
|  | for (i = 0; i < numdots-1; i++) { | 
|  | a = i * (dashsize + spacesize) / d; | 
|  | b = a + dashsize / d; | 
|  | line(x0 + (a*dx), y0 + (a*dy), x0 + (b*dx), y0 + (b*dy)); | 
|  | a = b; | 
|  | b = a + spacesize / d; | 
|  | move(x0 + (a*dx), y0 + (a*dy)); | 
|  | } | 
|  | line(x0 + (b * dx), y0 + (b * dy), x1, y1); | 
|  | } | 
|  | prevval = 0.05; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | void | 
|  | dotbox(double x0, double y0, double x1, double y1, int ddtype, double ddval)	/* dotted or dashed box */ | 
|  | { | 
|  | dotline(x0, y0, x1, y0, ddtype, ddval); | 
|  | dotline(x1, y0, x1, y1, ddtype, ddval); | 
|  | dotline(x1, y1, x0, y1, ddtype, ddval); | 
|  | dotline(x0, y1, x0, y0, ddtype, ddval); | 
|  | } | 
|  |  | 
|  | void | 
|  | dotext(obj *p)	/* print text strings of p in proper vertical spacing */ | 
|  | { | 
|  | int i, nhalf; | 
|  |  | 
|  | nhalf = p->o_nt2 - p->o_nt1 - 1; | 
|  | for (i = p->o_nt1; i < p->o_nt2; i++) { | 
|  | label(text[i].t_val, text[i].t_type, nhalf); | 
|  | nhalf -= 2; | 
|  | } | 
|  | } |