1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <bio.h> 4*219b2ee8SDavid du Colombier #include "../common/common.h" 5*219b2ee8SDavid du Colombier #include "tr2post.h" 6*219b2ee8SDavid du Colombier 7*219b2ee8SDavid du Colombier BOOLEAN drawflag = FALSE; 8*219b2ee8SDavid du Colombier 9*219b2ee8SDavid du Colombier void 10*219b2ee8SDavid du Colombier cover(double x, double y) { 11*219b2ee8SDavid du Colombier } 12*219b2ee8SDavid du Colombier 13*219b2ee8SDavid du Colombier void 14*219b2ee8SDavid du Colombier drawspline(Biobufhdr *Bp, int flag) { /* flag!=1 connect end points */ 15*219b2ee8SDavid du Colombier int x[100], y[100]; 16*219b2ee8SDavid du Colombier int i, N; 17*219b2ee8SDavid du Colombier /* 18*219b2ee8SDavid du Colombier * 19*219b2ee8SDavid du Colombier * Spline drawing routine for Postscript printers. The complicated stuff is 20*219b2ee8SDavid du Colombier * handled by procedure Ds, which should be defined in the library file. I've 21*219b2ee8SDavid du Colombier * seen wrong implementations of troff's spline drawing, so fo the record I'll 22*219b2ee8SDavid du Colombier * write down the parametric equations and the necessary conversions to Bezier 23*219b2ee8SDavid du Colombier * cubic splines (as used in Postscript). 24*219b2ee8SDavid du Colombier * 25*219b2ee8SDavid du Colombier * 26*219b2ee8SDavid du Colombier * Parametric equation (x coordinate only): 27*219b2ee8SDavid du Colombier * 28*219b2ee8SDavid du Colombier * 29*219b2ee8SDavid du Colombier * (x2 - 2 * x1 + x0) 2 (x0 + x1) 30*219b2ee8SDavid du Colombier * x = ------------------ * t + (x1 - x0) * t + --------- 31*219b2ee8SDavid du Colombier * 2 2 32*219b2ee8SDavid du Colombier * 33*219b2ee8SDavid du Colombier * 34*219b2ee8SDavid du Colombier * The coefficients in the Bezier cubic are, 35*219b2ee8SDavid du Colombier * 36*219b2ee8SDavid du Colombier * 37*219b2ee8SDavid du Colombier * A = 0 38*219b2ee8SDavid du Colombier * B = (x2 - 2 * x1 + x0) / 2 39*219b2ee8SDavid du Colombier * C = x1 - x0 40*219b2ee8SDavid du Colombier * 41*219b2ee8SDavid du Colombier * 42*219b2ee8SDavid du Colombier * while the current point is, 43*219b2ee8SDavid du Colombier * 44*219b2ee8SDavid du Colombier * current-point = (x0 + x1) / 2 45*219b2ee8SDavid du Colombier * 46*219b2ee8SDavid du Colombier * Using the relationships given in the Postscript manual (page 121) it's easy to 47*219b2ee8SDavid du Colombier * see that the control points are given by, 48*219b2ee8SDavid du Colombier * 49*219b2ee8SDavid du Colombier * 50*219b2ee8SDavid du Colombier * x0' = (x0 + 5 * x1) / 6 51*219b2ee8SDavid du Colombier * x1' = (x2 + 5 * x1) / 6 52*219b2ee8SDavid du Colombier * x2' = (x1 + x2) / 2 53*219b2ee8SDavid du Colombier * 54*219b2ee8SDavid du Colombier * 55*219b2ee8SDavid du Colombier * where the primed variables are the ones used by curveto. The calculations 56*219b2ee8SDavid du Colombier * shown above are done in procedure Ds using the coordinates set up in both 57*219b2ee8SDavid du Colombier * the x[] and y[] arrays. 58*219b2ee8SDavid du Colombier * 59*219b2ee8SDavid du Colombier * A simple test of whether your spline drawing is correct would be to use cip 60*219b2ee8SDavid du Colombier * to draw a spline and some tangent lines at appropriate points and then print 61*219b2ee8SDavid du Colombier * the file. 62*219b2ee8SDavid du Colombier * 63*219b2ee8SDavid du Colombier */ 64*219b2ee8SDavid du Colombier 65*219b2ee8SDavid du Colombier for (N=2; N<sizeof(x)/sizeof(x[0]); N++) 66*219b2ee8SDavid du Colombier if (Bgetfield(Bp, 'd', &x[N], 0)<=0 || Bgetfield(Bp, 'd', &y[N], 0)<=0) 67*219b2ee8SDavid du Colombier break; 68*219b2ee8SDavid du Colombier 69*219b2ee8SDavid du Colombier x[0] = x[1] = hpos; 70*219b2ee8SDavid du Colombier y[0] = y[1] = vpos; 71*219b2ee8SDavid du Colombier 72*219b2ee8SDavid du Colombier for (i = 1; i < N; i++) { 73*219b2ee8SDavid du Colombier x[i+1] += x[i]; 74*219b2ee8SDavid du Colombier y[i+1] += y[i]; 75*219b2ee8SDavid du Colombier } 76*219b2ee8SDavid du Colombier 77*219b2ee8SDavid du Colombier x[N] = x[N-1]; 78*219b2ee8SDavid du Colombier y[N] = y[N-1]; 79*219b2ee8SDavid du Colombier 80*219b2ee8SDavid du Colombier for (i = ((flag!=1)?0:1); i < ((flag!=1)?N-1:N-2); i++) { 81*219b2ee8SDavid du Colombier endstring(); 82*219b2ee8SDavid du Colombier if (pageon()) 83*219b2ee8SDavid du Colombier Bprint(Bstdout, "%d %d %d %d %d %d Ds\n", x[i], y[i], x[i+1], y[i+1], x[i+2], y[i+2]); 84*219b2ee8SDavid du Colombier /* if (dobbox == TRUE) { /* could be better */ 85*219b2ee8SDavid du Colombier /* cover((double)(x[i] + x[i+1])/2,(double)-(y[i] + y[i+1])/2); 86*219b2ee8SDavid du Colombier /* cover((double)x[i+1], (double)-y[i+1]); 87*219b2ee8SDavid du Colombier /* cover((double)(x[i+1] + x[i+2])/2, (double)-(y[i+1] + y[i+2])/2); 88*219b2ee8SDavid du Colombier /* } 89*219b2ee8SDavid du Colombier */ 90*219b2ee8SDavid du Colombier } 91*219b2ee8SDavid du Colombier 92*219b2ee8SDavid du Colombier hpos = x[N]; /* where troff expects to be */ 93*219b2ee8SDavid du Colombier vpos = y[N]; 94*219b2ee8SDavid du Colombier } 95*219b2ee8SDavid du Colombier 96*219b2ee8SDavid du Colombier void 97*219b2ee8SDavid du Colombier draw(Biobufhdr *Bp) { 98*219b2ee8SDavid du Colombier 99*219b2ee8SDavid du Colombier int r, x1, y1, x2, y2, i; 100*219b2ee8SDavid du Colombier int d1, d2; 101*219b2ee8SDavid du Colombier 102*219b2ee8SDavid du Colombier drawflag = TRUE; 103*219b2ee8SDavid du Colombier r = Bgetrune(Bp); 104*219b2ee8SDavid du Colombier switch(r) { 105*219b2ee8SDavid du Colombier case 'l': 106*219b2ee8SDavid du Colombier if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0)<=0 || Bgetfield(Bp, 'r', &i, 0)<=0) 107*219b2ee8SDavid du Colombier error(FATAL, "draw line function, destination coordinates not found.\n"); 108*219b2ee8SDavid du Colombier 109*219b2ee8SDavid du Colombier endstring(); 110*219b2ee8SDavid du Colombier if (pageon()) 111*219b2ee8SDavid du Colombier Bprint(Bstdout, "%d %d %d %d Dl\n", hpos, vpos, hpos+x1, vpos+y1); 112*219b2ee8SDavid du Colombier hpos += x1; 113*219b2ee8SDavid du Colombier vpos += y1; 114*219b2ee8SDavid du Colombier break; 115*219b2ee8SDavid du Colombier case 'c': 116*219b2ee8SDavid du Colombier if (Bgetfield(Bp, 'd', &d1, 0)<=0) 117*219b2ee8SDavid du Colombier error(FATAL, "draw circle function, diameter coordinates not found.\n"); 118*219b2ee8SDavid du Colombier 119*219b2ee8SDavid du Colombier endstring(); 120*219b2ee8SDavid du Colombier if (pageon()) 121*219b2ee8SDavid du Colombier Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d1); 122*219b2ee8SDavid du Colombier hpos += d1; 123*219b2ee8SDavid du Colombier break; 124*219b2ee8SDavid du Colombier case 'e': 125*219b2ee8SDavid du Colombier if (Bgetfield(Bp, 'd', &d1, 0)<=0 || Bgetfield(Bp, 'd', &d2, 0)<=0) 126*219b2ee8SDavid du Colombier error(FATAL, "draw ellipse function, diameter coordinates not found.\n"); 127*219b2ee8SDavid du Colombier 128*219b2ee8SDavid du Colombier endstring(); 129*219b2ee8SDavid du Colombier if (pageon()) 130*219b2ee8SDavid du Colombier Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d2); 131*219b2ee8SDavid du Colombier hpos += d1; 132*219b2ee8SDavid du Colombier break; 133*219b2ee8SDavid du Colombier case 'a': 134*219b2ee8SDavid du Colombier if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0)<=0 || Bgetfield(Bp, 'd', &x2, 0)<=0 || Bgetfield(Bp, 'd', &y2, 0)<=0) 135*219b2ee8SDavid du Colombier error(FATAL, "draw arc function, coordinates not found.\n"); 136*219b2ee8SDavid du Colombier 137*219b2ee8SDavid du Colombier endstring(); 138*219b2ee8SDavid du Colombier if (pageon()) 139*219b2ee8SDavid du Colombier Bprint(Bstdout, "%d %d %d %d %d %d Da\n", hpos, vpos, x1, y1, x2, y2); 140*219b2ee8SDavid du Colombier hpos += x1 + x2; 141*219b2ee8SDavid du Colombier vpos += y1 + y2; 142*219b2ee8SDavid du Colombier break; 143*219b2ee8SDavid du Colombier case 'q': 144*219b2ee8SDavid du Colombier drawspline(Bp, 1); 145*219b2ee8SDavid du Colombier break; 146*219b2ee8SDavid du Colombier case '~': 147*219b2ee8SDavid du Colombier drawspline(Bp, 2); 148*219b2ee8SDavid du Colombier break; 149*219b2ee8SDavid du Colombier default: 150*219b2ee8SDavid du Colombier error(FATAL, "unknown draw function <%c>\n", r); 151*219b2ee8SDavid du Colombier break; 152*219b2ee8SDavid du Colombier } 153*219b2ee8SDavid du Colombier } 154