Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "vnc.h"
2
#include "vncs.h"
3
 
4
static int tot;
5
static void rprint(Rlist*);
6
 
7
static void
8
growrlist(Rlist *rlist, int n)
9
{
10
	int old;
11
 
12
	if(rlist->nrect+n <= rlist->maxrect)
13
		return;
14
 
15
	old = rlist->maxrect;
16
	while(rlist->nrect+n > rlist->maxrect){
17
		if(rlist->maxrect == 0)
18
			rlist->maxrect = 16;
19
		else
20
			rlist->maxrect *= 2;
21
	}
22
 
23
	tot += rlist->maxrect - old;
24
	if(tot > 10000)
25
		sysfatal("too many rectangles");
26
 
27
	rlist->rect = realloc(rlist->rect, rlist->maxrect*sizeof(rlist->rect[0]));
28
	if(rlist->rect == nil)
29
		sysfatal("realloc failed in growrlist");
30
}
31
 
32
static void
33
rappend(Rlist *rl, Rectangle r)
34
{
35
	growrlist(rl, 1);
36
	rl->rect[rl->nrect++] = r;
37
}
38
 
39
/* remove rectangle i from the list */
40
static int
41
rtrim(Rlist *r, int i)
42
{
43
	if(i < 0 || i >= r->nrect)
44
		return 0;
45
	if(i == r->nrect-1){
46
		r->nrect--;
47
		return 1;
48
	}
49
	r->rect[i] = r->rect[--r->nrect];
50
	return 1;
51
}
52
 
53
static int
54
rectadjacent(Rectangle r, Rectangle s)
55
{
56
	return r.min.x<=s.max.x && s.min.x<=r.max.x &&
57
	       r.min.y<=s.max.y && s.min.y<=r.max.y;
58
}
59
 
60
/*
61
 * If s shares three edges with r, compute the
62
 * rectangle r - s and return 1.
63
 * Else return 0.
64
 */
65
static int
66
rectubr(Rectangle *r, Rectangle s)
67
{
68
	if(r->min.y==s.min.y && r->max.y==s.max.y){
69
		if(r->min.x == s.min.x){
70
			r->min.x = s.max.x;
71
			assert(r->max.x > r->min.x);
72
			return 1;
73
		}
74
		if(r->max.x == s.max.x){
75
			r->max.x = s.min.x;
76
			assert(r->max.x > r->min.x);
77
			return 1;
78
		}
79
	}
80
	if(r->min.x==s.min.x && r->max.x==s.max.x){
81
		if(r->min.y == s.min.y){
82
			r->min.y = s.max.y;
83
			assert(r->max.y > r->min.y);
84
			return 1;
85
		}
86
		if(r->max.y == s.max.y){
87
			r->max.y = s.min.y;
88
			assert(r->max.y > r->min.y);
89
			return 1;
90
		}
91
	}
92
	return 0;
93
}
94
 
95
/*
96
 * If s is a corner of r, remove s from r, yielding
97
 * two rectangles r and rr.  R holds the part with
98
 * smaller coordinates.
99
 */
100
static int
101
rectcornersubr(Rectangle *r, Rectangle s, Rectangle *rr)
102
{
103
#	define UPRIGHT(r) Pt((r).max.x, (r).min.y)
104
#	define LOWLEFT(r) Pt((r).min.x, (r).max.y)
105
 
106
	*rr = *r;
107
 
108
	if(s.min.x == r->min.x){  
109
		if(s.min.y == r->min.y){  // upper left
110
			*rr = Rpt(UPRIGHT(s), r->max);
111
			*r = Rpt(LOWLEFT(s), LOWLEFT(*rr));
112
			return 1;
113
		}
114
		if(s.max.y == r->max.y){ // lower left
115
			*rr = Rpt(Pt(s.max.x, r->min.y), r->max);
116
			*r = Rpt(r->min, UPRIGHT(s));
117
			return 1;
118
		}
119
	}
120
	if(s.max.x == r->max.x){
121
		if(s.max.y == r->max.y){ // lower right
122
			*rr = Rpt(Pt(s.min.x, r->min.y), UPRIGHT(s));
123
			*r = Rpt(r->min, LOWLEFT(s));
124
			return 1;
125
		}
126
		if(s.min.y == r->min.y){ // upper right
127
			*rr = Rpt(LOWLEFT(s), r->max);
128
			*r = Rpt(r->min, LOWLEFT(*rr));
129
			return 1;
130
		}
131
	}
132
	return 0;
133
}
134
 
135
/*
136
 * If s is a band cutting r into two pieces, set r to one piece
137
 * and rr to the other.
138
 */
