1implement Polyfill; 2 3include "sys.m"; 4 sys: Sys; 5include "draw.m"; 6 draw: Draw; 7 Point, Rect, Image, Endsquare: import draw; 8include "math/polyfill.m"; 9 10∞: con 16r7fffffff; 11 12init() 13{ 14 sys = load Sys Sys->PATH; 15 draw = load Draw Draw->PATH; 16} 17 18initzbuf(r: Rect): ref Zstate 19{ 20 if(sys == nil) 21 init(); 22 s := ref Zstate; 23 s.r = r; 24 s.xlen = r.dx(); 25 s.ylen = r.dy(); 26 s.xylen = s.xlen*s.ylen; 27 s.zbuf0 = array[s.xylen] of int; 28 s.zbuf1 = array[s.xylen] of int; 29 return s; 30} 31 32clearzbuf(s: ref Zstate) 33{ 34 b0 := s.zbuf0; 35 b1 := s.zbuf1; 36 n := s.xylen; 37 for(i := 0; i < n; i++) 38 b0[i] = b1[i] = ∞; 39} 40 41setzbuf(s: ref Zstate, zd: int) 42{ 43 b0 := s.zbuf0; 44 b1 := s.zbuf1; 45 n := s.xylen; 46 for(i := 0; i < n; i++) 47 b0[i] = b1[i] = zd; 48} 49 50Seg: adt 51{ 52 p0: Point; 53 p1: Point; 54 num: int; 55 den: int; 56 dz: int; 57 dzrem: int; 58 z: int; 59 zerr: int; 60 d: int; 61}; 62 63fillline(dst: ref Image, left: int, right: int, y: int, src: ref Image, p: Point) 64{ 65 p.x += left; 66 p.y += y; 67 dst.line((left, y), (right, y), Endsquare, Endsquare, 0, src, p); 68} 69 70filllinez(dst: ref Image, left: int, right: int, y: int, z: int, e: int, dx: int, k: int, zbuf0: array of int, zbuf1: array of int, src: ref Image, p: Point) 71{ 72 prevx := ∞; 73 for(x := left; x <= right; x++){ 74 if(z+e < zbuf0[k] || (z-e <= zbuf1[k] && x != right && prevx != ∞)){ 75 zbuf0[k] = z-e; 76 zbuf1[k] = z+e; 77 if(prevx == ∞) 78 prevx = x; 79 } 80 else if(prevx != ∞){ 81 fillline(dst, prevx, x-1, y, src, p); 82 prevx = ∞; 83 } 84 z += dx; 85 k++; 86 } 87 if(prevx != ∞) 88 fillline(dst, prevx, right, y, src, p); 89} 90 91fillpoly(dst: ref Image, vert: array of Point, w: int, src: ref Image, sp: Point, zstate: ref Zstate, dc: int, dx: int, dy: int) 92{ 93 p0: Point; 94 i: int; 95 96 nvert := len vert; 97 if(nvert == 0) 98 return; 99 fixshift := 0; 100 seg := array[nvert+2] of ref Seg; 101 if(seg == nil) 102 return; 103 segtab := array[nvert+1] of ref Seg; 104 if(segtab == nil) 105 return; 106 107 sp.x = (sp.x - vert[0].x) >> fixshift; 108 sp.y = (sp.y - vert[0].y) >> fixshift; 109 p0 = vert[nvert-1]; 110 if(!fixshift) { 111 p0.x <<= 1; 112 p0.y <<= 1; 113 } 114 for(i = 0; i < nvert; i++) { 115 segtab[i] = ref Seg; 116 segtab[i].p0 = p0; 117 p0 = vert[i]; 118 if(!fixshift) { 119 p0.x <<= 1; 120 p0.y <<= 1; 121 } 122 segtab[i].p1 = p0; 123 segtab[i].d = 1; 124 } 125 if(!fixshift) 126 fixshift = 1; 127 128 xscan(dst, seg, segtab, nvert, w, src, sp, zstate, dc, dx, dy, fixshift); 129} 130 131mod(x: int, y: int): int 132{ 133 z: int; 134 135 z = x%y; 136 if((z^y) > 0 || z == 0) 137 return z; 138 return z + y; 139} 140 141sdiv(x: int, y: int): int 142{ 143 if((x^y) >= 0 || x == 0) 144 return x/y; 145 return (x+((y>>30)|1))/y-1; 146} 147 148smuldivmod(x: int, y: int, z: int): (int, int) 149{ 150 mod: int; 151 vx: int; 152 153 if(x == 0 || y == 0) 154 return (0, 0); 155 vx = x; 156 vx *= y; 157 mod = vx % z; 158 if(mod < 0) 159 mod += z; 160 if((vx < 0) == (z < 0)) 161 return (vx/z, mod); 162 return (-((-vx)/z), mod); 163} 164 165xscan(dst: ref Image, seg: array of ref Seg, segtab: array of ref Seg, nseg: int, wind: int, src: ref Image, spt: Point, zstate: ref Zstate, dc: int, dx: int, dy: int, fixshift: int) 166{ 167 y, maxy, x, x2, onehalf: int; 168 ep, next, p, q, s: int; 169 n, i, iy, cnt, ix, ix2, minx, maxx, zinc, k, zv: int; 170 pt: Point; 171 sp: ref Seg; 172 173 er := (abs(dx)+abs(dy)+1)/2; 174 zr := zstate.r; 175 xlen := zstate.xlen; 176 zbuf0 := zstate.zbuf0; 177 zbuf1 := zstate.zbuf1; 178 s = 0; 179 p = 0; 180 for(i=0; i<nseg; i++) { 181 sp = seg[p] = segtab[s]; 182 if(sp.p0.y == sp.p1.y){ 183 s++; 184 continue; 185 } 186 if(sp.p0.y > sp.p1.y) { 187 pt = sp.p0; 188 sp.p0 = sp.p1; 189 sp.p1 = pt; 190 sp.d = -sp.d; 191 } 192 sp.num = sp.p1.x - sp.p0.x; 193 sp.den = sp.p1.y - sp.p0.y; 194 sp.dz = sdiv(sp.num, sp.den) << fixshift; 195 sp.dzrem = mod(sp.num, sp.den) << fixshift; 196 sp.dz += sdiv(sp.dzrem, sp.den); 197 sp.dzrem = mod(sp.dzrem, sp.den); 198 p++; 199 s++; 200 } 201 n = p; 202 if(n == 0) 203 return; 204 seg[p] = nil; 205 qsortycompare(seg, p); 206 207 onehalf = 0; 208 if(fixshift) 209 onehalf = 1 << (fixshift-1); 210 211 minx = dst.clipr.min.x; 212 maxx = dst.clipr.max.x; 213 214 y = seg[0].p0.y; 215 if(y < (dst.clipr.min.y << fixshift)) 216 y = dst.clipr.min.y << fixshift; 217 iy = (y + onehalf) >> fixshift; 218 y = (iy << fixshift) + onehalf; 219 maxy = dst.clipr.max.y << fixshift; 220 k = (iy-zr.min.y)*xlen; 221 zv = dc+iy*dy; 222 223 ep = next = 0; 224 225 while(y<maxy) { 226 for(q = p = 0; p < ep; p++) { 227 sp = seg[p]; 228 if(sp.p1.y < y) 229 continue; 230 sp.z += sp.dz; 231 sp.zerr += sp.dzrem; 232 if(sp.zerr >= sp.den) { 233 sp.z++; 234 sp.zerr -= sp.den; 235 if(sp.zerr < 0 || sp.zerr >= sp.den) 236 sys->print("bad ratzerr1: %d den %d dzrem %d\n", sp.zerr, sp.den, sp.dzrem); 237 } 238 seg[q] = sp; 239 q++; 240 } 241 242 for(p = next; seg[p] != nil; p++) { 243 sp = seg[p]; 244 if(sp.p0.y >= y) 245 break; 246 if(sp.p1.y < y) 247 continue; 248 sp.z = sp.p0.x; 249 (zinc, sp.zerr) = smuldivmod(y - sp.p0.y, sp.num, sp.den); 250 sp.z += zinc; 251 if(sp.zerr < 0 || sp.zerr >= sp.den) 252 sys->print("bad ratzerr2: %d den %d ratdzrem %d\n", sp.zerr, sp.den, sp.dzrem); 253 seg[q] = sp; 254 q++; 255 } 256 ep = q; 257 next = p; 258 259 if(ep == 0) { 260 if(seg[next] == nil) 261 break; 262 iy = (seg[next].p0.y + onehalf) >> fixshift; 263 y = (iy << fixshift) + onehalf; 264 k = (iy-zr.min.y)*xlen; 265 zv = dc+iy*dy; 266 continue; 267 } 268 269 zsort(seg, ep); 270 271 for(p = 0; p < ep; p++) { 272 sp = seg[p]; 273 cnt = 0; 274 x = sp.z; 275 ix = (x + onehalf) >> fixshift; 276 if(ix >= maxx) 277 break; 278 if(ix < minx) 279 ix = minx; 280 cnt += sp.d; 281 p++; 282 sp = seg[p]; 283 for(;;) { 284 if(p == ep) { 285 sys->print("xscan: fill to infinity"); 286 return; 287 } 288 cnt += sp.d; 289 if((cnt&wind) == 0) 290 break; 291 p++; 292 sp = seg[p]; 293 } 294 x2 = sp.z; 295 ix2 = (x2 + onehalf) >> fixshift; 296 if(ix2 <= minx) 297 continue; 298 if(ix2 > maxx) 299 ix2 = maxx; 300 filllinez(dst, ix, ix2, iy, zv+ix*dx, er, dx, k+ix-zr.min.x, zbuf0, zbuf1, src, spt); 301 } 302 y += (1<<fixshift); 303 iy++; 304 k += xlen; 305 zv += dy; 306 } 307} 308 309zsort(seg: array of ref Seg, ep: int) 310{ 311 done: int; 312 s: ref Seg; 313 q, p: int; 314 315 if(ep < 20) { 316 # bubble sort by z - they should be almost sorted already 317 q = ep; 318 do { 319 done = 1; 320 q--; 321 for(p = 0; p < q; p++) { 322 if(seg[p].z > seg[p+1].z) { 323 s = seg[p]; 324 seg[p] = seg[p+1]; 325 seg[p+1] = s; 326 done = 0; 327 } 328 } 329 } while(!done); 330 } else { 331 q = ep-1; 332 for(p = 0; p < q; p++) { 333 if(seg[p].z > seg[p+1].z) { 334 qsortzcompare(seg, ep); 335 break; 336 } 337 } 338 } 339} 340 341ycompare(s0: ref Seg, s1: ref Seg): int 342{ 343 y0, y1: int; 344 345 y0 = s0.p0.y; 346 y1 = s1.p0.y; 347 348 if(y0 < y1) 349 return -1; 350 if(y0 == y1) 351 return 0; 352 return 1; 353} 354 355zcompare(s0: ref Seg, s1: ref Seg): int 356{ 357 z0, z1: int; 358 359 z0 = s0.z; 360 z1 = s1.z; 361 362 if(z0 < z1) 363 return -1; 364 if(z0 == z1) 365 return 0; 366 return 1; 367} 368 369qsortycompare(a : array of ref Seg, n : int) 370{ 371 i, j : int; 372 t : ref Seg; 373 374 while(n > 1) { 375 i = n>>1; 376 t = a[0]; a[0] = a[i]; a[i] = t; 377 i = 0; 378 j = n; 379 for(;;) { 380 do 381 i++; 382 while(i < n && ycompare(a[i], a[0]) < 0); 383 do 384 j--; 385 while(j > 0 && ycompare(a[j], a[0]) > 0); 386 if(j < i) 387 break; 388 t = a[i]; a[i] = a[j]; a[j] = t; 389 } 390 t = a[0]; a[0] = a[j]; a[j] = t; 391 n = n-j-1; 392 if(j >= n) { 393 qsortycompare(a, j); 394 a = a[j+1:]; 395 } else { 396 qsortycompare(a[j+1:], n); 397 n = j; 398 } 399 } 400} 401 402qsortzcompare(a : array of ref Seg, n : int) 403{ 404 i, j : int; 405 t : ref Seg; 406 407 while(n > 1) { 408 i = n>>1; 409 t = a[0]; a[0] = a[i]; a[i] = t; 410 i = 0; 411 j = n; 412 for(;;) { 413 do 414 i++; 415 while(i < n && zcompare(a[i], a[0]) < 0); 416 do 417 j--; 418 while(j > 0 && zcompare(a[j], a[0]) > 0); 419 if(j < i) 420 break; 421 t = a[i]; a[i] = a[j]; a[j] = t; 422 } 423 t = a[0]; a[0] = a[j]; a[j] = t; 424 n = n-j-1; 425 if(j >= n) { 426 qsortzcompare(a, j); 427 a = a[j+1:]; 428 } else { 429 qsortzcompare(a[j+1:], n); 430 n = j; 431 } 432 } 433} 434 435abs(n: int): int 436{ 437 if(n < 0) 438 return -n; 439 return n; 440} 441