|
|
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.