1*7dd7cddfSDavid du Colombier #include "../lib9.h" 2*7dd7cddfSDavid du Colombier 3*7dd7cddfSDavid du Colombier #include "../libdraw/draw.h" 4*7dd7cddfSDavid du Colombier #include "../libmemdraw/memdraw.h" 5*7dd7cddfSDavid du Colombier #include "../libmemlayer/memlayer.h" 6*7dd7cddfSDavid du Colombier 7*7dd7cddfSDavid du Colombier enum 8*7dd7cddfSDavid du Colombier { 9*7dd7cddfSDavid du Colombier Arrow1 = 8, 10*7dd7cddfSDavid du Colombier Arrow2 = 10, 11*7dd7cddfSDavid du Colombier Arrow3 = 3 12*7dd7cddfSDavid du Colombier }; 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier /* 15*7dd7cddfSDavid du Colombier * not used 16*7dd7cddfSDavid du Colombier static 17*7dd7cddfSDavid du Colombier int 18*7dd7cddfSDavid du Colombier lmin(int a, int b) 19*7dd7cddfSDavid du Colombier { 20*7dd7cddfSDavid du Colombier if(a < b) 21*7dd7cddfSDavid du Colombier return a; 22*7dd7cddfSDavid du Colombier return b; 23*7dd7cddfSDavid du Colombier } 24*7dd7cddfSDavid du Colombier */ 25*7dd7cddfSDavid du Colombier 26*7dd7cddfSDavid du Colombier static 27*7dd7cddfSDavid du Colombier int 28*7dd7cddfSDavid du Colombier lmax(int a, int b) 29*7dd7cddfSDavid du Colombier { 30*7dd7cddfSDavid du Colombier if(a > b) 31*7dd7cddfSDavid du Colombier return a; 32*7dd7cddfSDavid du Colombier return b; 33*7dd7cddfSDavid du Colombier } 34*7dd7cddfSDavid du Colombier 35*7dd7cddfSDavid du Colombier /* 36*7dd7cddfSDavid du Colombier * Rather than line clip, we run the Bresenham loop over the full line, 37*7dd7cddfSDavid du Colombier * and clip on each pixel. This is more expensive but means that 38*7dd7cddfSDavid du Colombier * lines look the same regardless of how the windowing has tiled them. 39*7dd7cddfSDavid du Colombier * For speed, we check for clipping outside the loop and make the 40*7dd7cddfSDavid du Colombier * test easy when possible. 41*7dd7cddfSDavid du Colombier */ 42*7dd7cddfSDavid du Colombier 43*7dd7cddfSDavid du Colombier #ifdef NOTUSED 44*7dd7cddfSDavid du Colombier static 45*7dd7cddfSDavid du Colombier void 46*7dd7cddfSDavid du Colombier horline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) 47*7dd7cddfSDavid du Colombier { 48*7dd7cddfSDavid du Colombier int x, y, dy, deltay, deltax, maxx; 49*7dd7cddfSDavid du Colombier int dd, easy, e, bpp, m, m0; 50*7dd7cddfSDavid du Colombier uchar *d; 51*7dd7cddfSDavid du Colombier 52*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 53*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 54*7dd7cddfSDavid du Colombier dd = dst->width*sizeof(ulong); 55*7dd7cddfSDavid du Colombier dy = 1; 56*7dd7cddfSDavid du Colombier if(deltay < 0){ 57*7dd7cddfSDavid du Colombier dd = -dd; 58*7dd7cddfSDavid du Colombier deltay = -deltay; 59*7dd7cddfSDavid du Colombier dy = -1; 60*7dd7cddfSDavid du Colombier } 61*7dd7cddfSDavid du Colombier maxx = lmin(p1.x, clipr.max.x-1); 62*7dd7cddfSDavid du Colombier bpp = dst->depth; 63*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 64*7dd7cddfSDavid du Colombier m = m0 >> (p0.x&(7/dst->depth))*bpp; 65*7dd7cddfSDavid du Colombier easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); 66*7dd7cddfSDavid du Colombier e = 2*deltay - deltax; 67*7dd7cddfSDavid du Colombier y = p0.y; 68*7dd7cddfSDavid du Colombier d = byteaddr(dst, p0); 69*7dd7cddfSDavid du Colombier deltay *= 2; 70*7dd7cddfSDavid du Colombier deltax = deltay - 2*deltax; 71*7dd7cddfSDavid du Colombier for(x=p0.x; x<=maxx; x++){ 72*7dd7cddfSDavid du Colombier if(easy || (clipr.min.x<=x && clipr.min.y<=y && y<clipr.max.y)) 73*7dd7cddfSDavid du Colombier *d ^= (*d^srcval) & m; 74*7dd7cddfSDavid du Colombier if(e > 0){ 75*7dd7cddfSDavid du Colombier y += dy; 76*7dd7cddfSDavid du Colombier d += dd; 77*7dd7cddfSDavid du Colombier e += deltax; 78*7dd7cddfSDavid du Colombier }else 79*7dd7cddfSDavid du Colombier e += deltay; 80*7dd7cddfSDavid du Colombier d++; 81*7dd7cddfSDavid du Colombier m >>= bpp; 82*7dd7cddfSDavid du Colombier if(m == 0) 83*7dd7cddfSDavid du Colombier m = m0; 84*7dd7cddfSDavid du Colombier } 85*7dd7cddfSDavid du Colombier } 86*7dd7cddfSDavid du Colombier 87*7dd7cddfSDavid du Colombier static 88*7dd7cddfSDavid du Colombier void 89*7dd7cddfSDavid du Colombier verline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) 90*7dd7cddfSDavid du Colombier { 91*7dd7cddfSDavid du Colombier int x, y, deltay, deltax, maxy; 92*7dd7cddfSDavid du Colombier int easy, e, bpp, m, m0, dd; 93*7dd7cddfSDavid du Colombier uchar *d; 94*7dd7cddfSDavid du Colombier 95*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 96*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 97*7dd7cddfSDavid du Colombier dd = 1; 98*7dd7cddfSDavid du Colombier if(deltax < 0){ 99*7dd7cddfSDavid du Colombier dd = -1; 100*7dd7cddfSDavid du Colombier deltax = -deltax; 101*7dd7cddfSDavid du Colombier } 102*7dd7cddfSDavid du Colombier maxy = lmin(p1.y, clipr.max.y-1); 103*7dd7cddfSDavid du Colombier bpp = dst->depth; 104*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 105*7dd7cddfSDavid du Colombier m = m0 >> (p0.x&(7/dst->depth))*bpp; 106*7dd7cddfSDavid du Colombier easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); 107*7dd7cddfSDavid du Colombier e = 2*deltax - deltay; 108*7dd7cddfSDavid du Colombier x = p0.x; 109*7dd7cddfSDavid du Colombier d = byteaddr(dst, p0); 110*7dd7cddfSDavid du Colombier deltax *= 2; 111*7dd7cddfSDavid du Colombier deltay = deltax - 2*deltay; 112*7dd7cddfSDavid du Colombier for(y=p0.y; y<=maxy; y++){ 113*7dd7cddfSDavid du Colombier if(easy || (clipr.min.y<=y && clipr.min.x<=x && x<clipr.max.x)) 114*7dd7cddfSDavid du Colombier *d ^= (*d^srcval) & m; 115*7dd7cddfSDavid du Colombier if(e > 0){ 116*7dd7cddfSDavid du Colombier x += dd; 117*7dd7cddfSDavid du Colombier d += dd; 118*7dd7cddfSDavid du Colombier e += deltay; 119*7dd7cddfSDavid du Colombier }else 120*7dd7cddfSDavid du Colombier e += deltax; 121*7dd7cddfSDavid du Colombier d += dst->width*sizeof(ulong); 122*7dd7cddfSDavid du Colombier m >>= bpp; 123*7dd7cddfSDavid du Colombier if(m == 0) 124*7dd7cddfSDavid du Colombier m = m0; 125*7dd7cddfSDavid du Colombier } 126*7dd7cddfSDavid du Colombier } 127*7dd7cddfSDavid du Colombier 128*7dd7cddfSDavid du Colombier static 129*7dd7cddfSDavid du Colombier void 130*7dd7cddfSDavid du Colombier horliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) 131*7dd7cddfSDavid du Colombier { 132*7dd7cddfSDavid du Colombier int x, y, sx, sy, deltay, deltax, minx, maxx; 133*7dd7cddfSDavid du Colombier int bpp, m, m0; 134*7dd7cddfSDavid du Colombier uchar *d, *s; 135*7dd7cddfSDavid du Colombier 136*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 137*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 138*7dd7cddfSDavid du Colombier sx = drawreplxy(src->r.min.x, src->r.max.x, p0.x+dsrc.x); 139*7dd7cddfSDavid du Colombier minx = lmax(p0.x, clipr.min.x); 140*7dd7cddfSDavid du Colombier maxx = lmin(p1.x, clipr.max.x-1); 141*7dd7cddfSDavid du Colombier bpp = dst->depth; 142*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 143*7dd7cddfSDavid du Colombier m = m0 >> (minx&(7/dst->depth))*bpp; 144*7dd7cddfSDavid du Colombier for(x=minx; x<=maxx; x++){ 145*7dd7cddfSDavid du Colombier y = p0.y + (deltay*(x-p0.x)+deltax/2)/deltax; 146*7dd7cddfSDavid du Colombier if(clipr.min.y<=y && y<clipr.max.y){ 147*7dd7cddfSDavid du Colombier d = byteaddr(dst, Pt(x, y)); 148*7dd7cddfSDavid du Colombier sy = drawreplxy(src->r.min.y, src->r.max.y, y+dsrc.y); 149*7dd7cddfSDavid du Colombier s = byteaddr(src, Pt(sx, sy)); 150*7dd7cddfSDavid du Colombier *d ^= (*d^*s) & m; 151*7dd7cddfSDavid du Colombier } 152*7dd7cddfSDavid du Colombier if(++sx >= src->r.max.x) 153*7dd7cddfSDavid du Colombier sx = src->r.min.x; 154*7dd7cddfSDavid du Colombier m >>= bpp; 155*7dd7cddfSDavid du Colombier if(m == 0) 156*7dd7cddfSDavid du Colombier m = m0; 157*7dd7cddfSDavid du Colombier } 158*7dd7cddfSDavid du Colombier } 159*7dd7cddfSDavid du Colombier 160*7dd7cddfSDavid du Colombier static 161*7dd7cddfSDavid du Colombier void 162*7dd7cddfSDavid du Colombier verliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) 163*7dd7cddfSDavid du Colombier { 164*7dd7cddfSDavid du Colombier int x, y, sx, sy, deltay, deltax, miny, maxy; 165*7dd7cddfSDavid du Colombier int bpp, m, m0; 166*7dd7cddfSDavid du Colombier uchar *d, *s; 167*7dd7cddfSDavid du Colombier 168*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 169*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 170*7dd7cddfSDavid du Colombier sy = drawreplxy(src->r.min.y, src->r.max.y, p0.y+dsrc.y); 171*7dd7cddfSDavid du Colombier miny = lmax(p0.y, clipr.min.y); 172*7dd7cddfSDavid du Colombier maxy = lmin(p1.y, clipr.max.y-1); 173*7dd7cddfSDavid du Colombier bpp = dst->depth; 174*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 175*7dd7cddfSDavid du Colombier for(y=miny; y<=maxy; y++){ 176*7dd7cddfSDavid du Colombier if(deltay == 0) /* degenerate line */ 177*7dd7cddfSDavid du Colombier x = p0.x; 178*7dd7cddfSDavid du Colombier else 179*7dd7cddfSDavid du Colombier x = p0.x + (deltax*(y-p0.y)+deltay/2)/deltay; 180*7dd7cddfSDavid du Colombier if(clipr.min.x<=x && x<clipr.max.x){ 181*7dd7cddfSDavid du Colombier m = m0 >> (x&(7/dst->depth))*bpp; 182*7dd7cddfSDavid du Colombier d = byteaddr(dst, Pt(x, y)); 183*7dd7cddfSDavid du Colombier sx = drawreplxy(src->r.min.x, src->r.max.x, x+dsrc.x); 184*7dd7cddfSDavid du Colombier s = byteaddr(src, Pt(sx, sy)); 185*7dd7cddfSDavid du Colombier *d ^= (*d^*s) & m; 186*7dd7cddfSDavid du Colombier } 187*7dd7cddfSDavid du Colombier if(++sy >= src->r.max.y) 188*7dd7cddfSDavid du Colombier sy = src->r.min.y; 189*7dd7cddfSDavid du Colombier } 190*7dd7cddfSDavid du Colombier } 191*7dd7cddfSDavid du Colombier 192*7dd7cddfSDavid du Colombier static 193*7dd7cddfSDavid du Colombier void 194*7dd7cddfSDavid du Colombier horline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) 195*7dd7cddfSDavid du Colombier { 196*7dd7cddfSDavid du Colombier int x, y, deltay, deltax, minx, maxx; 197*7dd7cddfSDavid du Colombier int bpp, m, m0; 198*7dd7cddfSDavid du Colombier uchar *d, *s; 199*7dd7cddfSDavid du Colombier 200*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 201*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 202*7dd7cddfSDavid du Colombier minx = lmax(p0.x, clipr.min.x); 203*7dd7cddfSDavid du Colombier maxx = lmin(p1.x, clipr.max.x-1); 204*7dd7cddfSDavid du Colombier bpp = dst->depth; 205*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 206*7dd7cddfSDavid du Colombier m = m0 >> (minx&(7/dst->depth))*bpp; 207*7dd7cddfSDavid du Colombier for(x=minx; x<=maxx; x++){ 208*7dd7cddfSDavid du Colombier y = p0.y + (deltay*(x-p0.x)+deltay/2)/deltax; 209*7dd7cddfSDavid du Colombier if(clipr.min.y<=y && y<clipr.max.y){ 210*7dd7cddfSDavid du Colombier d = byteaddr(dst, Pt(x, y)); 211*7dd7cddfSDavid du Colombier s = byteaddr(src, addpt(dsrc, Pt(x, y))); 212*7dd7cddfSDavid du Colombier *d ^= (*d^*s) & m; 213*7dd7cddfSDavid du Colombier } 214*7dd7cddfSDavid du Colombier m >>= bpp; 215*7dd7cddfSDavid du Colombier if(m == 0) 216*7dd7cddfSDavid du Colombier m = m0; 217*7dd7cddfSDavid du Colombier } 218*7dd7cddfSDavid du Colombier } 219*7dd7cddfSDavid du Colombier 220*7dd7cddfSDavid du Colombier static 221*7dd7cddfSDavid du Colombier void 222*7dd7cddfSDavid du Colombier verline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) 223*7dd7cddfSDavid du Colombier { 224*7dd7cddfSDavid du Colombier int x, y, deltay, deltax, miny, maxy; 225*7dd7cddfSDavid du Colombier int bpp, m, m0; 226*7dd7cddfSDavid du Colombier uchar *d, *s; 227*7dd7cddfSDavid du Colombier 228*7dd7cddfSDavid du Colombier deltax = p1.x - p0.x; 229*7dd7cddfSDavid du Colombier deltay = p1.y - p0.y; 230*7dd7cddfSDavid du Colombier miny = lmax(p0.y, clipr.min.y); 231*7dd7cddfSDavid du Colombier maxy = lmin(p1.y, clipr.max.y-1); 232*7dd7cddfSDavid du Colombier bpp = dst->depth; 233*7dd7cddfSDavid du Colombier m0 = 0xFF^(0xFF>>bpp); 234*7dd7cddfSDavid du Colombier for(y=miny; y<=maxy; y++){ 235*7dd7cddfSDavid du Colombier if(deltay == 0) /* degenerate line */ 236*7dd7cddfSDavid du Colombier x = p0.x; 237*7dd7cddfSDavid du Colombier else 238*7dd7cddfSDavid du Colombier x = p0.x + deltax*(y-p0.y)/deltay; 239*7dd7cddfSDavid du Colombier if(clipr.min.x<=x && x<clipr.max.x){ 240*7dd7cddfSDavid du Colombier m = m0 >> (x&(7/dst->depth))*bpp; 241*7dd7cddfSDavid du Colombier d = byteaddr(dst, Pt(x, y)); 242*7dd7cddfSDavid du Colombier s = byteaddr(src, addpt(dsrc, Pt(x, y))); 243*7dd7cddfSDavid du Colombier *d ^= (*d^*s) & m; 244*7dd7cddfSDavid du Colombier } 245*7dd7cddfSDavid du Colombier } 246*7dd7cddfSDavid du Colombier } 247*7dd7cddfSDavid du Colombier #endif /* NOTUSED */ 248*7dd7cddfSDavid du Colombier 249*7dd7cddfSDavid du Colombier Memimage* 250*7dd7cddfSDavid du Colombier membrush(int radius) 251*7dd7cddfSDavid du Colombier { 252*7dd7cddfSDavid du Colombier static Memimage *brush; 253*7dd7cddfSDavid du Colombier static int brushradius; 254*7dd7cddfSDavid du Colombier 255*7dd7cddfSDavid du Colombier if(brush==nil || brushradius!=radius){ 256*7dd7cddfSDavid du Colombier freememimage(brush); 257*7dd7cddfSDavid du Colombier brush = allocmemimage(Rect(0, 0, 2*radius+1, 2*radius+1), memopaque->chan); 258*7dd7cddfSDavid du Colombier if(brush != nil){ 259*7dd7cddfSDavid du Colombier memfillcolor(brush, DTransparent); /* zeros */ 260*7dd7cddfSDavid du Colombier memellipse(brush, Pt(radius, radius), radius, radius, -1, memopaque, Pt(radius, radius)); 261*7dd7cddfSDavid du Colombier } 262*7dd7cddfSDavid du Colombier brushradius = radius; 263*7dd7cddfSDavid du Colombier } 264*7dd7cddfSDavid du Colombier return brush; 265*7dd7cddfSDavid du Colombier } 266*7dd7cddfSDavid du Colombier 267*7dd7cddfSDavid du Colombier static 268*7dd7cddfSDavid du Colombier void 269*7dd7cddfSDavid du Colombier discend(Point p, int radius, Memimage *dst, Memimage *src, Point dsrc) 270*7dd7cddfSDavid du Colombier { 271*7dd7cddfSDavid du Colombier Memimage *disc; 272*7dd7cddfSDavid du Colombier Rectangle r; 273*7dd7cddfSDavid du Colombier 274*7dd7cddfSDavid du Colombier disc = membrush(radius); 275*7dd7cddfSDavid du Colombier if(disc != nil){ 276*7dd7cddfSDavid du Colombier r.min.x = p.x - radius; 277*7dd7cddfSDavid du Colombier r.min.y = p.y - radius; 278*7dd7cddfSDavid du Colombier r.max.x = p.x + radius+1; 279*7dd7cddfSDavid du Colombier r.max.y = p.y + radius+1; 280*7dd7cddfSDavid du Colombier memdraw(dst, r, src, addpt(r.min, dsrc), disc, Pt(0,0)); 281*7dd7cddfSDavid du Colombier } 282*7dd7cddfSDavid du Colombier } 283*7dd7cddfSDavid du Colombier 284*7dd7cddfSDavid du Colombier static 285*7dd7cddfSDavid du Colombier void 286*7dd7cddfSDavid du Colombier arrowend(Point tip, Point *pp, int end, int sin, int cos, int radius) 287*7dd7cddfSDavid du Colombier { 288*7dd7cddfSDavid du Colombier int x1, x2, x3; 289*7dd7cddfSDavid du Colombier 290*7dd7cddfSDavid du Colombier /* before rotation */ 291*7dd7cddfSDavid du Colombier if(end == Endarrow){ 292*7dd7cddfSDavid du Colombier x1 = Arrow1; 293*7dd7cddfSDavid du Colombier x2 = Arrow2; 294*7dd7cddfSDavid du Colombier x3 = Arrow3; 295*7dd7cddfSDavid du Colombier }else{ 296*7dd7cddfSDavid du Colombier x1 = (end>>5) & 0x1FF; /* distance along line from end of line to tip */ 297*7dd7cddfSDavid du Colombier x2 = (end>>14) & 0x1FF; /* distance along line from barb to tip */ 298*7dd7cddfSDavid du Colombier x3 = (end>>23) & 0x1FF; /* distance perpendicular from edge of line to barb */ 299*7dd7cddfSDavid du Colombier } 300*7dd7cddfSDavid du Colombier 301*7dd7cddfSDavid du Colombier /* comments follow track of right-facing arrowhead */ 302*7dd7cddfSDavid du Colombier pp->x = tip.x+((2*radius+1)*sin/2-x1*cos); /* upper side of shaft */ 303*7dd7cddfSDavid du Colombier pp->y = tip.y-((2*radius+1)*cos/2+x1*sin); 304*7dd7cddfSDavid du Colombier pp++; 305*7dd7cddfSDavid du Colombier pp->x = tip.x+((2*radius+2*x3+1)*sin/2-x2*cos); /* upper barb */ 306*7dd7cddfSDavid du Colombier pp->y = tip.y-((2*radius+2*x3+1)*cos/2+x2*sin); 307*7dd7cddfSDavid du Colombier pp++; 308*7dd7cddfSDavid du Colombier pp->x = tip.x; 309*7dd7cddfSDavid du Colombier pp->y = tip.y; 310*7dd7cddfSDavid du Colombier pp++; 311*7dd7cddfSDavid du Colombier pp->x = tip.x+(-(2*radius+2*x3+1)*sin/2-x2*cos); /* lower barb */ 312*7dd7cddfSDavid du Colombier pp->y = tip.y-(-(2*radius+2*x3+1)*cos/2+x2*sin); 313*7dd7cddfSDavid du Colombier pp++; 314*7dd7cddfSDavid du Colombier pp->x = tip.x+(-(2*radius+1)*sin/2-x1*cos); /* lower side of shaft */ 315*7dd7cddfSDavid du Colombier pp->y = tip.y+((2*radius+1)*cos/2-x1*sin); 316*7dd7cddfSDavid du Colombier } 317*7dd7cddfSDavid du Colombier 318*7dd7cddfSDavid du Colombier void 319*7dd7cddfSDavid du Colombier _memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr) 320*7dd7cddfSDavid du Colombier { 321*7dd7cddfSDavid du Colombier /* 322*7dd7cddfSDavid du Colombier * BUG: We should really really pick off purely horizontal and purely 323*7dd7cddfSDavid du Colombier * vertical lines and handle them separately with calls to memimagedraw 324*7dd7cddfSDavid du Colombier * on rectangles. 325*7dd7cddfSDavid du Colombier */ 326*7dd7cddfSDavid du Colombier 327*7dd7cddfSDavid du Colombier int hor; 328*7dd7cddfSDavid du Colombier int sin, cos, dx, dy, t; 329*7dd7cddfSDavid du Colombier Rectangle oclipr; 330*7dd7cddfSDavid du Colombier Point q, pts[10], *pp, d; 331*7dd7cddfSDavid du Colombier 332*7dd7cddfSDavid du Colombier if(radius < 0) 333*7dd7cddfSDavid du Colombier return; 334*7dd7cddfSDavid du Colombier if(rectclip(&clipr, dst->r) == 0) 335*7dd7cddfSDavid du Colombier return; 336*7dd7cddfSDavid du Colombier if(rectclip(&clipr, dst->clipr) == 0) 337*7dd7cddfSDavid du Colombier return; 338*7dd7cddfSDavid du Colombier d = subpt(sp, p0); 339*7dd7cddfSDavid du Colombier if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0) 340*7dd7cddfSDavid du Colombier return; 341*7dd7cddfSDavid du Colombier if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0) 342*7dd7cddfSDavid du Colombier return; 343*7dd7cddfSDavid du Colombier /* this means that only verline() handles degenerate lines (p0==p1) */ 344*7dd7cddfSDavid du Colombier hor = (abs(p1.x-p0.x) > abs(p1.y-p0.y)); 345*7dd7cddfSDavid du Colombier /* 346*7dd7cddfSDavid du Colombier * Clipping is a little peculiar. We can't use Sutherland-Cohen 347*7dd7cddfSDavid du Colombier * clipping because lines are wide. But this is probably just fine: 348*7dd7cddfSDavid du Colombier * we do all math with the original p0 and p1, but clip when deciding 349*7dd7cddfSDavid du Colombier * what pixels to draw. This means the layer code can call this routine, 350*7dd7cddfSDavid du Colombier * using clipr to define the region being written, and get the same set 351*7dd7cddfSDavid du Colombier * of pixels regardless of the dicing. 352*7dd7cddfSDavid du Colombier */ 353*7dd7cddfSDavid du Colombier if((hor && p0.x>p1.x) || (!hor && p0.y>p1.y)){ 354*7dd7cddfSDavid du Colombier q = p0; 355*7dd7cddfSDavid du Colombier p0 = p1; 356*7dd7cddfSDavid du Colombier p1 = q; 357*7dd7cddfSDavid du Colombier t = end0; 358*7dd7cddfSDavid du Colombier end0 = end1; 359*7dd7cddfSDavid du Colombier end1 = t; 360*7dd7cddfSDavid du Colombier } 361*7dd7cddfSDavid du Colombier 362*7dd7cddfSDavid du Colombier /* Hard: */ 363*7dd7cddfSDavid du Colombier /* draw thick line using polygon fill */ 364*7dd7cddfSDavid du Colombier icossin2(p1.x-p0.x, p1.y-p0.y, &cos, &sin); 365*7dd7cddfSDavid du Colombier dx = (sin*(2*radius+1))/2; 366*7dd7cddfSDavid du Colombier dy = (cos*(2*radius+1))/2; 367*7dd7cddfSDavid du Colombier pp = pts; 368*7dd7cddfSDavid du Colombier oclipr = dst->clipr; 369*7dd7cddfSDavid du Colombier dst->clipr = clipr; 370*7dd7cddfSDavid du Colombier q.x = ICOSSCALE*p0.x+ICOSSCALE/2-cos/2; 371*7dd7cddfSDavid du Colombier q.y = ICOSSCALE*p0.y+ICOSSCALE/2-sin/2; 372*7dd7cddfSDavid du Colombier switch(end0 & 0x1F){ 373*7dd7cddfSDavid du Colombier case Enddisc: 374*7dd7cddfSDavid du Colombier discend(p0, radius, dst, src, d); 375*7dd7cddfSDavid du Colombier /* fall through */ 376*7dd7cddfSDavid du Colombier case Endsquare: 377*7dd7cddfSDavid du Colombier default: 378*7dd7cddfSDavid du Colombier pp->x = q.x-dx; 379*7dd7cddfSDavid du Colombier pp->y = q.y+dy; 380*7dd7cddfSDavid du Colombier pp++; 381*7dd7cddfSDavid du Colombier pp->x = q.x+dx; 382*7dd7cddfSDavid du Colombier pp->y = q.y-dy; 383*7dd7cddfSDavid du Colombier pp++; 384*7dd7cddfSDavid du Colombier break; 385*7dd7cddfSDavid du Colombier case Endarrow: 386*7dd7cddfSDavid du Colombier arrowend(q, pp, end0, -sin, -cos, radius); 387*7dd7cddfSDavid du Colombier memfillpolysc(dst, pts, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1); 388*7dd7cddfSDavid du Colombier pp[1] = pp[4]; 389*7dd7cddfSDavid du Colombier pp += 2; 390*7dd7cddfSDavid du Colombier } 391*7dd7cddfSDavid du Colombier q.x = ICOSSCALE*p1.x+ICOSSCALE/2+cos/2; 392*7dd7cddfSDavid du Colombier q.y = ICOSSCALE*p1.y+ICOSSCALE/2+sin/2; 393*7dd7cddfSDavid du Colombier switch(end1 & 0x1F){ 394*7dd7cddfSDavid du Colombier case Enddisc: 395*7dd7cddfSDavid du Colombier discend(p1, radius, dst, src, d); 396*7dd7cddfSDavid du Colombier /* fall through */ 397*7dd7cddfSDavid du Colombier case Endsquare: 398*7dd7cddfSDavid du Colombier default: 399*7dd7cddfSDavid du Colombier pp->x = q.x+dx; 400*7dd7cddfSDavid du Colombier pp->y = q.y-dy; 401*7dd7cddfSDavid du Colombier pp++; 402*7dd7cddfSDavid du Colombier pp->x = q.x-dx; 403*7dd7cddfSDavid du Colombier pp->y = q.y+dy; 404*7dd7cddfSDavid du Colombier pp++; 405*7dd7cddfSDavid du Colombier break; 406*7dd7cddfSDavid du Colombier case Endarrow: 407*7dd7cddfSDavid du Colombier arrowend(q, pp, end1, sin, cos, radius); 408*7dd7cddfSDavid du Colombier memfillpolysc(dst, pp, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1); 409*7dd7cddfSDavid du Colombier pp[1] = pp[4]; 410*7dd7cddfSDavid du Colombier pp += 2; 411*7dd7cddfSDavid du Colombier } 412*7dd7cddfSDavid du Colombier memfillpolysc(dst, pts, pp-pts, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 0, 10, 1); 413*7dd7cddfSDavid du Colombier dst->clipr = oclipr; 414*7dd7cddfSDavid du Colombier return; 415*7dd7cddfSDavid du Colombier } 416*7dd7cddfSDavid du Colombier 417*7dd7cddfSDavid du Colombier void 418*7dd7cddfSDavid du Colombier memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp) 419*7dd7cddfSDavid du Colombier { 420*7dd7cddfSDavid du Colombier _memimageline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr); 421*7dd7cddfSDavid du Colombier } 422*7dd7cddfSDavid du Colombier 423*7dd7cddfSDavid du Colombier /* 424*7dd7cddfSDavid du Colombier * Simple-minded conservative code to compute bounding box of line. 425*7dd7cddfSDavid du Colombier * Result is probably a little larger than it needs to be. 426*7dd7cddfSDavid du Colombier */ 427*7dd7cddfSDavid du Colombier static 428*7dd7cddfSDavid du Colombier void 429*7dd7cddfSDavid du Colombier addbbox(Rectangle *r, Point p) 430*7dd7cddfSDavid du Colombier { 431*7dd7cddfSDavid du Colombier if(r->min.x > p.x) 432*7dd7cddfSDavid du Colombier r->min.x = p.x; 433*7dd7cddfSDavid du Colombier if(r->min.y > p.y) 434*7dd7cddfSDavid du Colombier r->min.y = p.y; 435*7dd7cddfSDavid du Colombier if(r->max.x < p.x+1) 436*7dd7cddfSDavid du Colombier r->max.x = p.x+1; 437*7dd7cddfSDavid du Colombier if(r->max.y < p.y+1) 438*7dd7cddfSDavid du Colombier r->max.y = p.y+1; 439*7dd7cddfSDavid du Colombier } 440*7dd7cddfSDavid du Colombier 441*7dd7cddfSDavid du Colombier int 442*7dd7cddfSDavid du Colombier memlineendsize(int end) 443*7dd7cddfSDavid du Colombier { 444*7dd7cddfSDavid du Colombier int x3; 445*7dd7cddfSDavid du Colombier 446*7dd7cddfSDavid du Colombier if((end&0x3F) != Endarrow) 447*7dd7cddfSDavid du Colombier return 0; 448*7dd7cddfSDavid du Colombier if(end == Endarrow) 449*7dd7cddfSDavid du Colombier x3 = Arrow3; 450*7dd7cddfSDavid du Colombier else 451*7dd7cddfSDavid du Colombier x3 = (end>>23) & 0x1FF; 452*7dd7cddfSDavid du Colombier return x3; 453*7dd7cddfSDavid du Colombier } 454*7dd7cddfSDavid du Colombier 455*7dd7cddfSDavid du Colombier Rectangle 456*7dd7cddfSDavid du Colombier memlinebbox(Point p0, Point p1, int end0, int end1, int radius) 457*7dd7cddfSDavid du Colombier { 458*7dd7cddfSDavid du Colombier Rectangle r, r1; 459*7dd7cddfSDavid du Colombier int extra; 460*7dd7cddfSDavid du Colombier 461*7dd7cddfSDavid du Colombier r.min.x = 10000000; 462*7dd7cddfSDavid du Colombier r.min.y = 10000000; 463*7dd7cddfSDavid du Colombier r.max.x = -10000000; 464*7dd7cddfSDavid du Colombier r.max.y = -10000000; 465*7dd7cddfSDavid du Colombier extra = lmax(memlineendsize(end0), memlineendsize(end1)); 466*7dd7cddfSDavid du Colombier r1 = insetrect(canonrect(Rpt(p0, p1)), -(radius+extra)); 467*7dd7cddfSDavid du Colombier addbbox(&r, r1.min); 468*7dd7cddfSDavid du Colombier addbbox(&r, r1.max); 469*7dd7cddfSDavid du Colombier return r; 470*7dd7cddfSDavid du Colombier } 471