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 typedef struct Seg Seg; 8*7dd7cddfSDavid du Colombier 9*7dd7cddfSDavid du Colombier struct Seg 10*7dd7cddfSDavid du Colombier { 11*7dd7cddfSDavid du Colombier Point p0; 12*7dd7cddfSDavid du Colombier Point p1; 13*7dd7cddfSDavid du Colombier long num; 14*7dd7cddfSDavid du Colombier long den; 15*7dd7cddfSDavid du Colombier long dz; 16*7dd7cddfSDavid du Colombier long dzrem; 17*7dd7cddfSDavid du Colombier long z; 18*7dd7cddfSDavid du Colombier long zerr; 19*7dd7cddfSDavid du Colombier long d; 20*7dd7cddfSDavid du Colombier }; 21*7dd7cddfSDavid du Colombier 22*7dd7cddfSDavid du Colombier static void zsort(Seg **seg, Seg **ep); 23*7dd7cddfSDavid du Colombier static int ycompare(void*, void*); 24*7dd7cddfSDavid du Colombier static int xcompare(void*, void*); 25*7dd7cddfSDavid du Colombier static int zcompare(void*, void*); 26*7dd7cddfSDavid du Colombier static void xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int, int); 27*7dd7cddfSDavid du Colombier static void yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int); 28*7dd7cddfSDavid du Colombier 29*7dd7cddfSDavid du Colombier /* 30*7dd7cddfSDavid du Colombier static void 31*7dd7cddfSDavid du Colombier fillcolor(Memimage *dst, int left, int right, int y, Memimage *src, Point p) 32*7dd7cddfSDavid du Colombier { 33*7dd7cddfSDavid du Colombier int srcval; 34*7dd7cddfSDavid du Colombier 35*7dd7cddfSDavid du Colombier USED(src); 36*7dd7cddfSDavid du Colombier srcval = p.x; 37*7dd7cddfSDavid du Colombier p.x = left; 38*7dd7cddfSDavid du Colombier p.y = y; 39*7dd7cddfSDavid du Colombier memset(byteaddr(dst, p), srcval, right-left); 40*7dd7cddfSDavid du Colombier } 41*7dd7cddfSDavid du Colombier */ 42*7dd7cddfSDavid du Colombier 43*7dd7cddfSDavid du Colombier static void 44*7dd7cddfSDavid du Colombier fillline(Memimage *dst, int left, int right, int y, Memimage *src, Point p) 45*7dd7cddfSDavid du Colombier { 46*7dd7cddfSDavid du Colombier Rectangle r; 47*7dd7cddfSDavid du Colombier 48*7dd7cddfSDavid du Colombier r.min.x = left; 49*7dd7cddfSDavid du Colombier r.min.y = y; 50*7dd7cddfSDavid du Colombier r.max.x = right; 51*7dd7cddfSDavid du Colombier r.max.y = y+1; 52*7dd7cddfSDavid du Colombier p.x += left; 53*7dd7cddfSDavid du Colombier p.y += y; 54*7dd7cddfSDavid du Colombier memdraw(dst, r, src, p, memopaque, p); 55*7dd7cddfSDavid du Colombier } 56*7dd7cddfSDavid du Colombier 57*7dd7cddfSDavid du Colombier static void 58*7dd7cddfSDavid du Colombier fillpoint(Memimage *dst, int x, int y, Memimage *src, Point p) 59*7dd7cddfSDavid du Colombier { 60*7dd7cddfSDavid du Colombier Rectangle r; 61*7dd7cddfSDavid du Colombier 62*7dd7cddfSDavid du Colombier r.min.x = x; 63*7dd7cddfSDavid du Colombier r.min.y = y; 64*7dd7cddfSDavid du Colombier r.max.x = x+1; 65*7dd7cddfSDavid du Colombier r.max.y = y+1; 66*7dd7cddfSDavid du Colombier p.x += x; 67*7dd7cddfSDavid du Colombier p.y += y; 68*7dd7cddfSDavid du Colombier memdraw(dst, r, src, p, memopaque, p); 69*7dd7cddfSDavid du Colombier } 70*7dd7cddfSDavid du Colombier 71*7dd7cddfSDavid du Colombier void 72*7dd7cddfSDavid du Colombier memfillpoly(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp) 73*7dd7cddfSDavid du Colombier { 74*7dd7cddfSDavid du Colombier memfillpolysc(dst, vert, nvert, w, src, sp, 0, 0, 0); 75*7dd7cddfSDavid du Colombier } 76*7dd7cddfSDavid du Colombier 77*7dd7cddfSDavid du Colombier void 78*7dd7cddfSDavid du Colombier memfillpolysc(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int detail, int fixshift, int clipped) 79*7dd7cddfSDavid du Colombier { 80*7dd7cddfSDavid du Colombier Seg **seg, *segtab; 81*7dd7cddfSDavid du Colombier Point p0; 82*7dd7cddfSDavid du Colombier int i; 83*7dd7cddfSDavid du Colombier 84*7dd7cddfSDavid du Colombier if(nvert == 0) 85*7dd7cddfSDavid du Colombier return; 86*7dd7cddfSDavid du Colombier 87*7dd7cddfSDavid du Colombier seg = malloc((nvert+2)*sizeof(Seg*)); 88*7dd7cddfSDavid du Colombier if(seg == nil) 89*7dd7cddfSDavid du Colombier return; 90*7dd7cddfSDavid du Colombier segtab = malloc((nvert+1)*sizeof(Seg)); 91*7dd7cddfSDavid du Colombier if(segtab == nil) { 92*7dd7cddfSDavid du Colombier free(seg); 93*7dd7cddfSDavid du Colombier return; 94*7dd7cddfSDavid du Colombier } 95*7dd7cddfSDavid du Colombier 96*7dd7cddfSDavid du Colombier sp.x = (sp.x - vert[0].x) >> fixshift; 97*7dd7cddfSDavid du Colombier sp.y = (sp.y - vert[0].y) >> fixshift; 98*7dd7cddfSDavid du Colombier p0 = vert[nvert-1]; 99*7dd7cddfSDavid du Colombier if(!fixshift) { 100*7dd7cddfSDavid du Colombier p0.x <<= 1; 101*7dd7cddfSDavid du Colombier p0.y <<= 1; 102*7dd7cddfSDavid du Colombier } 103*7dd7cddfSDavid du Colombier for(i = 0; i < nvert; i++) { 104*7dd7cddfSDavid du Colombier segtab[i].p0 = p0; 105*7dd7cddfSDavid du Colombier p0 = vert[i]; 106*7dd7cddfSDavid du Colombier if(!fixshift) { 107*7dd7cddfSDavid du Colombier p0.x <<= 1; 108*7dd7cddfSDavid du Colombier p0.y <<= 1; 109*7dd7cddfSDavid du Colombier } 110*7dd7cddfSDavid du Colombier segtab[i].p1 = p0; 111*7dd7cddfSDavid du Colombier segtab[i].d = 1; 112*7dd7cddfSDavid du Colombier } 113*7dd7cddfSDavid du Colombier if(!fixshift) 114*7dd7cddfSDavid du Colombier fixshift = 1; 115*7dd7cddfSDavid du Colombier 116*7dd7cddfSDavid du Colombier xscan(dst, seg, segtab, nvert, w, src, sp, detail, fixshift, clipped); 117*7dd7cddfSDavid du Colombier if(detail) 118*7dd7cddfSDavid du Colombier yscan(dst, seg, segtab, nvert, w, src, sp, fixshift); 119*7dd7cddfSDavid du Colombier 120*7dd7cddfSDavid du Colombier free(seg); 121*7dd7cddfSDavid du Colombier free(segtab); 122*7dd7cddfSDavid du Colombier } 123*7dd7cddfSDavid du Colombier 124*7dd7cddfSDavid du Colombier static long 125*7dd7cddfSDavid du Colombier mod(long x, long y) 126*7dd7cddfSDavid du Colombier { 127*7dd7cddfSDavid du Colombier long z; 128*7dd7cddfSDavid du Colombier 129*7dd7cddfSDavid du Colombier z = x%y; 130*7dd7cddfSDavid du Colombier if((long)(((ulong)z)^((ulong)y)) > 0 || z == 0) 131*7dd7cddfSDavid du Colombier return z; 132*7dd7cddfSDavid du Colombier return z + y; 133*7dd7cddfSDavid du Colombier } 134*7dd7cddfSDavid du Colombier 135*7dd7cddfSDavid du Colombier static long 136*7dd7cddfSDavid du Colombier sdiv(long x, long y) 137*7dd7cddfSDavid du Colombier { 138*7dd7cddfSDavid du Colombier if((long)(((ulong)x)^((ulong)y)) >= 0 || x == 0) 139*7dd7cddfSDavid du Colombier return x/y; 140*7dd7cddfSDavid du Colombier 141*7dd7cddfSDavid du Colombier return (x+((y>>30)|1))/y-1; 142*7dd7cddfSDavid du Colombier } 143*7dd7cddfSDavid du Colombier 144*7dd7cddfSDavid du Colombier static long 145*7dd7cddfSDavid du Colombier smuldivmod(long x, long y, long z, long *mod) 146*7dd7cddfSDavid du Colombier { 147*7dd7cddfSDavid du Colombier vlong vx; 148*7dd7cddfSDavid du Colombier 149*7dd7cddfSDavid du Colombier if(x == 0 || y == 0){ 150*7dd7cddfSDavid du Colombier *mod = 0; 151*7dd7cddfSDavid du Colombier return 0; 152*7dd7cddfSDavid du Colombier } 153*7dd7cddfSDavid du Colombier vx = x; 154*7dd7cddfSDavid du Colombier vx *= y; 155*7dd7cddfSDavid du Colombier *mod = vx % z; 156*7dd7cddfSDavid du Colombier if(*mod < 0) 157*7dd7cddfSDavid du Colombier *mod += z; /* z is always >0 */ 158*7dd7cddfSDavid du Colombier if((vx < 0) == (z < 0)) 159*7dd7cddfSDavid du Colombier return vx/z; 160*7dd7cddfSDavid du Colombier return -((-vx)/z); 161*7dd7cddfSDavid du Colombier } 162*7dd7cddfSDavid du Colombier 163*7dd7cddfSDavid du Colombier static void 164*7dd7cddfSDavid du Colombier xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int detail, int fixshift, int clipped) 165*7dd7cddfSDavid du Colombier { 166*7dd7cddfSDavid du Colombier long y, maxy, x, x2, xerr, xden, onehalf; 167*7dd7cddfSDavid du Colombier Seg **ep, **next, **p, **q, *s; 168*7dd7cddfSDavid du Colombier long n, i, iy, cnt, ix, ix2, minx, maxx; 169*7dd7cddfSDavid du Colombier Point pt; 170*7dd7cddfSDavid du Colombier void (*fill)(Memimage*, int, int, int, Memimage*, Point); 171*7dd7cddfSDavid du Colombier 172*7dd7cddfSDavid du Colombier fill = fillline; 173*7dd7cddfSDavid du Colombier /* 174*7dd7cddfSDavid du Colombier * This can only work on 8-bit destinations, since fillcolor is 175*7dd7cddfSDavid du Colombier * just using memset on sp.x. 176*7dd7cddfSDavid du Colombier * 177*7dd7cddfSDavid du Colombier * I'd rather not even enable it then, since then if the general 178*7dd7cddfSDavid du Colombier * code is too slow, someone will come up with a better improvement 179*7dd7cddfSDavid du Colombier * than this sleazy hack. -rsc 180*7dd7cddfSDavid du Colombier * 181*7dd7cddfSDavid du Colombier if(clipped && (src->flags&Frepl) && src->depth==8 && Dx(src->r)==1 && Dy(src->r)==1) { 182*7dd7cddfSDavid du Colombier fill = fillcolor; 183*7dd7cddfSDavid du Colombier sp.x = membyteval(src); 184*7dd7cddfSDavid du Colombier } 185*7dd7cddfSDavid du Colombier * 186*7dd7cddfSDavid du Colombier */ 187*7dd7cddfSDavid du Colombier USED(clipped); 188*7dd7cddfSDavid du Colombier 189*7dd7cddfSDavid du Colombier 190*7dd7cddfSDavid du Colombier for(i=0, s=segtab, p=seg; i<nseg; i++, s++) { 191*7dd7cddfSDavid du Colombier *p = s; 192*7dd7cddfSDavid du Colombier if(s->p0.y == s->p1.y) 193*7dd7cddfSDavid du Colombier continue; 194*7dd7cddfSDavid du Colombier if(s->p0.y > s->p1.y) { 195*7dd7cddfSDavid du Colombier pt = s->p0; 196*7dd7cddfSDavid du Colombier s->p0 = s->p1; 197*7dd7cddfSDavid du Colombier s->p1 = pt; 198*7dd7cddfSDavid du Colombier s->d = -s->d; 199*7dd7cddfSDavid du Colombier } 200*7dd7cddfSDavid du Colombier s->num = s->p1.x - s->p0.x; 201*7dd7cddfSDavid du Colombier s->den = s->p1.y - s->p0.y; 202*7dd7cddfSDavid du Colombier s->dz = sdiv(s->num, s->den) << fixshift; 203*7dd7cddfSDavid du Colombier s->dzrem = mod(s->num, s->den) << fixshift; 204*7dd7cddfSDavid du Colombier s->dz += sdiv(s->dzrem, s->den); 205*7dd7cddfSDavid du Colombier s->dzrem = mod(s->dzrem, s->den); 206*7dd7cddfSDavid du Colombier p++; 207*7dd7cddfSDavid du Colombier } 208*7dd7cddfSDavid du Colombier n = p-seg; 209*7dd7cddfSDavid du Colombier if(n == 0) 210*7dd7cddfSDavid du Colombier return; 211*7dd7cddfSDavid du Colombier *p = 0; 212*7dd7cddfSDavid du Colombier qsort(seg, p-seg , sizeof(Seg*), 213*7dd7cddfSDavid du Colombier (int(*)(const void*, const void*))ycompare); 214*7dd7cddfSDavid du Colombier 215*7dd7cddfSDavid du Colombier onehalf = 0; 216*7dd7cddfSDavid du Colombier if(fixshift) 217*7dd7cddfSDavid du Colombier onehalf = 1 << (fixshift-1); 218*7dd7cddfSDavid du Colombier 219*7dd7cddfSDavid du Colombier minx = dst->clipr.min.x; 220*7dd7cddfSDavid du Colombier maxx = dst->clipr.max.x; 221*7dd7cddfSDavid du Colombier 222*7dd7cddfSDavid du Colombier y = seg[0]->p0.y; 223*7dd7cddfSDavid du Colombier if(y < (dst->clipr.min.y << fixshift)) 224*7dd7cddfSDavid du Colombier y = dst->clipr.min.y << fixshift; 225*7dd7cddfSDavid du Colombier iy = (y + onehalf) >> fixshift; 226*7dd7cddfSDavid du Colombier y = (iy << fixshift) + onehalf; 227*7dd7cddfSDavid du Colombier maxy = dst->clipr.max.y << fixshift; 228*7dd7cddfSDavid du Colombier 229*7dd7cddfSDavid du Colombier ep = next = seg; 230*7dd7cddfSDavid du Colombier 231*7dd7cddfSDavid du Colombier while(y<maxy) { 232*7dd7cddfSDavid du Colombier for(q = p = seg; p < ep; p++) { 233*7dd7cddfSDavid du Colombier s = *p; 234*7dd7cddfSDavid du Colombier if(s->p1.y < y) 235*7dd7cddfSDavid du Colombier continue; 236*7dd7cddfSDavid du Colombier s->z += s->dz; 237*7dd7cddfSDavid du Colombier s->zerr += s->dzrem; 238*7dd7cddfSDavid du Colombier if(s->zerr >= s->den) { 239*7dd7cddfSDavid du Colombier s->z++; 240*7dd7cddfSDavid du Colombier s->zerr -= s->den; 241*7dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den) 242*7dd7cddfSDavid du Colombier print("bad ratzerr1: %ld den %ld dzrem %ld\n", s->zerr, s->den, s->dzrem); 243*7dd7cddfSDavid du Colombier } 244*7dd7cddfSDavid du Colombier *q++ = s; 245*7dd7cddfSDavid du Colombier } 246*7dd7cddfSDavid du Colombier 247*7dd7cddfSDavid du Colombier for(p = next; *p; p++) { 248*7dd7cddfSDavid du Colombier s = *p; 249*7dd7cddfSDavid du Colombier if(s->p0.y >= y) 250*7dd7cddfSDavid du Colombier break; 251*7dd7cddfSDavid du Colombier if(s->p1.y < y) 252*7dd7cddfSDavid du Colombier continue; 253*7dd7cddfSDavid du Colombier s->z = s->p0.x; 254*7dd7cddfSDavid du Colombier s->z += smuldivmod(y - s->p0.y, s->num, s->den, &s->zerr); 255*7dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den) 256*7dd7cddfSDavid du Colombier print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); 257*7dd7cddfSDavid du Colombier *q++ = s; 258*7dd7cddfSDavid du Colombier } 259*7dd7cddfSDavid du Colombier ep = q; 260*7dd7cddfSDavid du Colombier next = p; 261*7dd7cddfSDavid du Colombier 262*7dd7cddfSDavid du Colombier if(ep == seg) { 263*7dd7cddfSDavid du Colombier if(*next == 0) 264*7dd7cddfSDavid du Colombier break; 265*7dd7cddfSDavid du Colombier iy = (next[0]->p0.y + onehalf) >> fixshift; 266*7dd7cddfSDavid du Colombier y = (iy << fixshift) + onehalf; 267*7dd7cddfSDavid du Colombier continue; 268*7dd7cddfSDavid du Colombier } 269*7dd7cddfSDavid du Colombier 270*7dd7cddfSDavid du Colombier zsort(seg, ep); 271*7dd7cddfSDavid du Colombier 272*7dd7cddfSDavid du Colombier for(p = seg; p < ep; p++) { 273*7dd7cddfSDavid du Colombier cnt = 0; 274*7dd7cddfSDavid du Colombier x = p[0]->z; 275*7dd7cddfSDavid du Colombier xerr = p[0]->zerr; 276*7dd7cddfSDavid du Colombier xden = p[0]->den; 277*7dd7cddfSDavid du Colombier ix = (x + onehalf) >> fixshift; 278*7dd7cddfSDavid du Colombier if(ix >= maxx) 279*7dd7cddfSDavid du Colombier break; 280*7dd7cddfSDavid du Colombier if(ix < minx) 281*7dd7cddfSDavid du Colombier ix = minx; 282*7dd7cddfSDavid du Colombier cnt += p[0]->d; 283*7dd7cddfSDavid du Colombier p++; 284*7dd7cddfSDavid du Colombier for(;;) { 285*7dd7cddfSDavid du Colombier if(p == ep) { 286*7dd7cddfSDavid du Colombier print("xscan: fill to infinity"); 287*7dd7cddfSDavid du Colombier return; 288*7dd7cddfSDavid du Colombier } 289*7dd7cddfSDavid du Colombier cnt += p[0]->d; 290*7dd7cddfSDavid du Colombier if((cnt&wind) == 0) 291*7dd7cddfSDavid du Colombier break; 292*7dd7cddfSDavid du Colombier p++; 293*7dd7cddfSDavid du Colombier } 294*7dd7cddfSDavid du Colombier x2 = p[0]->z; 295*7dd7cddfSDavid du Colombier ix2 = (x2 + onehalf) >> fixshift; 296*7dd7cddfSDavid du Colombier if(ix2 <= minx) 297*7dd7cddfSDavid du Colombier continue; 298*7dd7cddfSDavid du Colombier if(ix2 > maxx) 299*7dd7cddfSDavid du Colombier ix2 = maxx; 300*7dd7cddfSDavid du Colombier if(ix == ix2 && detail) { 301*7dd7cddfSDavid du Colombier if(xerr*p[0]->den + p[0]->zerr*xden > p[0]->den*xden) 302*7dd7cddfSDavid du Colombier x++; 303*7dd7cddfSDavid du Colombier ix = (x + x2) >> (fixshift+1); 304*7dd7cddfSDavid du Colombier ix2 = ix+1; 305*7dd7cddfSDavid du Colombier } 306*7dd7cddfSDavid du Colombier (*fill)(dst, ix, ix2, iy, src, sp); 307*7dd7cddfSDavid du Colombier } 308*7dd7cddfSDavid du Colombier y += (1<<fixshift); 309*7dd7cddfSDavid du Colombier iy++; 310*7dd7cddfSDavid du Colombier } 311*7dd7cddfSDavid du Colombier } 312*7dd7cddfSDavid du Colombier 313*7dd7cddfSDavid du Colombier static void 314*7dd7cddfSDavid du Colombier yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int fixshift) 315*7dd7cddfSDavid du Colombier { 316*7dd7cddfSDavid du Colombier long x, maxx, y, y2, yerr, yden, onehalf; 317*7dd7cddfSDavid du Colombier Seg **ep, **next, **p, **q, *s; 318*7dd7cddfSDavid du Colombier int n, i, ix, cnt, iy, iy2, miny, maxy; 319*7dd7cddfSDavid du Colombier Point pt; 320*7dd7cddfSDavid du Colombier 321*7dd7cddfSDavid du Colombier for(i=0, s=segtab, p=seg; i<nseg; i++, s++) { 322*7dd7cddfSDavid du Colombier *p = s; 323*7dd7cddfSDavid du Colombier if(s->p0.x == s->p1.x) 324*7dd7cddfSDavid du Colombier continue; 325*7dd7cddfSDavid du Colombier if(s->p0.x > s->p1.x) { 326*7dd7cddfSDavid du Colombier pt = s->p0; 327*7dd7cddfSDavid du Colombier s->p0 = s->p1; 328*7dd7cddfSDavid du Colombier s->p1 = pt; 329*7dd7cddfSDavid du Colombier s->d = -s->d; 330*7dd7cddfSDavid du Colombier } 331*7dd7cddfSDavid du Colombier s->num = s->p1.y - s->p0.y; 332*7dd7cddfSDavid du Colombier s->den = s->p1.x - s->p0.x; 333*7dd7cddfSDavid du Colombier s->dz = sdiv(s->num, s->den) << fixshift; 334*7dd7cddfSDavid du Colombier s->dzrem = mod(s->num, s->den) << fixshift; 335*7dd7cddfSDavid du Colombier s->dz += sdiv(s->dzrem, s->den); 336*7dd7cddfSDavid du Colombier s->dzrem = mod(s->dzrem, s->den); 337*7dd7cddfSDavid du Colombier p++; 338*7dd7cddfSDavid du Colombier } 339*7dd7cddfSDavid du Colombier n = p-seg; 340*7dd7cddfSDavid du Colombier if(n == 0) 341*7dd7cddfSDavid du Colombier return; 342*7dd7cddfSDavid du Colombier *p = 0; 343*7dd7cddfSDavid du Colombier qsort(seg, n , sizeof(Seg*), 344*7dd7cddfSDavid du Colombier (int(*)(const void*, const void*))xcompare); 345*7dd7cddfSDavid du Colombier 346*7dd7cddfSDavid du Colombier onehalf = 0; 347*7dd7cddfSDavid du Colombier if(fixshift) 348*7dd7cddfSDavid du Colombier onehalf = 1 << (fixshift-1); 349*7dd7cddfSDavid du Colombier 350*7dd7cddfSDavid du Colombier miny = dst->clipr.min.y; 351*7dd7cddfSDavid du Colombier maxy = dst->clipr.max.y; 352*7dd7cddfSDavid du Colombier 353*7dd7cddfSDavid du Colombier x = seg[0]->p0.x; 354*7dd7cddfSDavid du Colombier if(x < (dst->clipr.min.x << fixshift)) 355*7dd7cddfSDavid du Colombier x = dst->clipr.min.x << fixshift; 356*7dd7cddfSDavid du Colombier ix = (x + onehalf) >> fixshift; 357*7dd7cddfSDavid du Colombier x = (ix << fixshift) + onehalf; 358*7dd7cddfSDavid du Colombier maxx = dst->clipr.max.x << fixshift; 359*7dd7cddfSDavid du Colombier 360*7dd7cddfSDavid du Colombier ep = next = seg; 361*7dd7cddfSDavid du Colombier 362*7dd7cddfSDavid du Colombier while(x<maxx) { 363*7dd7cddfSDavid du Colombier for(q = p = seg; p < ep; p++) { 364*7dd7cddfSDavid du Colombier s = *p; 365*7dd7cddfSDavid du Colombier if(s->p1.x < x) 366*7dd7cddfSDavid du Colombier continue; 367*7dd7cddfSDavid du Colombier s->z += s->dz; 368*7dd7cddfSDavid du Colombier s->zerr += s->dzrem; 369*7dd7cddfSDavid du Colombier if(s->zerr >= s->den) { 370*7dd7cddfSDavid du Colombier s->z++; 371*7dd7cddfSDavid du Colombier s->zerr -= s->den; 372*7dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den) 373*7dd7cddfSDavid du Colombier print("bad ratzerr1: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); 374*7dd7cddfSDavid du Colombier } 375*7dd7cddfSDavid du Colombier *q++ = s; 376*7dd7cddfSDavid du Colombier } 377*7dd7cddfSDavid du Colombier 378*7dd7cddfSDavid du Colombier for(p = next; *p; p++) { 379*7dd7cddfSDavid du Colombier s = *p; 380*7dd7cddfSDavid du Colombier if(s->p0.x >= x) 381*7dd7cddfSDavid du Colombier break; 382*7dd7cddfSDavid du Colombier if(s->p1.x < x) 383*7dd7cddfSDavid du Colombier continue; 384*7dd7cddfSDavid du Colombier s->z = s->p0.y; 385*7dd7cddfSDavid du Colombier s->z += smuldivmod(x - s->p0.x, s->num, s->den, &s->zerr); 386*7dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den) 387*7dd7cddfSDavid du Colombier print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); 388*7dd7cddfSDavid du Colombier *q++ = s; 389*7dd7cddfSDavid du Colombier } 390*7dd7cddfSDavid du Colombier ep = q; 391*7dd7cddfSDavid du Colombier next = p; 392*7dd7cddfSDavid du Colombier 393*7dd7cddfSDavid du Colombier if(ep == seg) { 394*7dd7cddfSDavid du Colombier if(*next == 0) 395*7dd7cddfSDavid du Colombier break; 396*7dd7cddfSDavid du Colombier ix = (next[0]->p0.x + onehalf) >> fixshift; 397*7dd7cddfSDavid du Colombier x = (ix << fixshift) + onehalf; 398*7dd7cddfSDavid du Colombier continue; 399*7dd7cddfSDavid du Colombier } 400*7dd7cddfSDavid du Colombier 401*7dd7cddfSDavid du Colombier zsort(seg, ep); 402*7dd7cddfSDavid du Colombier 403*7dd7cddfSDavid du Colombier for(p = seg; p < ep; p++) { 404*7dd7cddfSDavid du Colombier cnt = 0; 405*7dd7cddfSDavid du Colombier y = p[0]->z; 406*7dd7cddfSDavid du Colombier yerr = p[0]->zerr; 407*7dd7cddfSDavid du Colombier yden = p[0]->den; 408*7dd7cddfSDavid du Colombier iy = (y + onehalf) >> fixshift; 409*7dd7cddfSDavid du Colombier if(iy >= maxy) 410*7dd7cddfSDavid du Colombier break; 411*7dd7cddfSDavid du Colombier if(iy < miny) 412*7dd7cddfSDavid du Colombier iy = miny; 413*7dd7cddfSDavid du Colombier cnt += p[0]->d; 414*7dd7cddfSDavid du Colombier p++; 415*7dd7cddfSDavid du Colombier for(;;) { 416*7dd7cddfSDavid du Colombier if(p == ep) { 417*7dd7cddfSDavid du Colombier print("yscan: fill to infinity"); 418*7dd7cddfSDavid du Colombier return; 419*7dd7cddfSDavid du Colombier } 420*7dd7cddfSDavid du Colombier cnt += p[0]->d; 421*7dd7cddfSDavid du Colombier if((cnt&wind) == 0) 422*7dd7cddfSDavid du Colombier break; 423*7dd7cddfSDavid du Colombier p++; 424*7dd7cddfSDavid du Colombier } 425*7dd7cddfSDavid du Colombier y2 = p[0]->z; 426*7dd7cddfSDavid du Colombier iy2 = (y2 + onehalf) >> fixshift; 427*7dd7cddfSDavid du Colombier if(iy2 <= miny) 428*7dd7cddfSDavid du Colombier continue; 429*7dd7cddfSDavid du Colombier if(iy2 > maxy) 430*7dd7cddfSDavid du Colombier iy2 = maxy; 431*7dd7cddfSDavid du Colombier if(iy == iy2) { 432*7dd7cddfSDavid du Colombier if(yerr*p[0]->den + p[0]->zerr*yden > p[0]->den*yden) 433*7dd7cddfSDavid du Colombier y++; 434*7dd7cddfSDavid du Colombier iy = (y + y2) >> (fixshift+1); 435*7dd7cddfSDavid du Colombier fillpoint(dst, ix, iy, src, sp); 436*7dd7cddfSDavid du Colombier } 437*7dd7cddfSDavid du Colombier } 438*7dd7cddfSDavid du Colombier x += (1<<fixshift); 439*7dd7cddfSDavid du Colombier ix++; 440*7dd7cddfSDavid du Colombier } 441*7dd7cddfSDavid du Colombier } 442*7dd7cddfSDavid du Colombier 443*7dd7cddfSDavid du Colombier static void 444*7dd7cddfSDavid du Colombier zsort(Seg **seg, Seg **ep) 445*7dd7cddfSDavid du Colombier { 446*7dd7cddfSDavid du Colombier int done; 447*7dd7cddfSDavid du Colombier Seg **q, **p, *s; 448*7dd7cddfSDavid du Colombier 449*7dd7cddfSDavid du Colombier if(ep-seg < 20) { 450*7dd7cddfSDavid du Colombier /* bubble sort by z - they should be almost sorted already */ 451*7dd7cddfSDavid du Colombier q = ep; 452*7dd7cddfSDavid du Colombier do { 453*7dd7cddfSDavid du Colombier done = 1; 454*7dd7cddfSDavid du Colombier q--; 455*7dd7cddfSDavid du Colombier for(p = seg; p < q; p++) { 456*7dd7cddfSDavid du Colombier if(p[0]->z > p[1]->z) { 457*7dd7cddfSDavid du Colombier s = p[0]; 458*7dd7cddfSDavid du Colombier p[0] = p[1]; 459*7dd7cddfSDavid du Colombier p[1] = s; 460*7dd7cddfSDavid du Colombier done = 0; 461*7dd7cddfSDavid du Colombier } 462*7dd7cddfSDavid du Colombier } 463*7dd7cddfSDavid du Colombier } while(!done); 464*7dd7cddfSDavid du Colombier } else { 465*7dd7cddfSDavid du Colombier q = ep-1; 466*7dd7cddfSDavid du Colombier for(p = seg; p < q; p++) { 467*7dd7cddfSDavid du Colombier if(p[0]->z > p[1]->z) { 468*7dd7cddfSDavid du Colombier qsort(seg, ep-seg, sizeof(Seg*), 469*7dd7cddfSDavid du Colombier (int(*)(const void*, const void*))zcompare); 470*7dd7cddfSDavid du Colombier break; 471*7dd7cddfSDavid du Colombier } 472*7dd7cddfSDavid du Colombier } 473*7dd7cddfSDavid du Colombier } 474*7dd7cddfSDavid du Colombier } 475*7dd7cddfSDavid du Colombier 476*7dd7cddfSDavid du Colombier static int 477*7dd7cddfSDavid du Colombier ycompare(void *a, void *b) 478*7dd7cddfSDavid du Colombier { 479*7dd7cddfSDavid du Colombier Seg **s0, **s1; 480*7dd7cddfSDavid du Colombier long y0, y1; 481*7dd7cddfSDavid du Colombier 482*7dd7cddfSDavid du Colombier s0 = a; 483*7dd7cddfSDavid du Colombier s1 = b; 484*7dd7cddfSDavid du Colombier y0 = (*s0)->p0.y; 485*7dd7cddfSDavid du Colombier y1 = (*s1)->p0.y; 486*7dd7cddfSDavid du Colombier 487*7dd7cddfSDavid du Colombier if(y0 < y1) 488*7dd7cddfSDavid du Colombier return -1; 489*7dd7cddfSDavid du Colombier if(y0 == y1) 490*7dd7cddfSDavid du Colombier return 0; 491*7dd7cddfSDavid du Colombier return 1; 492*7dd7cddfSDavid du Colombier } 493*7dd7cddfSDavid du Colombier 494*7dd7cddfSDavid du Colombier static int 495*7dd7cddfSDavid du Colombier xcompare(void *a, void *b) 496*7dd7cddfSDavid du Colombier { 497*7dd7cddfSDavid du Colombier Seg **s0, **s1; 498*7dd7cddfSDavid du Colombier long x0, x1; 499*7dd7cddfSDavid du Colombier 500*7dd7cddfSDavid du Colombier s0 = a; 501*7dd7cddfSDavid du Colombier s1 = b; 502*7dd7cddfSDavid du Colombier x0 = (*s0)->p0.x; 503*7dd7cddfSDavid du Colombier x1 = (*s1)->p0.x; 504*7dd7cddfSDavid du Colombier 505*7dd7cddfSDavid du Colombier if(x0 < x1) 506*7dd7cddfSDavid du Colombier return -1; 507*7dd7cddfSDavid du Colombier if(x0 == x1) 508*7dd7cddfSDavid du Colombier return 0; 509*7dd7cddfSDavid du Colombier return 1; 510*7dd7cddfSDavid du Colombier } 511*7dd7cddfSDavid du Colombier 512*7dd7cddfSDavid du Colombier static int 513*7dd7cddfSDavid du Colombier zcompare(void *a, void *b) 514*7dd7cddfSDavid du Colombier { 515*7dd7cddfSDavid du Colombier Seg **s0, **s1; 516*7dd7cddfSDavid du Colombier long z0, z1; 517*7dd7cddfSDavid du Colombier 518*7dd7cddfSDavid du Colombier s0 = a; 519*7dd7cddfSDavid du Colombier s1 = b; 520*7dd7cddfSDavid du Colombier z0 = (*s0)->z; 521*7dd7cddfSDavid du Colombier z1 = (*s1)->z; 522*7dd7cddfSDavid du Colombier 523*7dd7cddfSDavid du Colombier if(z0 < z1) 524*7dd7cddfSDavid du Colombier return -1; 525*7dd7cddfSDavid du Colombier if(z0 == z1) 526*7dd7cddfSDavid du Colombier return 0; 527*7dd7cddfSDavid du Colombier return 1; 528*7dd7cddfSDavid du Colombier } 529