rfbBool sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) { sraSpan *vcurr, *hcurr; sraSpan *vend, *hend; rfbBool right2left = flags & 2; rfbBool bottom2top = flags & 1; /* - Pick correct order */ if (bottom2top) { vcurr = ((sraSpanList*)rgn)->back._prev; vend = &(((sraSpanList*)rgn)->front); } else { vcurr = ((sraSpanList*)rgn)->front._next; vend = &(((sraSpanList*)rgn)->back); } if (vcurr != vend) { rect->y1 = vcurr->start; rect->y2 = vcurr->end; /* - Pick correct order */ if (right2left) { hcurr = vcurr->subspan->back._prev; hend = &(vcurr->subspan->front); } else { hcurr = vcurr->subspan->front._next; hend = &(vcurr->subspan->back); } if (hcurr != hend) { rect->x1 = hcurr->start; rect->x2 = hcurr->end; sraSpanRemove(hcurr); sraSpanDestroy(hcurr); if (sraSpanListEmpty(vcurr->subspan)) { sraSpanRemove(vcurr); sraSpanDestroy(vcurr); } #if 0 printf("poprect:(%dx%d)-(%dx%d)\n", rect->x1, rect->y1, rect->x2, rect->y2); #endif return 1; } } return 0; }
static void sraSpanMergePrevious(sraSpan *dest) { sraSpan *prev; if (!dest) return; prev = dest->_prev; while ((prev->_prev) && (prev->end == dest->start) && (sraSpanListEqual(prev->subspan, dest->subspan))) { /* printf("merge_prev:"); sraSpanPrint(prev); printf(" & "); sraSpanPrint(dest); printf("\n"); */ dest->start = prev->start; sraSpanRemove(prev); sraSpanDestroy(prev); prev = dest->_prev; } }
static void sraSpanListDestroy(sraSpanList *list) { sraSpan *curr, *next; while (list->front._next != &(list->back)) { curr = list->front._next; next = curr->_next; sraSpanRemove(curr); sraSpanDestroy(curr); curr = next; } free(list); }
static void sraSpanListMakeEmpty(sraSpanList *list) { sraSpan *curr, *next; while (list->front._next != &(list->back)) { curr = list->front._next; next = curr->_next; sraSpanRemove(curr); sraSpanDestroy(curr); curr = next; } list->front._next = &(list->back); list->front._prev = NULL; list->back._prev = &(list->front); list->back._next = NULL; }
void sraSpanListDestroy(sraSpanList *list) { sraSpan *curr, *next; if (!list) return; while (list->front._next != &(list->back)) { curr = list->front._next; next = curr->_next; sraSpanRemove(curr); sraSpanDestroy(curr); curr = next; } MemFree(list); }
static void sraSpanMergeNext(sraSpan *dest) { sraSpan *next = dest->_next; while ((next->start == dest->end) && (next->_next) && (sraSpanListEqual(next->subspan, dest->subspan))) { /* printf("merge_next:"); sraSpanPrint(dest); printf(" & "); sraSpanPrint(next); printf("\n"); */ dest->end = next->end; sraSpanRemove(next); sraSpanDestroy(next); next = dest->_next; } }
static rfbBool sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) { sraSpan *d_curr, *s_curr; if (!dest) { if (!src) { return 1; } else { printf("sraSpanListSubtract:incompatible spans (only one NULL!)\n"); return FALSE; } } d_curr = dest->front._next; s_curr = src->front._next; while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { /* - If we haven't reached a destination span yet then move on */ if (d_curr->start >= s_curr->end) { s_curr = s_curr->_next; continue; } /* - If we are beyond the current destination span then skip it */ if (d_curr->end <= s_curr->start) { d_curr = d_curr->_next; continue; } /* - If we partially overlap the current span then split it up */ if (s_curr->start > d_curr->start) { sraSpanInsertBefore(sraSpanCreate(d_curr->start, s_curr->start, d_curr->subspan), d_curr); d_curr->start = s_curr->start; } if (s_curr->end < d_curr->end) { sraSpanInsertAfter(sraSpanCreate(s_curr->end, d_curr->end, d_curr->subspan), d_curr); d_curr->end = s_curr->end; } /* - Now recursively process the affected span */ if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) { /* - The destination subspan is now empty, so we should remove it */ sraSpan *next = d_curr->_next; sraSpanRemove(d_curr); sraSpanDestroy(d_curr); d_curr = next; } else { /* Merge this span with previous or next? */ if (d_curr->_prev != &(dest->front)) sraSpanMergePrevious(d_curr); if (d_curr->_next != &(dest->back)) sraSpanMergeNext(d_curr); /* - Move on to the next span */ if (s_curr->end > d_curr->end) { d_curr = d_curr->_next; } else { s_curr = s_curr->_next; } } } return !sraSpanListEmpty(dest); }
static rfbBool sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) { sraSpan *d_curr, *s_curr, *d_next; if (!dest) { if (!src) { return 1; } else { ///rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n"); return FALSE; } } else if (!src) return FALSE; d_curr = dest->front._next; s_curr = src->front._next; while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { /* - If we haven't reached a destination span yet then move on */ if (d_curr->start >= s_curr->end) { s_curr = s_curr->_next; continue; } /* - If we are beyond the current destination span then remove it */ if (d_curr->end <= s_curr->start) { sraSpan *next = d_curr->_next; sraSpanRemove(d_curr); sraSpanDestroy(d_curr); d_curr = next; continue; } /* - If we partially overlap a span then split it up or remove bits */ if (s_curr->start > d_curr->start) { /* - The top bit of the span does not match */ d_curr->start = s_curr->start; } if (s_curr->end < d_curr->end) { /* - The end of the span does not match */ sraSpanInsertAfter(sraSpanCreate(s_curr->end, d_curr->end, d_curr->subspan), d_curr); d_curr->end = s_curr->end; } /* - Now recursively process the affected span */ if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) { /* - The destination subspan is now empty, so we should remove it */ sraSpan *next = d_curr->_next; sraSpanRemove(d_curr); sraSpanDestroy(d_curr); d_curr = next; } else { /* Merge this span with previous or next? */ if (d_curr->_prev != &(dest->front)) sraSpanMergePrevious(d_curr); /* - Move on to the next span */ d_next = d_curr; if (s_curr->end >= d_curr->end) { d_next = d_curr->_next; } if (s_curr->end <= d_curr->end) { s_curr = s_curr->_next; } d_curr = d_next; } } while (d_curr != &(dest->back)) { sraSpan *next = d_curr->_next; sraSpanRemove(d_curr); sraSpanDestroy(d_curr); d_curr=next; } return !sraSpanListEmpty(dest); }