00001
00002
00003
00004
00005
00006
00007
00008 #include <rfb/rfb.h>
00009 #include <rfb/rfbregion.h>
00010
00011
00012
00013 struct sraRegion;
00014
00015 typedef struct sraSpan {
00016 struct sraSpan *_next;
00017 struct sraSpan *_prev;
00018 int start;
00019 int end;
00020 struct sraRegion *subspan;
00021 } sraSpan;
00022
00023 typedef struct sraRegion {
00024 sraSpan front;
00025 sraSpan back;
00026 } sraSpanList;
00027
00028
00029
00030 sraSpanList *sraSpanListDup(const sraSpanList *src);
00031 void sraSpanListDestroy(sraSpanList *list);
00032
00033 static sraSpan *
00034 sraSpanCreate(int start, int end, const sraSpanList *subspan) {
00035 sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
00036 item->_next = item->_prev = NULL;
00037 item->start = start;
00038 item->end = end;
00039 item->subspan = sraSpanListDup(subspan);
00040 return item;
00041 }
00042
00043 static sraSpan *
00044 sraSpanDup(const sraSpan *src) {
00045 sraSpan *span;
00046 if (!src) return NULL;
00047 span = sraSpanCreate(src->start, src->end, src->subspan);
00048 return span;
00049 }
00050
00051 static void
00052 sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
00053 newspan->_next = after->_next;
00054 newspan->_prev = after;
00055 after->_next->_prev = newspan;
00056 after->_next = newspan;
00057 }
00058
00059 static void
00060 sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
00061 newspan->_next = before;
00062 newspan->_prev = before->_prev;
00063 before->_prev->_next = newspan;
00064 before->_prev = newspan;
00065 }
00066
00067 static void
00068 sraSpanRemove(sraSpan *span) {
00069 span->_prev->_next = span->_next;
00070 span->_next->_prev = span->_prev;
00071 }
00072
00073 static void
00074 sraSpanDestroy(sraSpan *span) {
00075 if (span->subspan) sraSpanListDestroy(span->subspan);
00076 free(span);
00077 }
00078
00079 #ifdef DEBUG
00080 static void
00081 sraSpanCheck(const sraSpan *span, const char *text) {
00082
00083 if (span->start == span->end) {
00084 printf(text);
00085 printf(":%d-%d\n", span->start, span->end);
00086 }
00087 }
00088 #endif
00089
00090
00091
00092 static void sraSpanPrint(const sraSpan *s);
00093
00094 static void
00095 sraSpanListPrint(const sraSpanList *l) {
00096 sraSpan *curr;
00097 if (!l) {
00098 printf("NULL");
00099 return;
00100 }
00101 curr = l->front._next;
00102 printf("[");
00103 while (curr != &(l->back)) {
00104 sraSpanPrint(curr);
00105 curr = curr->_next;
00106 }
00107 printf("]");
00108 }
00109
00110 void
00111 sraSpanPrint(const sraSpan *s) {
00112 printf("(%d-%d)", (s->start), (s->end));
00113 if (s->subspan)
00114 sraSpanListPrint(s->subspan);
00115 }
00116
00117 static sraSpanList *
00118 sraSpanListCreate(void) {
00119 sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
00120 item->front._next = &(item->back);
00121 item->front._prev = NULL;
00122 item->back._prev = &(item->front);
00123 item->back._next = NULL;
00124 return item;
00125 }
00126
00127 sraSpanList *
00128 sraSpanListDup(const sraSpanList *src) {
00129 sraSpanList *newlist;
00130 sraSpan *newspan, *curr;
00131
00132 if (!src) return NULL;
00133 newlist = sraSpanListCreate();
00134 curr = src->front._next;
00135 while (curr != &(src->back)) {
00136 newspan = sraSpanDup(curr);
00137 sraSpanInsertBefore(newspan, &(newlist->back));
00138 curr = curr->_next;
00139 }
00140
00141 return newlist;
00142 }
00143
00144 void
00145 sraSpanListDestroy(sraSpanList *list) {
00146 sraSpan *curr, *next;
00147 while (list->front._next != &(list->back)) {
00148 curr = list->front._next;
00149 next = curr->_next;
00150 sraSpanRemove(curr);
00151 sraSpanDestroy(curr);
00152 curr = next;
00153 }
00154 free(list);
00155 }
00156
00157 static void
00158 sraSpanListMakeEmpty(sraSpanList *list) {
00159 sraSpan *curr, *next;
00160 while (list->front._next != &(list->back)) {
00161 curr = list->front._next;
00162 next = curr->_next;
00163 sraSpanRemove(curr);
00164 sraSpanDestroy(curr);
00165 curr = next;
00166 }
00167 list->front._next = &(list->back);
00168 list->front._prev = NULL;
00169 list->back._prev = &(list->front);
00170 list->back._next = NULL;
00171 }
00172
00173 static rfbBool
00174 sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
00175 sraSpan *sp1, *sp2;
00176
00177 if (!s1) {
00178 if (!s2) {
00179 return 1;
00180 } else {
00181 rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n");
00182 return FALSE;
00183 }
00184 }
00185
00186 sp1 = s1->front._next;
00187 sp2 = s2->front._next;
00188 while ((sp1 != &(s1->back)) &&
00189 (sp2 != &(s2->back))) {
00190 if ((sp1->start != sp2->start) ||
00191 (sp1->end != sp2->end) ||
00192 (!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
00193 return 0;
00194 }
00195 sp1 = sp1->_next;
00196 sp2 = sp2->_next;
00197 }
00198
00199 if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
00200 return 1;
00201 } else {
00202 return 0;
00203 }
00204 }
00205
00206 static rfbBool
00207 sraSpanListEmpty(const sraSpanList *list) {
00208 return (list->front._next == &(list->back));
00209 }
00210
00211 static unsigned long
00212 sraSpanListCount(const sraSpanList *list) {
00213 sraSpan *curr = list->front._next;
00214 unsigned long count = 0;
00215 while (curr != &(list->back)) {
00216 if (curr->subspan) {
00217 count += sraSpanListCount(curr->subspan);
00218 } else {
00219 count += 1;
00220 }
00221 curr = curr->_next;
00222 }
00223 return count;
00224 }
00225
00226 static void
00227 sraSpanMergePrevious(sraSpan *dest) {
00228 sraSpan *prev = dest->_prev;
00229
00230 while ((prev->_prev) &&
00231 (prev->end == dest->start) &&
00232 (sraSpanListEqual(prev->subspan, dest->subspan))) {
00233
00234
00235
00236
00237
00238
00239
00240 dest->start = prev->start;
00241 sraSpanRemove(prev);
00242 sraSpanDestroy(prev);
00243 prev = dest->_prev;
00244 }
00245 }
00246
00247 static void
00248 sraSpanMergeNext(sraSpan *dest) {
00249 sraSpan *next = dest->_next;
00250 while ((next->_next) &&
00251 (next->start == dest->end) &&
00252 (sraSpanListEqual(next->subspan, dest->subspan))) {
00253
00254
00255
00256
00257
00258
00259
00260 dest->end = next->end;
00261 sraSpanRemove(next);
00262 sraSpanDestroy(next);
00263 next = dest->_next;
00264 }
00265 }
00266
00267 static void
00268 sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
00269 sraSpan *d_curr, *s_curr;
00270 int s_start, s_end;
00271
00272 if (!dest) {
00273 if (!src) {
00274 return;
00275 } else {
00276 rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n");
00277 return;
00278 }
00279 }
00280
00281 d_curr = dest->front._next;
00282 s_curr = src->front._next;
00283 s_start = s_curr->start;
00284 s_end = s_curr->end;
00285 while (s_curr != &(src->back)) {
00286
00287
00288
00289 if ((d_curr == &(dest->back)) ||
00290 (d_curr->start >= s_end)) {
00291
00292 sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
00293 s_curr->subspan),
00294 d_curr);
00295 if (d_curr != &(dest->back))
00296 sraSpanMergePrevious(d_curr);
00297 s_curr = s_curr->_next;
00298 s_start = s_curr->start;
00299 s_end = s_curr->end;
00300 } else {
00301
00302
00303 if ((s_start < d_curr->end) &&
00304 (s_end > d_curr->start)) {
00305
00306
00307 if (s_start < d_curr->start) {
00308 sraSpanInsertBefore(sraSpanCreate(s_start,
00309 d_curr->start,
00310 s_curr->subspan),
00311 d_curr);
00312 sraSpanMergePrevious(d_curr);
00313 }
00314
00315
00316 if (s_end < d_curr->end) {
00317 sraSpanInsertAfter(sraSpanCreate(s_end,
00318 d_curr->end,
00319 d_curr->subspan),
00320 d_curr);
00321 d_curr->end = s_end;
00322 }
00323 if (s_start > d_curr->start) {
00324 sraSpanInsertBefore(sraSpanCreate(d_curr->start,
00325 s_start,
00326 d_curr->subspan),
00327 d_curr);
00328 d_curr->start = s_start;
00329 }
00330
00331
00332 sraSpanListOr(d_curr->subspan, s_curr->subspan);
00333
00334
00335 if (d_curr->_prev != &(dest->front))
00336 sraSpanMergePrevious(d_curr);
00337 if (d_curr->_next != &(dest->back))
00338 sraSpanMergeNext(d_curr);
00339
00340
00341 if (s_end > d_curr->end) {
00342 s_start = d_curr->end;
00343 d_curr = d_curr->_next;
00344 } else {
00345 s_curr = s_curr->_next;
00346 s_start = s_curr->start;
00347 s_end = s_curr->end;
00348 }
00349 } else {
00350
00351 d_curr = d_curr->_next;
00352 }
00353 }
00354 }
00355 }
00356
00357 static rfbBool
00358 sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
00359 sraSpan *d_curr, *s_curr, *d_next;
00360
00361 if (!dest) {
00362 if (!src) {
00363 return 1;
00364 } else {
00365 rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n");
00366 return FALSE;
00367 }
00368 }
00369
00370 d_curr = dest->front._next;
00371 s_curr = src->front._next;
00372 while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
00373
00374
00375 if (d_curr->start >= s_curr->end) {
00376 s_curr = s_curr->_next;
00377 continue;
00378 }
00379
00380
00381 if (d_curr->end <= s_curr->start) {
00382 sraSpan *next = d_curr->_next;
00383 sraSpanRemove(d_curr);
00384 sraSpanDestroy(d_curr);
00385 d_curr = next;
00386 continue;
00387 }
00388
00389
00390 if (s_curr->start > d_curr->start) {
00391
00392 d_curr->start = s_curr->start;
00393 }
00394 if (s_curr->end < d_curr->end) {
00395
00396 sraSpanInsertAfter(sraSpanCreate(s_curr->end,
00397 d_curr->end,
00398 d_curr->subspan),
00399 d_curr);
00400 d_curr->end = s_curr->end;
00401 }
00402
00403
00404 if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
00405
00406 sraSpan *next = d_curr->_next;
00407 sraSpanRemove(d_curr);
00408 sraSpanDestroy(d_curr);
00409 d_curr = next;
00410 } else {
00411
00412 if (d_curr->_prev != &(dest->front))
00413 sraSpanMergePrevious(d_curr);
00414
00415
00416 d_next = d_curr;
00417 if (s_curr->end >= d_curr->end) {
00418 d_next = d_curr->_next;
00419 }
00420 if (s_curr->end <= d_curr->end) {
00421 s_curr = s_curr->_next;
00422 }
00423 d_curr = d_next;
00424 }
00425 }
00426
00427 while (d_curr != &(dest->back)) {
00428 sraSpan *next = d_curr->_next;
00429 sraSpanRemove(d_curr);
00430 sraSpanDestroy(d_curr);
00431 d_curr=next;
00432 }
00433
00434 return !sraSpanListEmpty(dest);
00435 }
00436
00437 static rfbBool
00438 sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
00439 sraSpan *d_curr, *s_curr;
00440
00441 if (!dest) {
00442 if (!src) {
00443 return 1;
00444 } else {
00445 rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
00446 return FALSE;
00447 }
00448 }
00449
00450 d_curr = dest->front._next;
00451 s_curr = src->front._next;
00452 while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
00453
00454
00455 if (d_curr->start >= s_curr->end) {
00456 s_curr = s_curr->_next;
00457 continue;
00458 }
00459
00460
00461 if (d_curr->end <= s_curr->start) {
00462 d_curr = d_curr->_next;
00463 continue;
00464 }
00465
00466
00467 if (s_curr->start > d_curr->start) {
00468 sraSpanInsertBefore(sraSpanCreate(d_curr->start,
00469 s_curr->start,
00470 d_curr->subspan),
00471 d_curr);
00472 d_curr->start = s_curr->start;
00473 }
00474 if (s_curr->end < d_curr->end) {
00475 sraSpanInsertAfter(sraSpanCreate(s_curr->end,
00476 d_curr->end,
00477 d_curr->subspan),
00478 d_curr);
00479 d_curr->end = s_curr->end;
00480 }
00481
00482
00483 if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
00484
00485 sraSpan *next = d_curr->_next;
00486 sraSpanRemove(d_curr);
00487 sraSpanDestroy(d_curr);
00488 d_curr = next;
00489 } else {
00490
00491 if (d_curr->_prev != &(dest->front))
00492 sraSpanMergePrevious(d_curr);
00493 if (d_curr->_next != &(dest->back))
00494 sraSpanMergeNext(d_curr);
00495
00496
00497 if (s_curr->end > d_curr->end) {
00498 d_curr = d_curr->_next;
00499 } else {
00500 s_curr = s_curr->_next;
00501 }
00502 }
00503 }
00504
00505 return !sraSpanListEmpty(dest);
00506 }
00507
00508
00509
00510 sraRegion *
00511 sraRgnCreate(void) {
00512 return (sraRegion*)sraSpanListCreate();
00513 }
00514
00515 sraRegion *
00516 sraRgnCreateRect(int x1, int y1, int x2, int y2) {
00517 sraSpanList *vlist, *hlist;
00518 sraSpan *vspan, *hspan;
00519
00520
00521 hlist = sraSpanListCreate();
00522 hspan = sraSpanCreate(x1, x2, NULL);
00523 sraSpanInsertAfter(hspan, &(hlist->front));
00524
00525
00526 vlist = sraSpanListCreate();
00527 vspan = sraSpanCreate(y1, y2, hlist);
00528 sraSpanInsertAfter(vspan, &(vlist->front));
00529
00530 sraSpanListDestroy(hlist);
00531
00532 return (sraRegion*)vlist;
00533 }
00534
00535 sraRegion *
00536 sraRgnCreateRgn(const sraRegion *src) {
00537 return (sraRegion*)sraSpanListDup((sraSpanList*)src);
00538 }
00539
00540 void
00541 sraRgnDestroy(sraRegion *rgn) {
00542 sraSpanListDestroy((sraSpanList*)rgn);
00543 }
00544
00545 void
00546 sraRgnMakeEmpty(sraRegion *rgn) {
00547 sraSpanListMakeEmpty((sraSpanList*)rgn);
00548 }
00549
00550
00551
00552 rfbBool
00553 sraRgnAnd(sraRegion *dst, const sraRegion *src) {
00554 return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
00555 }
00556
00557 void
00558 sraRgnOr(sraRegion *dst, const sraRegion *src) {
00559 sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
00560 }
00561
00562 rfbBool
00563 sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
00564 return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
00565 }
00566
00567 void
00568 sraRgnOffset(sraRegion *dst, int dx, int dy) {
00569 sraSpan *vcurr, *hcurr;
00570
00571 vcurr = ((sraSpanList*)dst)->front._next;
00572 while (vcurr != &(((sraSpanList*)dst)->back)) {
00573 vcurr->start += dy;
00574 vcurr->end += dy;
00575
00576 hcurr = vcurr->subspan->front._next;
00577 while (hcurr != &(vcurr->subspan->back)) {
00578 hcurr->start += dx;
00579 hcurr->end += dx;
00580 hcurr = hcurr->_next;
00581 }
00582
00583 vcurr = vcurr->_next;
00584 }
00585 }
00586
00587 sraRegion *sraRgnBBox(const sraRegion *src) {
00588 int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
00589 sraSpan *vcurr, *hcurr;
00590
00591 if(!src)
00592 return sraRgnCreate();
00593
00594 vcurr = ((sraSpanList*)src)->front._next;
00595 while (vcurr != &(((sraSpanList*)src)->back)) {
00596 if(vcurr->start<ymin)
00597 ymin=vcurr->start;
00598 if(vcurr->end>ymax)
00599 ymax=vcurr->end;
00600
00601 hcurr = vcurr->subspan->front._next;
00602 while (hcurr != &(vcurr->subspan->back)) {
00603 if(hcurr->start<xmin)
00604 xmin=hcurr->start;
00605 if(hcurr->end>xmax)
00606 xmax=hcurr->end;
00607 hcurr = hcurr->_next;
00608 }
00609
00610 vcurr = vcurr->_next;
00611 }
00612
00613 if(xmax<xmin || ymax<ymin)
00614 return sraRgnCreate();
00615
00616 return sraRgnCreateRect(xmin,ymin,xmax,ymax);
00617 }
00618
00619 rfbBool
00620 sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
00621 sraSpan *vcurr, *hcurr;
00622 sraSpan *vend, *hend;
00623 rfbBool right2left = (flags & 2) == 2;
00624 rfbBool bottom2top = (flags & 1) == 1;
00625
00626
00627 if (bottom2top) {
00628 vcurr = ((sraSpanList*)rgn)->back._prev;
00629 vend = &(((sraSpanList*)rgn)->front);
00630 } else {
00631 vcurr = ((sraSpanList*)rgn)->front._next;
00632 vend = &(((sraSpanList*)rgn)->back);
00633 }
00634
00635 if (vcurr != vend) {
00636 rect->y1 = vcurr->start;
00637 rect->y2 = vcurr->end;
00638
00639
00640 if (right2left) {
00641 hcurr = vcurr->subspan->back._prev;
00642 hend = &(vcurr->subspan->front);
00643 } else {
00644 hcurr = vcurr->subspan->front._next;
00645 hend = &(vcurr->subspan->back);
00646 }
00647
00648 if (hcurr != hend) {
00649 rect->x1 = hcurr->start;
00650 rect->x2 = hcurr->end;
00651
00652 sraSpanRemove(hcurr);
00653 sraSpanDestroy(hcurr);
00654
00655 if (sraSpanListEmpty(vcurr->subspan)) {
00656 sraSpanRemove(vcurr);
00657 sraSpanDestroy(vcurr);
00658 }
00659
00660 #if 0
00661 printf("poprect:(%dx%d)-(%dx%d)\n",
00662 rect->x1, rect->y1, rect->x2, rect->y2);
00663 #endif
00664 return 1;
00665 }
00666 }
00667
00668 return 0;
00669 }
00670
00671 unsigned long
00672 sraRgnCountRects(const sraRegion *rgn) {
00673 unsigned long count = sraSpanListCount((sraSpanList*)rgn);
00674 return count;
00675 }
00676
00677 rfbBool
00678 sraRgnEmpty(const sraRegion *rgn) {
00679 return sraSpanListEmpty((sraSpanList*)rgn);
00680 }
00681
00682
00683 sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
00684 {
00685
00686 #define DEFSIZE 4
00687 #define DEFSTEP 8
00688 sraRectangleIterator *i =
00689 (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
00690 if(!i)
00691 return NULL;
00692
00693
00694
00695
00696
00697 i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
00698 if(!i->sPtrs) {
00699 free(i);
00700 return NULL;
00701 }
00702 i->ptrSize = DEFSIZE;
00703 i->sPtrs[0] = &(s->front);
00704 i->sPtrs[1] = &(s->back);
00705 i->ptrPos = 0;
00706 i->reverseX = 0;
00707 i->reverseY = 0;
00708 return i;
00709 }
00710
00711 sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY)
00712 {
00713 sraRectangleIterator *i = sraRgnGetIterator(s);
00714 if(reverseY) {
00715 i->sPtrs[1] = &(s->front);
00716 i->sPtrs[0] = &(s->back);
00717 }
00718 i->reverseX = reverseX;
00719 i->reverseY = reverseY;
00720 return(i);
00721 }
00722
00723 static rfbBool sraReverse(sraRectangleIterator *i)
00724 {
00725 return( ((i->ptrPos&2) && i->reverseX) ||
00726 (!(i->ptrPos&2) && i->reverseY));
00727 }
00728
00729 static sraSpan* sraNextSpan(sraRectangleIterator *i)
00730 {
00731 if(sraReverse(i))
00732 return(i->sPtrs[i->ptrPos]->_prev);
00733 else
00734 return(i->sPtrs[i->ptrPos]->_next);
00735 }
00736
00737 rfbBool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
00738 {
00739
00740 while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
00741 i->ptrPos -= 2;
00742 if(i->ptrPos < 0)
00743 return(0);
00744 }
00745
00746 i->sPtrs[i->ptrPos] = sraNextSpan(i);
00747
00748
00749 while(i->sPtrs[i->ptrPos]->subspan) {
00750 if(i->ptrPos+2 > i->ptrSize) {
00751 i->ptrSize += DEFSTEP;
00752 i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
00753 }
00754 i->ptrPos =+ 2;
00755 if(sraReverse(i)) {
00756 i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
00757 i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
00758 } else {
00759 i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
00760 i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
00761 }
00762 }
00763
00764 if((i->ptrPos%4)!=2) {
00765 rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
00766 return FALSE;
00767 }
00768
00769 r->y1 = i->sPtrs[i->ptrPos-2]->start;
00770 r->y2 = i->sPtrs[i->ptrPos-2]->end;
00771 r->x1 = i->sPtrs[i->ptrPos]->start;
00772 r->x2 = i->sPtrs[i->ptrPos]->end;
00773
00774 return(-1);
00775 }
00776
00777 void sraRgnReleaseIterator(sraRectangleIterator* i)
00778 {
00779 free(i->sPtrs);
00780 free(i);
00781 }
00782
00783 void
00784 sraRgnPrint(const sraRegion *rgn) {
00785 sraSpanListPrint((sraSpanList*)rgn);
00786 }
00787
00788 rfbBool
00789 sraClipRect(int *x, int *y, int *w, int *h,
00790 int cx, int cy, int cw, int ch) {
00791 if (*x < cx) {
00792 *w -= (cx-*x);
00793 *x = cx;
00794 }
00795 if (*y < cy) {
00796 *h -= (cy-*y);
00797 *y = cy;
00798 }
00799 if (*x+*w > cx+cw) {
00800 *w = (cx+cw)-*x;
00801 }
00802 if (*y+*h > cy+ch) {
00803 *h = (cy+ch)-*y;
00804 }
00805 return (*w>0) && (*h>0);
00806 }
00807
00808 rfbBool
00809 sraClipRect2(int *x, int *y, int *x2, int *y2,
00810 int cx, int cy, int cx2, int cy2) {
00811 if (*x < cx)
00812 *x = cx;
00813 if (*y < cy)
00814 *y = cy;
00815 if (*x >= cx2)
00816 *x = cx2-1;
00817 if (*y >= cy2)
00818 *y = cy2-1;
00819 if (*x2 <= cx)
00820 *x2 = cx+1;
00821 if (*y2 <= cy)
00822 *y2 = cy+1;
00823 if (*x2 > cx2)
00824 *x2 = cx2;
00825 if (*y2 > cy2)
00826 *y2 = cy2;
00827 return (*x2>*x) && (*y2>*y);
00828 }
00829
00830
00831
00832 #ifdef SRA_TEST
00833
00834 int main(int argc, char** argv)
00835 {
00836 sraRegionPtr region, region1, region2;
00837 sraRectangleIterator* i;
00838 sraRect rect;
00839 rfbBool b;
00840
00841 region = sraRgnCreateRect(10, 10, 600, 300);
00842 region1 = sraRgnCreateRect(40, 50, 350, 200);
00843 region2 = sraRgnCreateRect(0, 0, 20, 40);
00844
00845 sraRgnPrint(region);
00846 printf("\n[(10-300)[(10-600)]]\n\n");
00847
00848 b = sraRgnSubtract(region, region1);
00849 printf("%s ",b?"true":"false");
00850 sraRgnPrint(region);
00851 printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
00852
00853 sraRgnOr(region, region2);
00854 printf("%ld\n6\n\n", sraRgnCountRects(region));
00855
00856 i = sraRgnGetIterator(region);
00857 while(sraRgnIteratorNext(i, &rect))
00858 printf("%dx%d+%d+%d ",
00859 rect.x2-rect.x1,rect.y2-rect.y1,
00860 rect.x1,rect.y1);
00861 sraRgnReleaseIterator(i);
00862 printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");
00863
00864 i = sraRgnGetReverseIterator(region,1,0);
00865 while(sraRgnIteratorNext(i, &rect))
00866 printf("%dx%d+%d+%d ",
00867 rect.x2-rect.x1,rect.y2-rect.y1,
00868 rect.x1,rect.y1);
00869 sraRgnReleaseIterator(i);
00870 printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");
00871
00872 i = sraRgnGetReverseIterator(region,1,1);
00873 while(sraRgnIteratorNext(i, &rect))
00874 printf("%dx%d+%d+%d ",
00875 rect.x2-rect.x1,rect.y2-rect.y1,
00876 rect.x1,rect.y1);
00877 sraRgnReleaseIterator(i);
00878 printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");
00879
00880 sraRgnDestroy(region);
00881 sraRgnDestroy(region1);
00882 sraRgnDestroy(region2);
00883
00884 return(0);
00885 }
00886 #endif