|
|
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: e++->p2 = *p;
68: e->p1 = *p;
69: }
70: if(vert) e++;
71: le = e;
72: *le = edges[0];
73: le[1] = edges[1];
74: for(e = edges+1; e <= le; e++)
75: {
76: if(e->p1.y < e->p2.y) /* going down */
77: e->dolow = (e[1].p1.y-e[1].p2.y) > 0;
78: else
79: e->dolow = (e[-1].p1.y-e[-1].p2.y) < 0;
80: }
81: edges[0] = *le;
82: /*
83: canonise the edges so that p1.y < p2.y
84: or if p1.y == p2.y then p1.x < p2.x.
85: */
86: for(e = edges; e < le; e++)
87: {
88: if((e->p1.y > e->p2.y) || ((e->p1.y == e->p2.y)&&(e->p1.x > e->p2.x)))
89: pt = e->p1, e->p1 = e->p2, e->p2 = pt;
90: }
91: return(le);
92: }
93:
94: static
95: ycmp(a, b)
96: register Edge *a, *b;
97: {
98: register k;
99:
100: if(k = a->p1.y - b->p1.y)
101: return(k);
102: return(a->p2.y - b->p2.y);
103: }
104:
105: static
106: xcmp(a, b)
107: register int *a, *b;
108: {
109: return(*a - *b);
110: }
111:
112: static
113: xcut(y, e)
114: register Edge *e;
115: {
116: return(e->p1.x + muldiv(e->p2.x-e->p1.x, y-e->p1.y, e->p2.y-e->p1.y));
117: }
118:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.