fillpoly.c 9.6 KB

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