|
|
1.1 root 1: #include <jerq.h>
2: #define SILLY -20
3:
4: /* Filling interior of arbitrary polygons on the Blit */
5: static draw(), xcut(), place(), realfill();
6:
7: #ifdef TEST
8: #include <font.h>
9: Texture black =
10: {
11: 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
12: 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
13: };
14:
15: main()
16: {
17: Point pts[40], *p;
18:
19: request(MOUSE);
20: string(&defont, "b1 vertex; b2 end; b3 exit", &display, Drect.origin, F_XOR);
21: p = pts;
22: for(;;)
23: {
24: wait(CPU);
25: wait(MOUSE);
26: if((own()&MOUSE) && button1())
27: {
28: *p++ = mouse.xy;
29: if(p != pts) segment(&display, p[-2], p[-1], F_OR);
30: while(button1()) nap(1);
31: }
32: if((own()&MOUSE) && button2())
33: {
34: *p++ = pts[0];
35: while(button2()) nap(1);
36: ppfill(pts, (int)(p-pts), &display, &black, F_OR);
37: p = pts;
38: }
39: if((own()&MOUSE) && button3())
40: {
41: while(button3()) nap(1);
42: exit(0);
43: }
44: }
45: }
46: #endif TEST
47:
48: struct seg { short x, y, X, Y; char stat;} ;
49: typedef struct seg segS;
50: typedef struct seg * segP;
51: typedef Point *pointP;
52: #ifdef BRAVE
53: segP sinp;
54: #else
55: segS sinp[128];
56: #endif
57:
58: static short ymin;
59:
60: #define COMP(A) if(p1->A>p2->A) return(-1); else if(p1->A<p2->A) return(1);
61:
62: static
63: place(p1,p2) segP p1, p2;
64: {
65: COMP(y) else {
66: COMP(x) else {
67: COMP(X) else {
68: COMP(Y) else return(0);
69: }
70: }
71: }
72: }
73:
74: #define SWITCH { xyt=y; y=Y; Y=xyt; xyt=x; x=X; X=xyt; ren=0;}
75:
76: ppfill(pts, npts, bm, text, mode)
77: Point *pts;
78: Bitmap *bm;
79: Texture *text;
80: {
81: short so;
82: short x, y, X, Y;
83: short xyt, ren, newc;
84: register pointP pp, qq, opp;
85: register segP sp;
86: register j;
87:
88: #ifdef BRAVE
89: sinp = (segP)alloc((unsigned)((npts+2)*sizeof(segS)));
90: if(!sinp) return(-1);
91: #else
92: if(npts>125) return(-1);
93: #endif
94: #ifdef EFFIC
95: if(npts==4){
96: rectf(bm,Rect(pts->x,pts->y,
97: (pts[2]).x,(pts[2]).y),mode);
98: }
99: #endif
100: ymin = Drect.origin.y;
101: qq = pts;
102: x = qq->x; y = qq->y;
103: pp = qq + 1;
104: for(j=1,sp=sinp,so=0;j<=npts;j++,pp++) {
105: /* missing: we should take precaution abt HH */
106: if(j==npts) pp = qq;
107: if(pp->x < SILLY) { /*break in contour*/
108: opp = pp;
109: pp = qq;
110: newc = 1;
111: }
112: else newc = 0;
113: X = pp->x; Y = pp->y;
114: if(Y<ymin) ymin = Y;
115: if(Y>y) SWITCH
116: else {if(Y==y && x<X) SWITCH else ren=1;}
117: sp->x=x; sp->y=y; sp->X=X; sp->Y=Y; sp->stat=1;
118: if(ren) { x = X; y = Y;}
119: sp++; so++;
120: if(newc) {
121: qq = opp + 1;
122: if(!qq) break;
123: x = qq->x; y = qq->y;
124: pp = qq; /*will be incr. in loop*/
125: j++;
126: }
127: }
128: realfill(so,ymin,bm,text,mode);
129: #ifdef BRAVE
130: free(sinp);
131: #endif
132: return(1);
133: }
134:
135: /* Fill a contour defined by a set of line segments */
136:
137: static
138: realfill(so, yymin, bm, text, mode)
139: int so, yymin;
140: Bitmap *bm;
141: Texture *text;
142: {
143: int i, n;
144: int yb;
145: segP sp, s1, s2, sfin, st, sbf, snx;
146: for(i=0,sp=sinp;i<so;i++,sp++) sp->stat = 1;
147: sfin = sp; /*sp was not incremented last time*/
148: /* edit horizontal lines */
149: for(i=0,sp=sinp;i<so;i++,sp++){
150: if(!(sp->stat)) continue;
151: if(sp->y != sp->Y) continue;
152: if(sp==sinp) sbf = sp+so-1;
153: else sbf = sp-1;
154: if(sp<sfin) snx = sp+1;
155: else snx = sp;
156: if(sbf->y==sp->y){ /* point before is below*/
157: if(snx->y==sp->y){ /* both below */
158: sp->stat = 0;
159: }
160: continue;
161: }
162: else if(sbf->Y==sp->y){ /*previous point above*/
163: if(snx->Y==sp->y){ /* both above */
164: sp->stat = 0;
165: }
166: continue;
167: }
168: }
169: /* finished with horizontal editing */
170:
171: qsort(sinp,so,sizeof(struct seg),place);
172:
173: sp = sinp;
174: i = 0;
175: n = so;
176: s1 = sp;
177: yb = s1->y;
178: for(;yb<=sp->y;sp++,i++);
179: s2 = sp - 1;
180: for(;yb>=yymin;yb--){
181: draw(yb,s1,s2, bm, text, mode);
182: for(st=s1;st<=s2;st++){
183: if(!(st->stat)) continue;
184: if(yb<=st->Y) st->stat=0;
185: }
186: if(sp >= sfin) continue; /*nomore*/
187: if(i>=n) continue;
188: for(;yb<=(sp->y+1)&&i<n;sp++,i++){ /*we have gone below next element */
189: for(st=s1;st<=s2;st++){
190: if(sp->y==st->Y){
191: if(sp->x==st->X) st->stat=0;
192: else if(sp->Y==sp->y&&sp->X==st->X) st->stat=0;
193: }
194: }
195: }
196: /*cleanup*/
197: s2 = sp - 1;
198: while(!(s1->stat)) s1++;
199: }
200: }
201:
202: #define NCUTS 32
203: #define NCUTS_1 31
204:
205: static
206: draw(y,pr1,pr2, bm, text, mode)
207: int y; segP pr1, pr2;
208: Bitmap *bm;
209: Texture *text;
210: {
211: register segP pr;
212: register i, j, k, n;
213: int x[NCUTS];
214: for(pr=pr1,n=0;pr<=pr2;pr++){
215: if(!(pr->stat)) continue;
216: if(pr->y==pr->Y) continue; /* ignore horizontals */
217: x[n++] = xcut(y,pr->x,pr->y,pr->X,pr->Y);
218: if(n>NCUTS_1) /*jtag(1,"Too many intersections")*/;
219: }
220: if(n<=1) return(0);
221: k=1;
222: while(k){
223: k = 0;
224: for(i=1;i<n;i++){
225: if(x[i-1]>x[i]) {
226: j=x[i-1];
227: x[i-1]=x[i];
228: x[i]=j;
229: k=1;
230: }
231: }
232: }
233: for(i=1;i<n;i +=2)
234: texture(bm,Rect(x[i-1],y,x[i]+1,y+2),text, mode);
235:
236: return(1);
237: }
238:
239: static
240: xcut(y,x1,y1,x2,y2){
241: long dx, dy, xy;
242: int x;
243: if(y1==y2) {
244: x = x1>x2? x1: x2;
245: return(x);
246: }
247: dy = y1-y2;
248: dx = x1-x2;
249: xy = (long)y1*x2-x1*(long)y2;
250: x = (y*dx+xy)/dy; /*dy non zero because of prev. check*/
251: return(x);
252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.