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