fillpoly.c 9.6 KB

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