1 #ifndef lint 2 static char sccsid[] = "@(#)pltroff.c 3.2 (CWI) 85/08/15"; 3 #endif lint 4 5 #include <stdio.h> 6 #include <math.h> 7 #include "pic.h" 8 extern int dbg; 9 10 #define abs(n) (n >= 0 ? n : -(n)) 11 #define max(x,y) ((x)>(y) ? (x) : (y)) 12 13 char *textshift = "\\v'.2m'"; /* move text this far down */ 14 15 /* scaling stuff defined by s command as X0,Y0 to X1,Y1 */ 16 /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */ 17 /* default output is 6x6 inches */ 18 19 20 float xscale; 21 float yscale; 22 23 float hpos = 0; /* current horizontal position in output coordinate system */ 24 float vpos = 0; /* current vertical position; 0 is top of page */ 25 26 float htrue = 0; /* where we really are */ 27 float vtrue = 0; 28 29 float X0, Y0; /* left bottom of input */ 30 float X1, Y1; /* right top of input */ 31 32 float hmax; /* right end of output */ 33 float vmax; /* top of output (down is positive) */ 34 35 extern float deltx; 36 extern float delty; 37 extern float xmin, ymin, xmax, ymax; 38 39 float xconv(), yconv(), xsc(), ysc(); 40 41 openpl(s) /* initialize device */ 42 char *s; /* residue of .PS invocation line */ 43 { 44 float maxdelt; 45 46 hpos = vpos = 0; 47 if (deltx > 8.5 || delty > 11) { /* 8.5x11 inches max */ 48 fprintf(stderr, "pic: %g X %g picture shrunk to", deltx, delty); 49 maxdelt = max(deltx, delty); 50 deltx *= 7/maxdelt; 51 delty *= 7/maxdelt; 52 fprintf(stderr, " %g X %g\n", deltx, delty); 53 } 54 space(xmin, ymin, xmax, ymax); 55 printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax); 56 printf("... %.3fi %.3fi %.3fi %.3fi\n", 57 xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax)); 58 printf(".nr 00 \\n(.u\n"); 59 printf(".nf\n"); 60 printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s); 61 /* assumes \n comes as part of s */ 62 } 63 64 space(x0, y0, x1, y1) /* set limits of page */ 65 float x0, y0, x1, y1; 66 { 67 X0 = x0; 68 Y0 = y0; 69 X1 = x1; 70 Y1 = y1; 71 xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0); 72 yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0); 73 } 74 75 float xconv(x) /* convert x from external to internal form */ 76 float x; 77 { 78 return (x-X0) * xscale; 79 } 80 81 float xsc(x) /* convert x from external to internal form, scaling only */ 82 float x; 83 { 84 85 return (x) * xscale; 86 } 87 88 float yconv(y) /* convert y from external to internal form */ 89 float y; 90 { 91 return (Y1-y) * yscale; 92 } 93 94 float ysc(y) /* convert y from external to internal form, scaling only */ 95 float y; 96 { 97 return (y) * yscale; 98 } 99 100 closepl(type) /* clean up after finished */ 101 int type; 102 { 103 movehv(0.0, 0.0); /* get back to where we started */ 104 if (type == 'F') 105 printf(".PF\n"); 106 else { 107 printf(".sp 1+%.3fi\n", yconv(ymin)); 108 printf(".PE\n"); 109 } 110 printf(".if \\n(00 .fi\n"); 111 } 112 113 move(x, y) /* go to position x, y in external coords */ 114 float x, y; 115 { 116 hgoto(xconv(x)); 117 vgoto(yconv(y)); 118 } 119 120 movehv(h, v) /* go to internal position h, v */ 121 float h, v; 122 { 123 hgoto(h); 124 vgoto(v); 125 } 126 127 hmot(n) /* generate n units of horizontal motion */ 128 float n; 129 { 130 hpos += n; 131 } 132 133 vmot(n) /* generate n units of vertical motion */ 134 float n; 135 { 136 vpos += n; 137 } 138 139 hgoto(n) 140 float n; 141 { 142 hpos = n; 143 } 144 145 vgoto(n) 146 float n; 147 { 148 vpos = n; 149 } 150 151 hvflush() /* get to proper point for output */ 152 { 153 if (hpos != htrue) { 154 printf("\\h'%.3fi'", hpos - htrue); 155 htrue = hpos; 156 } 157 if (vpos != vtrue) { 158 printf("\\v'%.3fi'", vpos - vtrue); 159 vtrue = vpos; 160 } 161 } 162 163 flyback() /* return to upper left corner (entry point) */ 164 { 165 printf(".sp -1\n"); 166 htrue = vtrue = 0; 167 } 168 169 troff(s) /* output troff right here */ 170 char *s; 171 { 172 printf("%s\n", s); 173 } 174 175 label(s, t, nh) /* text s of type t nh half-lines up */ 176 char *s; 177 int t, nh; 178 { 179 int q; 180 char *p; 181 182 hvflush(); 183 dprintf("label: %s %o %d\n", s, t, nh); 184 printf("%s", textshift); /* shift down and left */ 185 if (t & ABOVE) 186 nh++; 187 else if (t & BELOW) 188 nh--; 189 if (nh) 190 printf("\\v'%du*\\n(.vu/2u'", -nh); 191 /* just in case the text contains a quote: */ 192 q = 0; 193 for (p = s; *p; p++) 194 if (*p == '\'') { 195 q = 1; 196 break; 197 } 198 t &= ~(ABOVE|BELOW); 199 if (t & LJUST) { 200 printf("%s", s); 201 } else if (t & RJUST) { 202 if (q) 203 printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s); 204 else 205 printf("\\h'-\\w'%s'u'%s", s, s); 206 } else { /* CENTER */ 207 if (q) 208 printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts", s, s, s); 209 else 210 printf("\\h'-\\w'%s'u/2u'%s\\h'-\\w'%s'u/2u'", s, s, s); 211 } 212 printf("\n"); 213 flyback(); 214 } 215 216 line(x0, y0, x1, y1) /* draw line from x0,y0 to x1,y1 */ 217 float x0, y0, x1, y1; 218 { 219 move(x0, y0); 220 cont(x1, y1); 221 } 222 223 arrow(x0, y0, x1, y1, w, h, ang, nhead) /* draw arrow (without shaft) */ 224 float x0, y0, x1, y1, w, h, ang; /* head wid w, len h, rotated ang */ 225 int nhead; /* and drawn with nhead lines */ 226 { 227 double alpha, rot, drot, hyp; 228 float dx, dy; 229 int i; 230 231 rot = atan2(w / 2, h); 232 hyp = sqrt(w/2 * w/2 + h * h); 233 alpha = atan2(y1-y0, x1-x0) + ang; 234 if (nhead < 2) 235 nhead = 2; 236 dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha); 237 for (i = nhead-1; i >= 0; i--) { 238 drot = 2 * rot / (float) (nhead-1) * (float) i; 239 dx = hyp * cos(alpha + PI - rot + drot); 240 dy = hyp * sin(alpha + PI - rot + drot); 241 dprintf("dx,dy = %g,%g\n", dx, dy); 242 line(x1+dx, y1+dy, x1, y1); 243 } 244 } 245 246 box(x0, y0, x1, y1) 247 float x0, y0, x1, y1; 248 { 249 move(x0, y0); 250 cont(x0, y1); 251 cont(x1, y1); 252 cont(x1, y0); 253 cont(x0, y0); 254 } 255 256 cont(x, y) /* continue line from here to x,y */ 257 float x, y; 258 { 259 float h1, v1; 260 float dh, dv; 261 262 h1 = xconv(x); 263 v1 = yconv(y); 264 dh = h1 - hpos; 265 dv = v1 - vpos; 266 hvflush(); 267 printf("\\D'l%.3fi %.3fi'\n", dh, dv); 268 flyback(); /* expensive */ 269 hpos = h1; 270 vpos = v1; 271 } 272 273 circle(x, y, r) 274 float x, y, r; 275 { 276 move(x-r, y); 277 hvflush(); 278 printf("\\D'c%.3fi'\n", xsc(2 * r)); 279 flyback(); 280 } 281 282 spline(x, y, n, p, dashed, ddval) 283 float x, y, *p; 284 float n; /* sic */ 285 int dashed; 286 float ddval; 287 { 288 int i; 289 float dx, dy; 290 float xerr, yerr; 291 292 if (dashed && ddval) 293 printf(".nr 99 %.3fi\n", ddval); 294 move(x, y); 295 hvflush(); 296 xerr = yerr = 0.0; 297 if (dashed) { 298 if (ddval) 299 printf("\\X'Pd \\n(99'\\D'q 0 0"); 300 else 301 printf("\\X'Pd'\\D'q 0 0"); 302 } else 303 printf("\\D'~"); 304 for (i = 0; i < 2 * n; i += 2) { 305 dx = xsc(xerr += p[i]); 306 xerr -= dx/xscale; 307 dy = ysc(yerr += p[i+1]); 308 yerr -= dy/yscale; 309 printf(" %.3fi %.3fi", dx, -dy); /* WATCH SIGN */ 310 } 311 if (dashed) 312 printf(" 0 0'\\X'Ps'\n"); 313 else 314 printf("'\n"); 315 flyback(); 316 } 317 318 ellipse(x, y, r1, r2) 319 float x, y, r1, r2; 320 { 321 float ir1, ir2; 322 323 move(x-r1, y); 324 hvflush(); 325 ir1 = xsc(r1); 326 ir2 = ysc(r2); 327 printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2)); 328 flyback(); 329 } 330 331 arc(x, y, x0, y0, x1, y1) /* draw arc with center x,y */ 332 float x, y, x0, y0, x1, y1; 333 { 334 335 move(x0, y0); 336 hvflush(); 337 printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n", 338 xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y)); /* WATCH SIGNS */ 339 flyback(); 340 } 341 342 dot() { 343 hvflush(); 344 /* what character to draw here depends on what's available. */ 345 /* on the 202, l. is good but small. */ 346 /* in general, use a smaller, shifted period and hope */ 347 348 printf("\\&\\f1\\h'-.05m'\\v'.03m'\\s-3.\\s+3\\fP\n"); 349 flyback(); 350 } 351