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