1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
4*8ccd4a63SDavid du Colombier #include <memdraw.h>
5*8ccd4a63SDavid du Colombier #include <memlayer.h>
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier typedef struct Seg Seg;
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier struct Seg
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier Point p0;
127dd7cddfSDavid du Colombier Point p1;
137dd7cddfSDavid du Colombier long num;
147dd7cddfSDavid du Colombier long den;
157dd7cddfSDavid du Colombier long dz;
167dd7cddfSDavid du Colombier long dzrem;
177dd7cddfSDavid du Colombier long z;
187dd7cddfSDavid du Colombier long zerr;
197dd7cddfSDavid du Colombier long d;
207dd7cddfSDavid du Colombier };
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier static void zsort(Seg **seg, Seg **ep);
23*8ccd4a63SDavid du Colombier static int ycompare(const void*, const void*);
24*8ccd4a63SDavid du Colombier static int xcompare(const void*, const void*);
25*8ccd4a63SDavid du Colombier static int zcompare(const void*, const void*);
26*8ccd4a63SDavid du Colombier static void xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int, int, int);
27*8ccd4a63SDavid du Colombier static void yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int);
287dd7cddfSDavid du Colombier
29*8ccd4a63SDavid du Colombier #ifdef NOT
307dd7cddfSDavid du Colombier static void
fillcolor(Memimage * dst,int left,int right,int y,Memimage * src,Point p)317dd7cddfSDavid du Colombier fillcolor(Memimage *dst, int left, int right, int y, Memimage *src, Point p)
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier int srcval;
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier USED(src);
367dd7cddfSDavid du Colombier srcval = p.x;
377dd7cddfSDavid du Colombier p.x = left;
387dd7cddfSDavid du Colombier p.y = y;
397dd7cddfSDavid du Colombier memset(byteaddr(dst, p), srcval, right-left);
407dd7cddfSDavid du Colombier }
41*8ccd4a63SDavid du Colombier #endif
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier static void
fillline(Memimage * dst,int left,int right,int y,Memimage * src,Point p,int op)44*8ccd4a63SDavid du Colombier fillline(Memimage *dst, int left, int right, int y, Memimage *src, Point p, int op)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier Rectangle r;
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier r.min.x = left;
497dd7cddfSDavid du Colombier r.min.y = y;
507dd7cddfSDavid du Colombier r.max.x = right;
517dd7cddfSDavid du Colombier r.max.y = y+1;
527dd7cddfSDavid du Colombier p.x += left;
537dd7cddfSDavid du Colombier p.y += y;
54*8ccd4a63SDavid du Colombier memdraw(dst, r, src, p, memopaque, p, op);
557dd7cddfSDavid du Colombier }
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier static void
fillpoint(Memimage * dst,int x,int y,Memimage * src,Point p,int op)58*8ccd4a63SDavid du Colombier fillpoint(Memimage *dst, int x, int y, Memimage *src, Point p, int op)
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier Rectangle r;
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier r.min.x = x;
637dd7cddfSDavid du Colombier r.min.y = y;
647dd7cddfSDavid du Colombier r.max.x = x+1;
657dd7cddfSDavid du Colombier r.max.y = y+1;
667dd7cddfSDavid du Colombier p.x += x;
677dd7cddfSDavid du Colombier p.y += y;
68*8ccd4a63SDavid du Colombier memdraw(dst, r, src, p, memopaque, p, op);
697dd7cddfSDavid du Colombier }
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier void
memfillpoly(Memimage * dst,Point * vert,int nvert,int w,Memimage * src,Point sp,int op)72*8ccd4a63SDavid du Colombier memfillpoly(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int op)
737dd7cddfSDavid du Colombier {
74*8ccd4a63SDavid du Colombier _memfillpolysc(dst, vert, nvert, w, src, sp, 0, 0, 0, op);
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier void
_memfillpolysc(Memimage * dst,Point * vert,int nvert,int w,Memimage * src,Point sp,int detail,int fixshift,int clipped,int op)78*8ccd4a63SDavid du Colombier _memfillpolysc(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier Seg **seg, *segtab;
817dd7cddfSDavid du Colombier Point p0;
827dd7cddfSDavid du Colombier int i;
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier if(nvert == 0)
857dd7cddfSDavid du Colombier return;
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier seg = malloc((nvert+2)*sizeof(Seg*));
887dd7cddfSDavid du Colombier if(seg == nil)
897dd7cddfSDavid du Colombier return;
907dd7cddfSDavid du Colombier segtab = malloc((nvert+1)*sizeof(Seg));
917dd7cddfSDavid du Colombier if(segtab == nil) {
927dd7cddfSDavid du Colombier free(seg);
937dd7cddfSDavid du Colombier return;
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier sp.x = (sp.x - vert[0].x) >> fixshift;
977dd7cddfSDavid du Colombier sp.y = (sp.y - vert[0].y) >> fixshift;
987dd7cddfSDavid du Colombier p0 = vert[nvert-1];
997dd7cddfSDavid du Colombier if(!fixshift) {
1007dd7cddfSDavid du Colombier p0.x <<= 1;
1017dd7cddfSDavid du Colombier p0.y <<= 1;
1027dd7cddfSDavid du Colombier }
1037dd7cddfSDavid du Colombier for(i = 0; i < nvert; i++) {
1047dd7cddfSDavid du Colombier segtab[i].p0 = p0;
1057dd7cddfSDavid du Colombier p0 = vert[i];
1067dd7cddfSDavid du Colombier if(!fixshift) {
1077dd7cddfSDavid du Colombier p0.x <<= 1;
1087dd7cddfSDavid du Colombier p0.y <<= 1;
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier segtab[i].p1 = p0;
1117dd7cddfSDavid du Colombier segtab[i].d = 1;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier if(!fixshift)
1147dd7cddfSDavid du Colombier fixshift = 1;
1157dd7cddfSDavid du Colombier
116*8ccd4a63SDavid du Colombier xscan(dst, seg, segtab, nvert, w, src, sp, detail, fixshift, clipped, op);
1177dd7cddfSDavid du Colombier if(detail)
118*8ccd4a63SDavid du Colombier yscan(dst, seg, segtab, nvert, w, src, sp, fixshift, op);
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier free(seg);
1217dd7cddfSDavid du Colombier free(segtab);
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier static long
mod(long x,long y)1257dd7cddfSDavid du Colombier mod(long x, long y)
1267dd7cddfSDavid du Colombier {
1277dd7cddfSDavid du Colombier long z;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier z = x%y;
1307dd7cddfSDavid du Colombier if((long)(((ulong)z)^((ulong)y)) > 0 || z == 0)
1317dd7cddfSDavid du Colombier return z;
1327dd7cddfSDavid du Colombier return z + y;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier static long
sdiv(long x,long y)1367dd7cddfSDavid du Colombier sdiv(long x, long y)
1377dd7cddfSDavid du Colombier {
1387dd7cddfSDavid du Colombier if((long)(((ulong)x)^((ulong)y)) >= 0 || x == 0)
1397dd7cddfSDavid du Colombier return x/y;
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier return (x+((y>>30)|1))/y-1;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier static long
smuldivmod(long x,long y,long z,long * mod)1457dd7cddfSDavid du Colombier smuldivmod(long x, long y, long z, long *mod)
1467dd7cddfSDavid du Colombier {
1477dd7cddfSDavid du Colombier vlong vx;
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier if(x == 0 || y == 0){
1507dd7cddfSDavid du Colombier *mod = 0;
1517dd7cddfSDavid du Colombier return 0;
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier vx = x;
1547dd7cddfSDavid du Colombier vx *= y;
1557dd7cddfSDavid du Colombier *mod = vx % z;
1567dd7cddfSDavid du Colombier if(*mod < 0)
1577dd7cddfSDavid du Colombier *mod += z; /* z is always >0 */
1587dd7cddfSDavid du Colombier if((vx < 0) == (z < 0))
1597dd7cddfSDavid du Colombier return vx/z;
1607dd7cddfSDavid du Colombier return -((-vx)/z);
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier static void
xscan(Memimage * dst,Seg ** seg,Seg * segtab,int nseg,int wind,Memimage * src,Point sp,int detail,int fixshift,int clipped,int op)164*8ccd4a63SDavid du Colombier xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op)
1657dd7cddfSDavid du Colombier {
1667dd7cddfSDavid du Colombier long y, maxy, x, x2, xerr, xden, onehalf;
1677dd7cddfSDavid du Colombier Seg **ep, **next, **p, **q, *s;
1687dd7cddfSDavid du Colombier long n, i, iy, cnt, ix, ix2, minx, maxx;
1697dd7cddfSDavid du Colombier Point pt;
170*8ccd4a63SDavid du Colombier void (*fill)(Memimage*, int, int, int, Memimage*, Point, int);
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier fill = fillline;
1737dd7cddfSDavid du Colombier /*
1747dd7cddfSDavid du Colombier * This can only work on 8-bit destinations, since fillcolor is
1757dd7cddfSDavid du Colombier * just using memset on sp.x.
1767dd7cddfSDavid du Colombier *
1777dd7cddfSDavid du Colombier * I'd rather not even enable it then, since then if the general
1787dd7cddfSDavid du Colombier * code is too slow, someone will come up with a better improvement
1797dd7cddfSDavid du Colombier * than this sleazy hack. -rsc
1807dd7cddfSDavid du Colombier *
1817dd7cddfSDavid du Colombier if(clipped && (src->flags&Frepl) && src->depth==8 && Dx(src->r)==1 && Dy(src->r)==1) {
1827dd7cddfSDavid du Colombier fill = fillcolor;
1837dd7cddfSDavid du Colombier sp.x = membyteval(src);
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier *
1867dd7cddfSDavid du Colombier */
1877dd7cddfSDavid du Colombier USED(clipped);
1887dd7cddfSDavid du Colombier
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier for(i=0, s=segtab, p=seg; i<nseg; i++, s++) {
1917dd7cddfSDavid du Colombier *p = s;
1927dd7cddfSDavid du Colombier if(s->p0.y == s->p1.y)
1937dd7cddfSDavid du Colombier continue;
1947dd7cddfSDavid du Colombier if(s->p0.y > s->p1.y) {
1957dd7cddfSDavid du Colombier pt = s->p0;
1967dd7cddfSDavid du Colombier s->p0 = s->p1;
1977dd7cddfSDavid du Colombier s->p1 = pt;
1987dd7cddfSDavid du Colombier s->d = -s->d;
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier s->num = s->p1.x - s->p0.x;
2017dd7cddfSDavid du Colombier s->den = s->p1.y - s->p0.y;
2027dd7cddfSDavid du Colombier s->dz = sdiv(s->num, s->den) << fixshift;
2037dd7cddfSDavid du Colombier s->dzrem = mod(s->num, s->den) << fixshift;
2047dd7cddfSDavid du Colombier s->dz += sdiv(s->dzrem, s->den);
2057dd7cddfSDavid du Colombier s->dzrem = mod(s->dzrem, s->den);
2067dd7cddfSDavid du Colombier p++;
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier n = p-seg;
2097dd7cddfSDavid du Colombier if(n == 0)
2107dd7cddfSDavid du Colombier return;
2117dd7cddfSDavid du Colombier *p = 0;
212*8ccd4a63SDavid du Colombier qsort(seg, p-seg , sizeof(Seg*), ycompare);
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier onehalf = 0;
2157dd7cddfSDavid du Colombier if(fixshift)
2167dd7cddfSDavid du Colombier onehalf = 1 << (fixshift-1);
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier minx = dst->clipr.min.x;
2197dd7cddfSDavid du Colombier maxx = dst->clipr.max.x;
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier y = seg[0]->p0.y;
2227dd7cddfSDavid du Colombier if(y < (dst->clipr.min.y << fixshift))
2237dd7cddfSDavid du Colombier y = dst->clipr.min.y << fixshift;
2247dd7cddfSDavid du Colombier iy = (y + onehalf) >> fixshift;
2257dd7cddfSDavid du Colombier y = (iy << fixshift) + onehalf;
2267dd7cddfSDavid du Colombier maxy = dst->clipr.max.y << fixshift;
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier ep = next = seg;
2297dd7cddfSDavid du Colombier
2307dd7cddfSDavid du Colombier while(y<maxy) {
2317dd7cddfSDavid du Colombier for(q = p = seg; p < ep; p++) {
2327dd7cddfSDavid du Colombier s = *p;
2337dd7cddfSDavid du Colombier if(s->p1.y < y)
2347dd7cddfSDavid du Colombier continue;
2357dd7cddfSDavid du Colombier s->z += s->dz;
2367dd7cddfSDavid du Colombier s->zerr += s->dzrem;
2377dd7cddfSDavid du Colombier if(s->zerr >= s->den) {
2387dd7cddfSDavid du Colombier s->z++;
2397dd7cddfSDavid du Colombier s->zerr -= s->den;
2407dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den)
2417dd7cddfSDavid du Colombier print("bad ratzerr1: %ld den %ld dzrem %ld\n", s->zerr, s->den, s->dzrem);
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier *q++ = s;
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier for(p = next; *p; p++) {
2477dd7cddfSDavid du Colombier s = *p;
2487dd7cddfSDavid du Colombier if(s->p0.y >= y)
2497dd7cddfSDavid du Colombier break;
2507dd7cddfSDavid du Colombier if(s->p1.y < y)
2517dd7cddfSDavid du Colombier continue;
2527dd7cddfSDavid du Colombier s->z = s->p0.x;
2537dd7cddfSDavid du Colombier s->z += smuldivmod(y - s->p0.y, s->num, s->den, &s->zerr);
2547dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den)
2557dd7cddfSDavid du Colombier print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
2567dd7cddfSDavid du Colombier *q++ = s;
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier ep = q;
2597dd7cddfSDavid du Colombier next = p;
2607dd7cddfSDavid du Colombier
2617dd7cddfSDavid du Colombier if(ep == seg) {
2627dd7cddfSDavid du Colombier if(*next == 0)
2637dd7cddfSDavid du Colombier break;
2647dd7cddfSDavid du Colombier iy = (next[0]->p0.y + onehalf) >> fixshift;
2657dd7cddfSDavid du Colombier y = (iy << fixshift) + onehalf;
2667dd7cddfSDavid du Colombier continue;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier zsort(seg, ep);
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier for(p = seg; p < ep; p++) {
2727dd7cddfSDavid du Colombier cnt = 0;
2737dd7cddfSDavid du Colombier x = p[0]->z;
2747dd7cddfSDavid du Colombier xerr = p[0]->zerr;
2757dd7cddfSDavid du Colombier xden = p[0]->den;
2767dd7cddfSDavid du Colombier ix = (x + onehalf) >> fixshift;
2777dd7cddfSDavid du Colombier if(ix >= maxx)
2787dd7cddfSDavid du Colombier break;
2797dd7cddfSDavid du Colombier if(ix < minx)
2807dd7cddfSDavid du Colombier ix = minx;
2817dd7cddfSDavid du Colombier cnt += p[0]->d;
2827dd7cddfSDavid du Colombier p++;
2837dd7cddfSDavid du Colombier for(;;) {
2847dd7cddfSDavid du Colombier if(p == ep) {
2857dd7cddfSDavid du Colombier print("xscan: fill to infinity");
2867dd7cddfSDavid du Colombier return;
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier cnt += p[0]->d;
2897dd7cddfSDavid du Colombier if((cnt&wind) == 0)
2907dd7cddfSDavid du Colombier break;
2917dd7cddfSDavid du Colombier p++;
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier x2 = p[0]->z;
2947dd7cddfSDavid du Colombier ix2 = (x2 + onehalf) >> fixshift;
2957dd7cddfSDavid du Colombier if(ix2 <= minx)
2967dd7cddfSDavid du Colombier continue;
2977dd7cddfSDavid du Colombier if(ix2 > maxx)
2987dd7cddfSDavid du Colombier ix2 = maxx;
2997dd7cddfSDavid du Colombier if(ix == ix2 && detail) {
3007dd7cddfSDavid du Colombier if(xerr*p[0]->den + p[0]->zerr*xden > p[0]->den*xden)
3017dd7cddfSDavid du Colombier x++;
3027dd7cddfSDavid du Colombier ix = (x + x2) >> (fixshift+1);
3037dd7cddfSDavid du Colombier ix2 = ix+1;
3047dd7cddfSDavid du Colombier }
305*8ccd4a63SDavid du Colombier (*fill)(dst, ix, ix2, iy, src, sp, op);
3067dd7cddfSDavid du Colombier }
3077dd7cddfSDavid du Colombier y += (1<<fixshift);
3087dd7cddfSDavid du Colombier iy++;
3097dd7cddfSDavid du Colombier }
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier static void
yscan(Memimage * dst,Seg ** seg,Seg * segtab,int nseg,int wind,Memimage * src,Point sp,int fixshift,int op)313*8ccd4a63SDavid du Colombier yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int fixshift, int op)
3147dd7cddfSDavid du Colombier {
3157dd7cddfSDavid du Colombier long x, maxx, y, y2, yerr, yden, onehalf;
3167dd7cddfSDavid du Colombier Seg **ep, **next, **p, **q, *s;
3177dd7cddfSDavid du Colombier int n, i, ix, cnt, iy, iy2, miny, maxy;
3187dd7cddfSDavid du Colombier Point pt;
3197dd7cddfSDavid du Colombier
3207dd7cddfSDavid du Colombier for(i=0, s=segtab, p=seg; i<nseg; i++, s++) {
3217dd7cddfSDavid du Colombier *p = s;
3227dd7cddfSDavid du Colombier if(s->p0.x == s->p1.x)
3237dd7cddfSDavid du Colombier continue;
3247dd7cddfSDavid du Colombier if(s->p0.x > s->p1.x) {
3257dd7cddfSDavid du Colombier pt = s->p0;
3267dd7cddfSDavid du Colombier s->p0 = s->p1;
3277dd7cddfSDavid du Colombier s->p1 = pt;
3287dd7cddfSDavid du Colombier s->d = -s->d;
3297dd7cddfSDavid du Colombier }
3307dd7cddfSDavid du Colombier s->num = s->p1.y - s->p0.y;
3317dd7cddfSDavid du Colombier s->den = s->p1.x - s->p0.x;
3327dd7cddfSDavid du Colombier s->dz = sdiv(s->num, s->den) << fixshift;
3337dd7cddfSDavid du Colombier s->dzrem = mod(s->num, s->den) << fixshift;
3347dd7cddfSDavid du Colombier s->dz += sdiv(s->dzrem, s->den);
3357dd7cddfSDavid du Colombier s->dzrem = mod(s->dzrem, s->den);
3367dd7cddfSDavid du Colombier p++;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier n = p-seg;
3397dd7cddfSDavid du Colombier if(n == 0)
3407dd7cddfSDavid du Colombier return;
3417dd7cddfSDavid du Colombier *p = 0;
342*8ccd4a63SDavid du Colombier qsort(seg, n , sizeof(Seg*), xcompare);
3437dd7cddfSDavid du Colombier
3447dd7cddfSDavid du Colombier onehalf = 0;
3457dd7cddfSDavid du Colombier if(fixshift)
3467dd7cddfSDavid du Colombier onehalf = 1 << (fixshift-1);
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier miny = dst->clipr.min.y;
3497dd7cddfSDavid du Colombier maxy = dst->clipr.max.y;
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier x = seg[0]->p0.x;
3527dd7cddfSDavid du Colombier if(x < (dst->clipr.min.x << fixshift))
3537dd7cddfSDavid du Colombier x = dst->clipr.min.x << fixshift;
3547dd7cddfSDavid du Colombier ix = (x + onehalf) >> fixshift;
3557dd7cddfSDavid du Colombier x = (ix << fixshift) + onehalf;
3567dd7cddfSDavid du Colombier maxx = dst->clipr.max.x << fixshift;
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier ep = next = seg;
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier while(x<maxx) {
3617dd7cddfSDavid du Colombier for(q = p = seg; p < ep; p++) {
3627dd7cddfSDavid du Colombier s = *p;
3637dd7cddfSDavid du Colombier if(s->p1.x < x)
3647dd7cddfSDavid du Colombier continue;
3657dd7cddfSDavid du Colombier s->z += s->dz;
3667dd7cddfSDavid du Colombier s->zerr += s->dzrem;
3677dd7cddfSDavid du Colombier if(s->zerr >= s->den) {
3687dd7cddfSDavid du Colombier s->z++;
3697dd7cddfSDavid du Colombier s->zerr -= s->den;
3707dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den)
3717dd7cddfSDavid du Colombier print("bad ratzerr1: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
3727dd7cddfSDavid du Colombier }
3737dd7cddfSDavid du Colombier *q++ = s;
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier for(p = next; *p; p++) {
3777dd7cddfSDavid du Colombier s = *p;
3787dd7cddfSDavid du Colombier if(s->p0.x >= x)
3797dd7cddfSDavid du Colombier break;
3807dd7cddfSDavid du Colombier if(s->p1.x < x)
3817dd7cddfSDavid du Colombier continue;
3827dd7cddfSDavid du Colombier s->z = s->p0.y;
3837dd7cddfSDavid du Colombier s->z += smuldivmod(x - s->p0.x, s->num, s->den, &s->zerr);
3847dd7cddfSDavid du Colombier if(s->zerr < 0 || s->zerr >= s->den)
3857dd7cddfSDavid du Colombier print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem);
3867dd7cddfSDavid du Colombier *q++ = s;
3877dd7cddfSDavid du Colombier }
3887dd7cddfSDavid du Colombier ep = q;
3897dd7cddfSDavid du Colombier next = p;
3907dd7cddfSDavid du Colombier
3917dd7cddfSDavid du Colombier if(ep == seg) {
3927dd7cddfSDavid du Colombier if(*next == 0)
3937dd7cddfSDavid du Colombier break;
3947dd7cddfSDavid du Colombier ix = (next[0]->p0.x + onehalf) >> fixshift;
3957dd7cddfSDavid du Colombier x = (ix << fixshift) + onehalf;
3967dd7cddfSDavid du Colombier continue;
3977dd7cddfSDavid du Colombier }
3987dd7cddfSDavid du Colombier
3997dd7cddfSDavid du Colombier zsort(seg, ep);
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier for(p = seg; p < ep; p++) {
4027dd7cddfSDavid du Colombier cnt = 0;
4037dd7cddfSDavid du Colombier y = p[0]->z;
4047dd7cddfSDavid du Colombier yerr = p[0]->zerr;
4057dd7cddfSDavid du Colombier yden = p[0]->den;
4067dd7cddfSDavid du Colombier iy = (y + onehalf) >> fixshift;
4077dd7cddfSDavid du Colombier if(iy >= maxy)
4087dd7cddfSDavid du Colombier break;
4097dd7cddfSDavid du Colombier if(iy < miny)
4107dd7cddfSDavid du Colombier iy = miny;
4117dd7cddfSDavid du Colombier cnt += p[0]->d;
4127dd7cddfSDavid du Colombier p++;
4137dd7cddfSDavid du Colombier for(;;) {
4147dd7cddfSDavid du Colombier if(p == ep) {
4157dd7cddfSDavid du Colombier print("yscan: fill to infinity");
4167dd7cddfSDavid du Colombier return;
4177dd7cddfSDavid du Colombier }
4187dd7cddfSDavid du Colombier cnt += p[0]->d;
4197dd7cddfSDavid du Colombier if((cnt&wind) == 0)
4207dd7cddfSDavid du Colombier break;
4217dd7cddfSDavid du Colombier p++;
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier y2 = p[0]->z;
4247dd7cddfSDavid du Colombier iy2 = (y2 + onehalf) >> fixshift;
4257dd7cddfSDavid du Colombier if(iy2 <= miny)
4267dd7cddfSDavid du Colombier continue;
4277dd7cddfSDavid du Colombier if(iy2 > maxy)
4287dd7cddfSDavid du Colombier iy2 = maxy;
4297dd7cddfSDavid du Colombier if(iy == iy2) {
4307dd7cddfSDavid du Colombier if(yerr*p[0]->den + p[0]->zerr*yden > p[0]->den*yden)
4317dd7cddfSDavid du Colombier y++;
4327dd7cddfSDavid du Colombier iy = (y + y2) >> (fixshift+1);
433*8ccd4a63SDavid du Colombier fillpoint(dst, ix, iy, src, sp, op);
4347dd7cddfSDavid du Colombier }
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier x += (1<<fixshift);
4377dd7cddfSDavid du Colombier ix++;
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier static void
zsort(Seg ** seg,Seg ** ep)4427dd7cddfSDavid du Colombier zsort(Seg **seg, Seg **ep)
4437dd7cddfSDavid du Colombier {
4447dd7cddfSDavid du Colombier int done;
4457dd7cddfSDavid du Colombier Seg **q, **p, *s;
4467dd7cddfSDavid du Colombier
4477dd7cddfSDavid du Colombier if(ep-seg < 20) {
4487dd7cddfSDavid du Colombier /* bubble sort by z - they should be almost sorted already */
4497dd7cddfSDavid du Colombier q = ep;
4507dd7cddfSDavid du Colombier do {
4517dd7cddfSDavid du Colombier done = 1;
4527dd7cddfSDavid du Colombier q--;
4537dd7cddfSDavid du Colombier for(p = seg; p < q; p++) {
4547dd7cddfSDavid du Colombier if(p[0]->z > p[1]->z) {
4557dd7cddfSDavid du Colombier s = p[0];
4567dd7cddfSDavid du Colombier p[0] = p[1];
4577dd7cddfSDavid du Colombier p[1] = s;
4587dd7cddfSDavid du Colombier done = 0;
4597dd7cddfSDavid du Colombier }
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier } while(!done);
4627dd7cddfSDavid du Colombier } else {
4637dd7cddfSDavid du Colombier q = ep-1;
4647dd7cddfSDavid du Colombier for(p = seg; p < q; p++) {
4657dd7cddfSDavid du Colombier if(p[0]->z > p[1]->z) {
466*8ccd4a63SDavid du Colombier qsort(seg, ep-seg, sizeof(Seg*), zcompare);
4677dd7cddfSDavid du Colombier break;
4687dd7cddfSDavid du Colombier }
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier }
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier static int
ycompare(const void * a,const void * b)474*8ccd4a63SDavid du Colombier ycompare(const void *a, const void *b)
4757dd7cddfSDavid du Colombier {
4767dd7cddfSDavid du Colombier Seg **s0, **s1;
4777dd7cddfSDavid du Colombier long y0, y1;
4787dd7cddfSDavid du Colombier
479*8ccd4a63SDavid du Colombier s0 = (Seg**)a;
480*8ccd4a63SDavid du Colombier s1 = (Seg**)b;
4817dd7cddfSDavid du Colombier y0 = (*s0)->p0.y;
4827dd7cddfSDavid du Colombier y1 = (*s1)->p0.y;
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier if(y0 < y1)
4857dd7cddfSDavid du Colombier return -1;
4867dd7cddfSDavid du Colombier if(y0 == y1)
4877dd7cddfSDavid du Colombier return 0;
4887dd7cddfSDavid du Colombier return 1;
4897dd7cddfSDavid du Colombier }
4907dd7cddfSDavid du Colombier
4917dd7cddfSDavid du Colombier static int
xcompare(const void * a,const void * b)492*8ccd4a63SDavid du Colombier xcompare(const void *a, const void *b)
4937dd7cddfSDavid du Colombier {
4947dd7cddfSDavid du Colombier Seg **s0, **s1;
4957dd7cddfSDavid du Colombier long x0, x1;
4967dd7cddfSDavid du Colombier
497*8ccd4a63SDavid du Colombier s0 = (Seg**)a;
498*8ccd4a63SDavid du Colombier s1 = (Seg**)b;
4997dd7cddfSDavid du Colombier x0 = (*s0)->p0.x;
5007dd7cddfSDavid du Colombier x1 = (*s1)->p0.x;
5017dd7cddfSDavid du Colombier
5027dd7cddfSDavid du Colombier if(x0 < x1)
5037dd7cddfSDavid du Colombier return -1;
5047dd7cddfSDavid du Colombier if(x0 == x1)
5057dd7cddfSDavid du Colombier return 0;
5067dd7cddfSDavid du Colombier return 1;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier static int
zcompare(const void * a,const void * b)510*8ccd4a63SDavid du Colombier zcompare(const void *a, const void *b)
5117dd7cddfSDavid du Colombier {
5127dd7cddfSDavid du Colombier Seg **s0, **s1;
5137dd7cddfSDavid du Colombier long z0, z1;
5147dd7cddfSDavid du Colombier
515*8ccd4a63SDavid du Colombier s0 = (Seg**)a;
516*8ccd4a63SDavid du Colombier s1 = (Seg**)b;
5177dd7cddfSDavid du Colombier z0 = (*s0)->z;
5187dd7cddfSDavid du Colombier z1 = (*s1)->z;
5197dd7cddfSDavid du Colombier
5207dd7cddfSDavid du Colombier if(z0 < z1)
5217dd7cddfSDavid du Colombier return -1;
5227dd7cddfSDavid du Colombier if(z0 == z1)
5237dd7cddfSDavid du Colombier return 0;
5247dd7cddfSDavid du Colombier return 1;
5257dd7cddfSDavid du Colombier }
526