LibVNCServer/LibVNCClient
rfbregion.c
Go to the documentation of this file.
1 /* -=- sraRegion.c
2  * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
3  *
4  * A general purpose region clipping library
5  * Only deals with rectangular regions, though.
6  */
7 
8 #include <rfb/rfb.h>
9 #include <rfb/rfbregion.h>
10 
11 /* -=- Internal Span structure */
12 
13 struct sraRegion;
14 
15 typedef struct sraSpan {
16  struct sraSpan *_next;
17  struct sraSpan *_prev;
18  int start;
19  int end;
20  struct sraRegion *subspan;
21 } sraSpan;
22 
23 typedef struct sraRegion {
26 } sraSpanList;
27 
28 /* -=- Span routines */
29 
32 
33 static sraSpan *
34 sraSpanCreate(int start, int end, const sraSpanList *subspan) {
35  sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
36  if (!item) return NULL;
37  item->_next = item->_prev = NULL;
38  item->start = start;
39  item->end = end;
40  item->subspan = sraSpanListDup(subspan);
41  return item;
42 }
43 
44 static sraSpan *
45 sraSpanDup(const sraSpan *src) {
46  sraSpan *span;
47  if (!src) return NULL;
48  span = sraSpanCreate(src->start, src->end, src->subspan);
49  return span;
50 }
51 
52 static void
53 sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
54  if(newspan && after) {
55  newspan->_next = after->_next;
56  newspan->_prev = after;
57  after->_next->_prev = newspan;
58  after->_next = newspan;
59  }
60 }
61 
62 static void
63 sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
64  if(newspan && before) {
65  newspan->_next = before;
66  newspan->_prev = before->_prev;
67  before->_prev->_next = newspan;
68  before->_prev = newspan;
69  }
70 }
71 
72 static void
73 sraSpanRemove(sraSpan *span) {
74  if(span) {
75  span->_prev->_next = span->_next;
76  span->_next->_prev = span->_prev;
77  }
78 }
79 
80 static void
81 sraSpanDestroy(sraSpan *span) {
82  if (span->subspan) sraSpanListDestroy(span->subspan);
83  free(span);
84 }
85 
86 #ifdef DEBUG
87 static void
88 sraSpanCheck(const sraSpan *span, const char *text) {
89  /* Check the span is valid! */
90  if (span->start == span->end) {
91  printf(text);
92  printf(":%d-%d\n", span->start, span->end);
93  }
94 }
95 #endif
96 
97 /* -=- SpanList routines */
98 
99 static void sraSpanPrint(const sraSpan *s);
100 
101 static void
102 sraSpanListPrint(const sraSpanList *l) {
103  sraSpan *curr;
104  if (!l) {
105  printf("NULL");
106  return;
107  }
108  curr = l->front._next;
109  printf("[");
110  while (curr != &(l->back)) {
111  sraSpanPrint(curr);
112  curr = curr->_next;
113  }
114  printf("]");
115 }
116 
117 void
118 sraSpanPrint(const sraSpan *s) {
119  printf("(%d-%d)", (s->start), (s->end));
120  if (s->subspan)
121  sraSpanListPrint(s->subspan);
122 }
123 
124 static sraSpanList *
125 sraSpanListCreate(void) {
126  sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
127  if (!item) return NULL;
128  item->front._next = &(item->back);
129  item->front._prev = NULL;
130  item->back._prev = &(item->front);
131  item->back._next = NULL;
132  return item;
133 }
134 
135 sraSpanList *
137  sraSpanList *newlist;
138  sraSpan *newspan, *curr;
139 
140  if (!src) return NULL;
141  newlist = sraSpanListCreate();
142  curr = src->front._next;
143  while (curr != &(src->back)) {
144  newspan = sraSpanDup(curr);
145  sraSpanInsertBefore(newspan, &(newlist->back));
146  curr = curr->_next;
147  }
148 
149  return newlist;
150 }
151 
152 void
154  sraSpan *curr;
155  while (list->front._next != &(list->back)) {
156  curr = list->front._next;
157  sraSpanRemove(curr);
158  sraSpanDestroy(curr);
159  }
160  free(list);
161 }
162 
163 static void
164 sraSpanListMakeEmpty(sraSpanList *list) {
165  sraSpan *curr;
166  while (list->front._next != &(list->back)) {
167  curr = list->front._next;
168  sraSpanRemove(curr);
169  sraSpanDestroy(curr);
170  }
171  list->front._next = &(list->back);
172  list->front._prev = NULL;
173  list->back._prev = &(list->front);
174  list->back._next = NULL;
175 }
176 
177 static rfbBool
178 sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
179  sraSpan *sp1, *sp2;
180 
181  if (!s1) {
182  if (!s2) {
183  return 1;
184  } else {
185  rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n");
186  return FALSE;
187  }
188  }
189 
190  sp1 = s1->front._next;
191  sp2 = s2->front._next;
192  while ((sp1 != &(s1->back)) &&
193  (sp2 != &(s2->back))) {
194  if ((sp1->start != sp2->start) ||
195  (sp1->end != sp2->end) ||
196  (!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
197  return 0;
198  }
199  sp1 = sp1->_next;
200  sp2 = sp2->_next;
201  }
202 
203  if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
204  return 1;
205  } else {
206  return 0;
207  }
208 }
209 
210 static rfbBool
211 sraSpanListEmpty(const sraSpanList *list) {
212  return (list->front._next == &(list->back));
213 }
214 
215 static unsigned long
216 sraSpanListCount(const sraSpanList *list) {
217  sraSpan *curr = list->front._next;
218  unsigned long count = 0;
219  while (curr != &(list->back)) {
220  if (curr->subspan) {
221  count += sraSpanListCount(curr->subspan);
222  } else {
223  count += 1;
224  }
225  curr = curr->_next;
226  }
227  return count;
228 }
229 
230 static void
231 sraSpanMergePrevious(sraSpan *dest) {
232  sraSpan *prev = dest->_prev;
233 
234  while ((prev->_prev) &&
235  (prev->end == dest->start) &&
236  (sraSpanListEqual(prev->subspan, dest->subspan))) {
237  /*
238  printf("merge_prev:");
239  sraSpanPrint(prev);
240  printf(" & ");
241  sraSpanPrint(dest);
242  printf("\n");
243  */
244  dest->start = prev->start;
245  sraSpanRemove(prev);
246  sraSpanDestroy(prev);
247  prev = dest->_prev;
248  }
249 }
250 
251 static void
252 sraSpanMergeNext(sraSpan *dest) {
253  sraSpan *next = dest->_next;
254  while ((next->_next) &&
255  (next->start == dest->end) &&
256  (sraSpanListEqual(next->subspan, dest->subspan))) {
257 /*
258  printf("merge_next:");
259  sraSpanPrint(dest);
260  printf(" & ");
261  sraSpanPrint(next);
262  printf("\n");
263  */
264  dest->end = next->end;
265  sraSpanRemove(next);
266  sraSpanDestroy(next);
267  next = dest->_next;
268  }
269 }
270 
271 static void
272 sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
273  sraSpan *d_curr, *s_curr;
274  int s_start, s_end;
275 
276  if (!dest) {
277  if (!src) {
278  return;
279  } else {
280  rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n");
281  return;
282  }
283  }
284 
285  d_curr = dest->front._next;
286  s_curr = src->front._next;
287  s_start = s_curr->start;
288  s_end = s_curr->end;
289  while (s_curr != &(src->back)) {
290 
291  /* - If we are at end of destination list OR
292  If the new span comes before the next destination one */
293  if ((d_curr == &(dest->back)) ||
294  (d_curr->start >= s_end)) {
295  /* - Add the span */
296  sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
297  s_curr->subspan),
298  d_curr);
299  if (d_curr != &(dest->back))
300  sraSpanMergePrevious(d_curr);
301  s_curr = s_curr->_next;
302  s_start = s_curr->start;
303  s_end = s_curr->end;
304  } else {
305 
306  /* - If the new span overlaps the existing one */
307  if ((s_start < d_curr->end) &&
308  (s_end > d_curr->start)) {
309 
310  /* - Insert new span before the existing destination one? */
311  if (s_start < d_curr->start) {
312  sraSpanInsertBefore(sraSpanCreate(s_start,
313  d_curr->start,
314  s_curr->subspan),
315  d_curr);
316  sraSpanMergePrevious(d_curr);
317  }
318 
319  /* Split the existing span if necessary */
320  if (s_end < d_curr->end) {
321  sraSpanInsertAfter(sraSpanCreate(s_end,
322  d_curr->end,
323  d_curr->subspan),
324  d_curr);
325  d_curr->end = s_end;
326  }
327  if (s_start > d_curr->start) {
328  sraSpanInsertBefore(sraSpanCreate(d_curr->start,
329  s_start,
330  d_curr->subspan),
331  d_curr);
332  d_curr->start = s_start;
333  }
334 
335  /* Recursively OR subspans */
336  sraSpanListOr(d_curr->subspan, s_curr->subspan);
337 
338  /* Merge this span with previous or next? */
339  if (d_curr->_prev != &(dest->front))
340  sraSpanMergePrevious(d_curr);
341  if (d_curr->_next != &(dest->back))
342  sraSpanMergeNext(d_curr);
343 
344  /* Move onto the next pair to compare */
345  if (s_end > d_curr->end) {
346  s_start = d_curr->end;
347  d_curr = d_curr->_next;
348  } else {
349  s_curr = s_curr->_next;
350  s_start = s_curr->start;
351  s_end = s_curr->end;
352  }
353  } else {
354  /* - No overlap. Move to the next destination span */
355  d_curr = d_curr->_next;
356  }
357  }
358  }
359 }
360 
361 static rfbBool
362 sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
363  sraSpan *d_curr, *s_curr, *d_next;
364 
365  if (!dest) {
366  if (!src) {
367  return 1;
368  } else {
369  rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n");
370  return FALSE;
371  }
372  }
373 
374  d_curr = dest->front._next;
375  s_curr = src->front._next;
376  while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
377 
378  /* - If we haven't reached a destination span yet then move on */
379  if (d_curr->start >= s_curr->end) {
380  s_curr = s_curr->_next;
381  continue;
382  }
383 
384  /* - If we are beyond the current destination span then remove it */
385  if (d_curr->end <= s_curr->start) {
386  sraSpan *next = d_curr->_next;
387  sraSpanRemove(d_curr);
388  sraSpanDestroy(d_curr);
389  d_curr = next;
390  continue;
391  }
392 
393  /* - If we partially overlap a span then split it up or remove bits */
394  if (s_curr->start > d_curr->start) {
395  /* - The top bit of the span does not match */
396  d_curr->start = s_curr->start;
397  }
398  if (s_curr->end < d_curr->end) {
399  /* - The end of the span does not match */
400  sraSpanInsertAfter(sraSpanCreate(s_curr->end,
401  d_curr->end,
402  d_curr->subspan),
403  d_curr);
404  d_curr->end = s_curr->end;
405  }
406 
407  /* - Now recursively process the affected span */
408  if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
409  /* - The destination subspan is now empty, so we should remove it */
410  sraSpan *next = d_curr->_next;
411  sraSpanRemove(d_curr);
412  sraSpanDestroy(d_curr);
413  d_curr = next;
414  } else {
415  /* Merge this span with previous or next? */
416  if (d_curr->_prev != &(dest->front))
417  sraSpanMergePrevious(d_curr);
418 
419  /* - Move on to the next span */
420  d_next = d_curr;
421  if (s_curr->end >= d_curr->end) {
422  d_next = d_curr->_next;
423  }
424  if (s_curr->end <= d_curr->end) {
425  s_curr = s_curr->_next;
426  }
427  d_curr = d_next;
428  }
429  }
430 
431  while (d_curr != &(dest->back)) {
432  sraSpan *next = d_curr->_next;
433  sraSpanRemove(d_curr);
434  sraSpanDestroy(d_curr);
435  d_curr=next;
436  }
437 
438  return !sraSpanListEmpty(dest);
439 }
440 
441 static rfbBool
442 sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
443  sraSpan *d_curr, *s_curr;
444 
445  if (!dest) {
446  if (!src) {
447  return 1;
448  } else {
449  rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
450  return FALSE;
451  }
452  }
453 
454  d_curr = dest->front._next;
455  s_curr = src->front._next;
456  while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
457 
458  /* - If we haven't reached a destination span yet then move on */
459  if (d_curr->start >= s_curr->end) {
460  s_curr = s_curr->_next;
461  continue;
462  }
463 
464  /* - If we are beyond the current destination span then skip it */
465  if (d_curr->end <= s_curr->start) {
466  d_curr = d_curr->_next;
467  continue;
468  }
469 
470  /* - If we partially overlap the current span then split it up */
471  if (s_curr->start > d_curr->start) {
472  sraSpanInsertBefore(sraSpanCreate(d_curr->start,
473  s_curr->start,
474  d_curr->subspan),
475  d_curr);
476  d_curr->start = s_curr->start;
477  }
478  if (s_curr->end < d_curr->end) {
479  sraSpanInsertAfter(sraSpanCreate(s_curr->end,
480  d_curr->end,
481  d_curr->subspan),
482  d_curr);
483  d_curr->end = s_curr->end;
484  }
485 
486  /* - Now recursively process the affected span */
487  if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
488  /* - The destination subspan is now empty, so we should remove it */
489  sraSpan *next = d_curr->_next;
490  sraSpanRemove(d_curr);
491  sraSpanDestroy(d_curr);
492  d_curr = next;
493  } else {
494  /* Merge this span with previous or next? */
495  if (d_curr->_prev != &(dest->front))
496  sraSpanMergePrevious(d_curr);
497  if (d_curr->_next != &(dest->back))
498  sraSpanMergeNext(d_curr);
499 
500  /* - Move on to the next span */
501  if (s_curr->end > d_curr->end) {
502  d_curr = d_curr->_next;
503  } else {
504  s_curr = s_curr->_next;
505  }
506  }
507  }
508 
509  return !sraSpanListEmpty(dest);
510 }
511 
512 /* -=- Region routines */
513 
514 sraRegion *
516  return (sraRegion*)sraSpanListCreate();
517 }
518 
519 sraRegion *
520 sraRgnCreateRect(int x1, int y1, int x2, int y2) {
521  sraSpanList *vlist, *hlist;
522  sraSpan *vspan, *hspan;
523 
524  /* - Build the horizontal portion of the span */
525  hlist = sraSpanListCreate();
526  hspan = sraSpanCreate(x1, x2, NULL);
527  sraSpanInsertAfter(hspan, &(hlist->front));
528 
529  /* - Build the vertical portion of the span */
530  vlist = sraSpanListCreate();
531  vspan = sraSpanCreate(y1, y2, hlist);
532  sraSpanInsertAfter(vspan, &(vlist->front));
533 
534  sraSpanListDestroy(hlist);
535 
536  return (sraRegion*)vlist;
537 }
538 
539 sraRegion *
541  return (sraRegion*)sraSpanListDup((sraSpanList*)src);
542 }
543 
544 void
547 }
548 
549 void
551  sraSpanListMakeEmpty((sraSpanList*)rgn);
552 }
553 
554 /* -=- Boolean Region ops */
555 
556 rfbBool
557 sraRgnAnd(sraRegion *dst, const sraRegion *src) {
558  return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
559 }
560 
561 void
562 sraRgnOr(sraRegion *dst, const sraRegion *src) {
563  sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
564 }
565 
566 rfbBool
567 sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
568  return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
569 }
570 
571 void
572 sraRgnOffset(sraRegion *dst, int dx, int dy) {
573  sraSpan *vcurr, *hcurr;
574 
575  vcurr = ((sraSpanList*)dst)->front._next;
576  while (vcurr != &(((sraSpanList*)dst)->back)) {
577  vcurr->start += dy;
578  vcurr->end += dy;
579 
580  hcurr = vcurr->subspan->front._next;
581  while (hcurr != &(vcurr->subspan->back)) {
582  hcurr->start += dx;
583  hcurr->end += dx;
584  hcurr = hcurr->_next;
585  }
586 
587  vcurr = vcurr->_next;
588  }
589 }
590 
592  int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
593  sraSpan *vcurr, *hcurr;
594 
595  if(!src)
596  return sraRgnCreate();
597 
598  vcurr = ((sraSpanList*)src)->front._next;
599  while (vcurr != &(((sraSpanList*)src)->back)) {
600  if(vcurr->start<ymin)
601  ymin=vcurr->start;
602  if(vcurr->end>ymax)
603  ymax=vcurr->end;
604 
605  hcurr = vcurr->subspan->front._next;
606  while (hcurr != &(vcurr->subspan->back)) {
607  if(hcurr->start<xmin)
608  xmin=hcurr->start;
609  if(hcurr->end>xmax)
610  xmax=hcurr->end;
611  hcurr = hcurr->_next;
612  }
613 
614  vcurr = vcurr->_next;
615  }
616 
617  if(xmax<xmin || ymax<ymin)
618  return sraRgnCreate();
619 
620  return sraRgnCreateRect(xmin,ymin,xmax,ymax);
621 }
622 
623 rfbBool
624 sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
625  sraSpan *vcurr, *hcurr;
626  sraSpan *vend, *hend;
627  rfbBool right2left = (flags & 2) == 2;
628  rfbBool bottom2top = (flags & 1) == 1;
629 
630  /* - Pick correct order */
631  if (bottom2top) {
632  vcurr = ((sraSpanList*)rgn)->back._prev;
633  vend = &(((sraSpanList*)rgn)->front);
634  } else {
635  vcurr = ((sraSpanList*)rgn)->front._next;
636  vend = &(((sraSpanList*)rgn)->back);
637  }
638 
639  if (vcurr != vend) {
640  rect->y1 = vcurr->start;
641  rect->y2 = vcurr->end;
642 
643  /* - Pick correct order */
644  if (right2left) {
645  hcurr = vcurr->subspan->back._prev;
646  hend = &(vcurr->subspan->front);
647  } else {
648  hcurr = vcurr->subspan->front._next;
649  hend = &(vcurr->subspan->back);
650  }
651 
652  if (hcurr != hend) {
653  rect->x1 = hcurr->start;
654  rect->x2 = hcurr->end;
655 
656  sraSpanRemove(hcurr);
657  sraSpanDestroy(hcurr);
658 
659  if (sraSpanListEmpty(vcurr->subspan)) {
660  sraSpanRemove(vcurr);
661  sraSpanDestroy(vcurr);
662  }
663 
664 #if 0
665  printf("poprect:(%dx%d)-(%dx%d)\n",
666  rect->x1, rect->y1, rect->x2, rect->y2);
667 #endif
668  return 1;
669  }
670  }
671 
672  return 0;
673 }
674 
675 unsigned long
677  unsigned long count = sraSpanListCount((sraSpanList*)rgn);
678  return count;
679 }
680 
681 rfbBool
682 sraRgnEmpty(const sraRegion *rgn) {
683  return sraSpanListEmpty((sraSpanList*)rgn);
684 }
685 
686 /* iterator stuff */
688 {
689  /* these values have to be multiples of 4 */
690 #define DEFSIZE 4
691 #define DEFSTEP 8
693  (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
694  if(!i)
695  return NULL;
696 
697  /* we have to recurse eventually. So, the first sPtr is the pointer to
698  the sraSpan in the first level. the second sPtr is the pointer to
699  the sraRegion.back. The third and fourth sPtr are for the second
700  recursion level and so on. */
701  i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
702  if(!i->sPtrs) {
703  free(i);
704  return NULL;
705  }
706  i->ptrSize = DEFSIZE;
707  i->sPtrs[0] = &(s->front);
708  i->sPtrs[1] = &(s->back);
709  i->ptrPos = 0;
710  i->reverseX = 0;
711  i->reverseY = 0;
712  return i;
713 }
714 
716 {
718  if(reverseY) {
719  i->sPtrs[1] = &(s->front);
720  i->sPtrs[0] = &(s->back);
721  }
722  i->reverseX = reverseX;
723  i->reverseY = reverseY;
724  return(i);
725 }
726 
727 static rfbBool sraReverse(sraRectangleIterator *i)
728 {
729  return( ((i->ptrPos&2) && i->reverseX) ||
730  (!(i->ptrPos&2) && i->reverseY));
731 }
732 
733 static sraSpan* sraNextSpan(sraRectangleIterator *i)
734 {
735  if(sraReverse(i))
736  return(i->sPtrs[i->ptrPos]->_prev);
737  else
738  return(i->sPtrs[i->ptrPos]->_next);
739 }
740 
742 {
743  /* is the subspan finished? */
744  while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
745  i->ptrPos -= 2;
746  if(i->ptrPos < 0) /* the end */
747  return(0);
748  }
749 
750  i->sPtrs[i->ptrPos] = sraNextSpan(i);
751 
752  /* is this a new subspan? */
753  while(i->sPtrs[i->ptrPos]->subspan) {
754  if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
755  i->ptrSize += DEFSTEP;
756  i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
757  }
758  i->ptrPos += 2;
759  if(sraReverse(i)) {
760  i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
761  i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
762  } else {
763  i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
764  i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
765  }
766  }
767 
768  if((i->ptrPos%4)!=2) {
769  rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
770  return FALSE;
771  }
772 
773  r->y1 = i->sPtrs[i->ptrPos-2]->start;
774  r->y2 = i->sPtrs[i->ptrPos-2]->end;
775  r->x1 = i->sPtrs[i->ptrPos]->start;
776  r->x2 = i->sPtrs[i->ptrPos]->end;
777 
778  return(-1);
779 }
780 
782 {
783  free(i->sPtrs);
784  free(i);
785 }
786 
787 void
788 sraRgnPrint(const sraRegion *rgn) {
789  sraSpanListPrint((sraSpanList*)rgn);
790 }
791 
792 rfbBool
793 sraClipRect(int *x, int *y, int *w, int *h,
794  int cx, int cy, int cw, int ch) {
795  if (*x < cx) {
796  *w -= (cx-*x);
797  *x = cx;
798  }
799  if (*y < cy) {
800  *h -= (cy-*y);
801  *y = cy;
802  }
803  if (*x+*w > cx+cw) {
804  *w = (cx+cw)-*x;
805  }
806  if (*y+*h > cy+ch) {
807  *h = (cy+ch)-*y;
808  }
809  return (*w>0) && (*h>0);
810 }
811 
812 rfbBool
813 sraClipRect2(int *x, int *y, int *x2, int *y2,
814  int cx, int cy, int cx2, int cy2) {
815  if (*x < cx)
816  *x = cx;
817  if (*y < cy)
818  *y = cy;
819  if (*x >= cx2)
820  *x = cx2-1;
821  if (*y >= cy2)
822  *y = cy2-1;
823  if (*x2 <= cx)
824  *x2 = cx+1;
825  if (*y2 <= cy)
826  *y2 = cy+1;
827  if (*x2 > cx2)
828  *x2 = cx2;
829  if (*y2 > cy2)
830  *y2 = cy2;
831  return (*x2>*x) && (*y2>*y);
832 }
833 
834 /* test */
835 
836 #ifdef SRA_TEST
837 /* pipe the output to sort|uniq -u and you'll get the errors. */
838 int main(int argc, char** argv)
839 {
840  sraRegionPtr region, region1, region2;
842  sraRect rect;
843  rfbBool b;
844 
845  region = sraRgnCreateRect(10, 10, 600, 300);
846  region1 = sraRgnCreateRect(40, 50, 350, 200);
847  region2 = sraRgnCreateRect(0, 0, 20, 40);
848 
849  sraRgnPrint(region);
850  printf("\n[(10-300)[(10-600)]]\n\n");
851 
852  b = sraRgnSubtract(region, region1);
853  printf("%s ",b?"true":"false");
854  sraRgnPrint(region);
855  printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
856 
857  sraRgnOr(region, region2);
858  printf("%ld\n6\n\n", sraRgnCountRects(region));
859 
860  i = sraRgnGetIterator(region);
861  while(sraRgnIteratorNext(i, &rect))
862  printf("%dx%d+%d+%d ",
863  rect.x2-rect.x1,rect.y2-rect.y1,
864  rect.x1,rect.y1);
866  printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
867 
868  i = sraRgnGetReverseIterator(region,1,0);
869  while(sraRgnIteratorNext(i, &rect))
870  printf("%dx%d+%d+%d ",
871  rect.x2-rect.x1,rect.y2-rect.y1,
872  rect.x1,rect.y1);
874  printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
875 
876  i = sraRgnGetReverseIterator(region,1,1);
877  while(sraRgnIteratorNext(i, &rect))
878  printf("%dx%d+%d+%d ",
879  rect.x2-rect.x1,rect.y2-rect.y1,
880  rect.x1,rect.y1);
882  printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
883 
884  sraRgnDestroy(region);
885  sraRgnDestroy(region1);
886  sraRgnDestroy(region2);
887 
888  return(0);
889 }
890 #endif
rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2, int cx, int cy, int cx2, int cy2)
Definition: rfbregion.c:813
int x1
Definition: rfbregion.h:12
void sraRgnOr(sraRegion *dst, const sraRegion *src)
Definition: rfbregion.c:562
sraSpanList * sraSpanListDup(const sraSpanList *src)
Definition: rfbregion.c:136
#define DEFSIZE
int x
Definition: SDLvncviewer.c:34
unsigned long sraRgnCountRects(const sraRegion *rgn)
Definition: rfbregion.c:676
void sraRgnReleaseIterator(sraRectangleIterator *i)
Definition: rfbregion.c:781
rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src)
Definition: rfbregion.c:567
rfbLogProc rfbErr
Definition: main.c:264
void sraRgnDestroy(sraRegion *rgn)
Definition: rfbregion.c:545
struct sraRegion * sraRegionPtr
Definition: rfb.h:381
int8_t rfbBool
Definition: rfbproto.h:108
sraSpan back
Definition: rfbregion.c:25
int x2
Definition: rfbregion.h:14
sraRegion * sraRgnBBox(const sraRegion *src)
Definition: rfbregion.c:591
void sraRgnMakeEmpty(sraRegion *rgn)
Definition: rfbregion.c:550
sraRegion * sraRgnCreate(void)
Definition: rfbregion.c:515
sraRegion * sraRgnCreateRect(int x1, int y1, int x2, int y2)
Definition: rfbregion.c:520
int start
Definition: rfbregion.c:18
sraRectangleIterator * sraRgnGetIterator(sraRegion *s)
Definition: rfbregion.c:687
#define DEFSTEP
sraSpan front
Definition: rfbregion.c:24
int main(int argc, char **argv)
Definition: SDLvncviewer.c:456
int y2
Definition: rfbregion.h:15
int y1
Definition: rfbregion.h:13
rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src)
Definition: rfbregion.c:557
int y
Definition: SDLvncviewer.c:34
sraRectangleIterator * sraRgnGetReverseIterator(sraRegion *s, rfbBool reverseX, rfbBool reverseY)
Definition: rfbregion.c:715
rfbBool sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags)
Definition: rfbregion.c:624
sraRegion * sraRgnCreateRgn(const sraRegion *src)
Definition: rfbregion.c:540
struct sraRegion sraRegion
Definition: rfbregion.h:18
void sraRgnPrint(const sraRegion *rgn)
Definition: rfbregion.c:788
rfbBool sraRgnIteratorNext(sraRectangleIterator *i, sraRect *r)
Definition: rfbregion.c:741
int end
Definition: rfbregion.c:19
void sraSpanListDestroy(sraSpanList *list)
Definition: rfbregion.c:153
#define FALSE
Definition: rfbproto.h:110
struct sraSpan * _prev
Definition: rfbregion.c:17
rfbBool sraClipRect(int *x, int *y, int *w, int *h, int cx, int cy, int cw, int ch)
Definition: rfbregion.c:793
struct sraRegion * subspan
Definition: rfbregion.c:20
struct sraSpan * _next
Definition: rfbregion.c:16
struct sraSpan ** sPtrs
Definition: rfbregion.h:47
void sraRgnOffset(sraRegion *dst, int dx, int dy)
Definition: rfbregion.c:572
rfbBool sraRgnEmpty(const sraRegion *rgn)
Definition: rfbregion.c:682