|
|
1.1 ! root 1: #include <jerq.h> ! 2: ! 3: static emax(a,b) { return((a<b)? b:a); } ! 4: static emin(a,b) { return((a>b)? b:a); } ! 5: static ycmp(), xcmp(), xcut(); ! 6: ! 7: typedef struct Edge ! 8: { ! 9: Point p1, p2; ! 10: short dolow; ! 11: } Edge; ! 12: static Edge edges[300]; ! 13: static Edge *canon(); ! 14: ! 15: polyture(bp, pts, n, t, mode) ! 16: Bitmap *bp; ! 17: Point *pts; ! 18: Texture *t; ! 19: { ! 20: register Edge *eend, *e, *estart; ! 21: register y; ! 22: int ymin, ymax, flag; ! 23: Point p; ! 24: int xcuts[64], *xp, *x; ! 25: ! 26: eend = canon(pts, n, &ymax); ! 27: qsort(edges, eend-edges, sizeof(edges[0]), ycmp); ! 28: ymin = edges->p1.y; ! 29: eend->p1.y = eend->p2.y = ymax+1; ! 30: /* ! 31: traditional scanline ! 32: */ ! 33: for(estart = eend = edges, y = ymin; y <= ymax; y++) ! 34: { ! 35: while(estart->p2.y < y) estart++; ! 36: while(eend->p1.y <= y) eend++; ! 37: for(e = estart, xp = xcuts; e < eend; e++) ! 38: if((y < e->p2.y) || (e->dolow && (y == e->p2.y))) ! 39: *xp++ = xcut(y, e); ! 40: qsort(xcuts, xp-xcuts, sizeof(*xp), xcmp); ! 41: for(x = xcuts; x < xp; x += 2) ! 42: texture(bp, Rect(*x, y, x[1]+1, y+1), t, mode); ! 43: } ! 44: } ! 45: ! 46: static Edge * ! 47: canon(pts, n, ymax) ! 48: register Point *pts; ! 49: register *ymax; ! 50: { ! 51: register Edge *le, *e; ! 52: register Point *p, *lp, pt; ! 53: int vert; ! 54: ! 55: /* ! 56: delete horizontal edges; compact vertical edges into one ! 57: */ ! 58: p = pts; ! 59: lp = p+n; ! 60: e = edges; ! 61: *ymax = p->y; ! 62: e->p1 = *p++; ! 63: for(vert = 0; p < lp; p++) ! 64: { ! 65: if(*ymax < p->y) *ymax = p->y; ! 66: if(p->y == p[-1].y) ! 67: { ! 68: vert = 0; ! 69: e->p1 = *p; ! 70: continue; ! 71: } ! 72: if(vert && (p->x == p[-1].x)) ! 73: e->p2.y = p->y; ! 74: else ! 75: { ! 76: if(vert) ! 77: e[1].p1 = e->p2, e++; ! 78: e++->p2 = *p; ! 79: e->p1 = *p; ! 80: if(vert = p->x == p[-1].x) e--; ! 81: } ! 82: } ! 83: if(vert) e++; ! 84: le = e; ! 85: *le = edges[0]; ! 86: le[1] = edges[1]; ! 87: for(e = edges+1; e <= le; e++) ! 88: { ! 89: if(e->p1.y < e->p2.y) /* going down */ ! 90: e->dolow = (e[1].p1.y-e[1].p2.y) > 0; ! 91: else ! 92: e->dolow = (e[-1].p1.y-e[-1].p2.y) < 0; ! 93: } ! 94: edges[0] = *le; ! 95: /* ! 96: canonise the edges so that p1.y < p2.y ! 97: or if p1.y == p2.y then p1.x < p2.x. ! 98: */ ! 99: for(e = edges; e < le; e++) ! 100: { ! 101: if((e->p1.y > e->p2.y) || ((e->p1.y == e->p2.y)&&(e->p1.x > e->p2.x))) ! 102: pt = e->p1, e->p1 = e->p2, e->p2 = pt; ! 103: } ! 104: return(le); ! 105: } ! 106: ! 107: static ! 108: ycmp(a, b) ! 109: register Edge *a, *b; ! 110: { ! 111: register k; ! 112: ! 113: if(k = a->p1.y - b->p1.y) ! 114: return(k); ! 115: return(a->p2.y - b->p2.y); ! 116: } ! 117: ! 118: static ! 119: xcmp(a, b) ! 120: register int *a, *b; ! 121: { ! 122: return(*a - *b); ! 123: } ! 124: ! 125: static ! 126: xcut(y, e) ! 127: register Edge *e; ! 128: { ! 129: return(e->p1.x + muldiv(e->p2.x-e->p1.x, y-e->p1.y, e->p2.y-e->p1.y)); ! 130: } ! 131:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.