plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

print.c (6263B)


      1 #include <stdio.h>
      2 #include <math.h>
      3 #include "pic.h"
      4 #include "y.tab.h"
      5 
      6 void dotext(obj *);
      7 void dotline(double, double, double, double, int, double);
      8 void dotbox(double, double, double, double, int, double);
      9 void ellipse(double, double, double, double);
     10 void circle(double, double, double);
     11 void arc(double, double, double, double, double, double);
     12 void arrow(double, double, double, double, double, double, double, int);
     13 void line(double, double, double, double);
     14 void box(double, double, double, double);
     15 void spline(double x, double y, double n, ofloat *p, int dashed, double ddval);
     16 void move(double, double);
     17 void troff(char *);
     18 void dot(void);
     19 void fillstart(double), fillend(int vis, int noedge);
     20 
     21 void print(void)
     22 {
     23 	obj *p;
     24 	int i, j, k, m;
     25 	int fill, vis, invis;
     26 	double x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy;
     27 
     28 	x1 = y1 = 0.0; /* Botch? (gcc) */
     29 
     30 	for (i = 0; i < nobj; i++) {
     31 		p = objlist[i];
     32 		ox = p->o_x;
     33 		oy = p->o_y;
     34 		if (p->o_count >= 1)
     35 			x1 = p->o_val[0];
     36 		if (p->o_count >= 2)
     37 			y1 = p->o_val[1];
     38 		m = p->o_mode;
     39 		fill = p->o_attr & FILLBIT;
     40 		invis = p->o_attr & INVIS;
     41 		vis = !invis;
     42 		switch (p->o_type) {
     43 		case TROFF:
     44 			troff(text[p->o_nt1].t_val);
     45 			break;
     46 		case BOX:
     47 		case BLOCK:
     48 			x0 = ox - x1 / 2;
     49 			y0 = oy - y1 / 2;
     50 			x1 = ox + x1 / 2;
     51 			y1 = oy + y1 / 2;
     52 			if (fill) {
     53 				move(x0, y0);
     54 				fillstart(p->o_fillval);
     55 			}
     56 			if (p->o_type == BLOCK)
     57 				;	/* nothing at all */
     58 			else if (invis && !fill)
     59 				;	/* nothing at all */
     60 			else if (p->o_attr & (DOTBIT|DASHBIT))
     61 				dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval);
     62 			else
     63 				box(x0, y0, x1, y1);
     64 			if (fill)
     65 				fillend(vis, fill);
     66 			move(ox, oy);
     67 			dotext(p);	/* if there are any text strings */
     68 			if (ishor(m))
     69 				move(isright(m) ? x1 : x0, oy);	/* right side */
     70 			else
     71 				move(ox, isdown(m) ? y0 : y1);	/* bottom */
     72 			break;
     73 		case BLOCKEND:
     74 			break;
     75 		case CIRCLE:
     76 			if (fill)
     77 				fillstart(p->o_fillval);
     78 			if (vis || fill)
     79 				circle(ox, oy, x1);
     80 			if (fill)
     81 				fillend(vis, fill);
     82 			move(ox, oy);
     83 			dotext(p);
     84 			if (ishor(m))
     85 				move(ox + isright(m) ? x1 : -x1, oy);
     86 			else
     87 				move(ox, oy + isup(m) ? x1 : -x1);
     88 			break;
     89 		case ELLIPSE:
     90 			if (fill)
     91 				fillstart(p->o_fillval);
     92 			if (vis || fill)
     93 				ellipse(ox, oy, x1, y1);
     94 			if (fill)
     95 				fillend(vis, fill);
     96 			move(ox, oy);
     97 			dotext(p);
     98 			if (ishor(m))
     99 				move(ox + isright(m) ? x1 : -x1, oy);
    100 			else
    101 				move(ox, oy - isdown(m) ? y1 : -y1);
    102 			break;
    103 		case ARC:
    104 			if (fill) {
    105 				move(ox, oy);
    106 				fillstart(p->o_fillval);
    107 			}
    108 			if (p->o_attr & HEAD1)
    109 				arrow(x1 - (y1 - oy), y1 + (x1 - ox),
    110 				      x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead);
    111                         if (invis && !fill)
    112                                 /* probably wrong when it's cw */
    113                                 move(x1, y1);
    114                         else
    115 				arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]);
    116 			if (p->o_attr & HEAD2)
    117 				arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
    118 				      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);
    119 			if (fill)
    120 				fillend(vis, fill);
    121 			if (p->o_attr & CW_ARC)
    122 				move(x1, y1);	/* because drawn backwards */
    123 			move(ox, oy);
    124 			dotext(p);
    125 			break;
    126 		case LINE:
    127 		case ARROW:
    128 		case SPLINE:
    129 			if (fill) {
    130 				move(ox, oy);
    131 				fillstart(p->o_fillval);
    132 			}
    133 			if (vis && p->o_attr & HEAD1)
    134 				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);
    135                         if (invis && !fill)
    136                                 move(x1, y1);
    137 			else if (p->o_type == SPLINE)
    138 				spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval);
    139 			else {
    140 				dx = ox;
    141 				dy = oy;
    142 				for (k=0, j=5; k < p->o_val[4]; k++, j += 2) {
    143 					ndx = dx + p->o_val[j];
    144 					ndy = dy + p->o_val[j+1];
    145 					if (p->o_attr & (DOTBIT|DASHBIT))
    146 						dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval);
    147 					else
    148 						line(dx, dy, ndx, ndy);
    149 					dx = ndx;
    150 					dy = ndy;
    151 				}
    152 			}
    153 			if (vis && p->o_attr & HEAD2) {
    154 				dx = ox;
    155 				dy = oy;
    156 				for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) {
    157 					dx += p->o_val[j];
    158 					dy += p->o_val[j+1];
    159 				}
    160 				arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
    161 			}
    162 			if (fill)
    163 				fillend(vis, fill);
    164 			move((ox + x1)/2, (oy + y1)/2);	/* center */
    165 			dotext(p);
    166 			break;
    167 		case MOVE:
    168 			move(ox, oy);
    169 			break;
    170 		case TEXT:
    171 			move(ox, oy);
    172                         if (vis)
    173 				dotext(p);
    174 			break;
    175 		}
    176 	}
    177 }
    178 
    179 void dotline(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted line */
    180 {
    181 	static double prevval = 0.05;	/* 20 per inch by default */
    182 	int i, numdots;
    183 	double a, b, dx, dy;
    184 
    185 	b = 0.0; /* Botch? (gcc) */
    186 
    187 	if (ddval == 0)
    188 		ddval = prevval;
    189 	prevval = ddval;
    190 	/* don't save dot/dash value */
    191 	dx = x1 - x0;
    192 	dy = y1 - y0;
    193 	if (ddtype & DOTBIT) {
    194 		numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
    195 		if (numdots > 0)
    196 			for (i = 0; i <= numdots; i++) {
    197 				a = (double) i / (double) numdots;
    198 				move(x0 + (a * dx), y0 + (a * dy));
    199 				dot();
    200 			}
    201 	} else if (ddtype & DASHBIT) {
    202 		double d, dashsize, spacesize;
    203 		d = sqrt(dx*dx + dy*dy);
    204 		if (d <= 2 * prevval) {
    205 			line(x0, y0, x1, y1);
    206 			return;
    207 		}
    208 		numdots = d / (2 * prevval) + 1;	/* ceiling */
    209 		dashsize = prevval;
    210 		spacesize = (d - numdots * dashsize) / (numdots - 1);
    211 		for (i = 0; i < numdots-1; i++) {
    212 			a = i * (dashsize + spacesize) / d;
    213 			b = a + dashsize / d;
    214 			line(x0 + (a*dx), y0 + (a*dy), x0 + (b*dx), y0 + (b*dy));
    215 			a = b;
    216 			b = a + spacesize / d;
    217 			move(x0 + (a*dx), y0 + (a*dy));
    218 		}
    219 		line(x0 + (b * dx), y0 + (b * dy), x1, y1);
    220 	}
    221 	prevval = 0.05;
    222 }
    223 
    224 void dotbox(double x0, double y0, double x1, double y1, int ddtype, double ddval)	/* dotted or dashed box */
    225 {
    226 	dotline(x0, y0, x1, y0, ddtype, ddval);
    227 	dotline(x1, y0, x1, y1, ddtype, ddval);
    228 	dotline(x1, y1, x0, y1, ddtype, ddval);
    229 	dotline(x0, y1, x0, y0, ddtype, ddval);
    230 }
    231 
    232 void dotext(obj *p)	/* print text strings of p in proper vertical spacing */
    233 {
    234 	int i, nhalf;
    235 	void label(char *, int, int);
    236 
    237 	nhalf = p->o_nt2 - p->o_nt1 - 1;
    238 	for (i = p->o_nt1; i < p->o_nt2; i++) {
    239 		label(text[i].t_val, text[i].t_type, nhalf);
    240 		nhalf -= 2;
    241 	}
    242 }