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