139
static int
140
recttridesubr(Rectangle *nr, Rectangle s, Rectangle *rr)
141
{
142
	*rr = *nr;
143
	if((nr->min.x == s.min.x && nr->max.x == s.max.x) &&
144
	    (nr->min.y < s.min.y && s.max.y < nr->max.y)){
145
		nr->max.y = s.min.y;
146
		rr->min.y = s.max.y;
147
		return 1;
148
	}
149
 
150
	if((nr->min.y == s.min.y && nr->max.y == s.max.y) &&
151
	    (nr->min.x < s.min.x && s.max.x < nr->max.x)){
152
		nr->max.x = s.min.x;
153
		rr->min.x = s.max.x;
154
		return 1;
155
	}
156
	return 0;
157
}
158
 
159
void
160
addtorlist(Rlist *rlist, Rectangle r)
161
{
162
	int i, j;
163
	Rectangle ir, cr, rr;
164
	Rlist tmp;
165
 
166
	if(r.min.x >= r.max.x || r.min.y >= r.max.y)
167
		return;
168
 
169
	memset(&tmp, 0, sizeof tmp);
170
	rappend(&tmp, r);
171
 
172
	if(verbose > 5)
173
		fprint(2, "region union add %R:\n", r);
174
 
175
	combinerect(&rlist->bbox, r); // must do this first
176
	for(j = 0; j < tmp.nrect; j++){
177
		r = tmp.rect[j];
178
 
179
		for(i=0; i < rlist->nrect; i++){
180
			ir = rlist->rect[i];
181
 
182
			if(verbose > 5)
183
				fprint(2, "checking %R against %R\n", r, ir);
184
			if(!rectadjacent(ir, r))
185
				continue;
186
 
187
			/* r is covered by ir? */
188
			if(rectinrect(r, ir))
189
				break;
190
 
191
			/* r covers ir? */
192
 			if(rectinrect(ir, r)){
193
				rtrim(rlist, i);
194
				i--;
195
				continue;
196
			}
197
 
198
			/* aligned and overlapping? */
199
			if((ir.min.y == r.min.y && ir.max.y == r.max.y) ||
200
		    	(ir.min.x == r.min.x && ir.max.x == r.max.x)){
201
				combinerect(&r, ir);
202
				rtrim(rlist, i);
203
				i--;
204
				continue;
205
			}
206
 
207
			/* not aligned */ 
208
			if(verbose > 5)
209
				fprint(2, "break up rect %R and %R\n", ir, r);
210
			/* 2->2 breakup */
211
			cr = ir;
212
			if (!rectclip(&cr, r))	/* share only one point */
213
				continue;
214
 
215
			if(rectubr(&r, cr))
216
				continue;
217
 
218
			if(rectubr(&rlist->rect[i], cr))
219
				continue;
220
 
221
			/* 2 -> 3 breakup */
222
			/* stride across */
223
			if(recttridesubr(&r, cr, &rr)){
224
				rappend(&tmp, rr);
225
				continue;
226
			}
227
 
228
			/* corner overlap */
229
			if(rectcornersubr(&r, cr, &rr)){
230
				rappend(&tmp, rr);
231
				continue;
232
			}
233
			abort();
234
		}
235
		if(i == rlist->nrect)
236
			rappend(rlist, r);
237
	}
238
	freerlist(&tmp);
239
	if(verbose > 5)
240
		rprint(rlist);
241
}
242
 
243
void
244
freerlist(Rlist *r)
245
{
246
	free(r->rect);
247
	tot -= r->maxrect;
248
	r->nrect = 0;
249
	r->maxrect = 0;
250
	r->rect = nil;
251
}
252
 
253
static void
254
rprint(Rlist *r)
255
{
256
	int i;
257
 
258
	fprint(2, "rlist %p:", r);
259
	for(i=0; i<r->nrect; i++)
260
		fprint(2, " %R", r->rect[i]);
261
	fprint(2, "\n");
262
}
263
 
264
 
265
#ifdef REGION_DEBUG
266
 
267
int verbose = 10;
268
 
269
void main(int argc, char * argv[])
270
{
271
	Rectangle r1 = Rect(0, 0, 300, 200);
272
	Rectangle r2 = Rect(100, 100, 400, 300);
273
	Rectangle r3 = Rect(200, 100, 500, 300);
274
	Region reg;
275
 
276
	initdraw(0, 0, "vncviewer");
277
	region_init(&reg);
278
	region_union(&reg, r1, r1);
279
	region_union(&reg, r2, r2);
280
	region_union(&reg, r3, r3);
281
}
282
 
283
#endif