📄 region.c
字号:
return 0; /* lint */}/*- *----------------------------------------------------------------------- * miUnionO -- * Handle an overlapping band for the union operation. Picks the * left-most rectangle each time and merges it into the region. * * Results: * None. * * Side Effects: * Rectangles are overwritten in pReg->rects and pReg->numRects will * be changed. * *----------------------------------------------------------------------- *//* static void*/static intmiUnionO (pReg, r1, r1End, r2, r2End, y1, y2) register XRegion pReg; register BoxPtr r1; BoxPtr r1End; register BoxPtr r2; BoxPtr r2End; register short y1; register short y2;{ register BoxPtr pNextRect; pNextRect = &pReg->rects[pReg->numRects];#define MERGERECT(r) \ if ((pReg->numRects != 0) && \ (pNextRect[-1].y1 == y1) && \ (pNextRect[-1].y2 == y2) && \ (pNextRect[-1].x2 >= r->x1)) \ { \ if (pNextRect[-1].x2 < r->x2) \ { \ pNextRect[-1].x2 = r->x2; \ assert(pNextRect[-1].x1<pNextRect[-1].x2); \ } \ } \ else \ { \ MEMCHECK(pReg, pNextRect, pReg->rects); \ pNextRect->y1 = y1; \ pNextRect->y2 = y2; \ pNextRect->x1 = r->x1; \ pNextRect->x2 = r->x2; \ pReg->numRects += 1; \ pNextRect += 1; \ } \ assert(pReg->numRects<=pReg->size);\ r++; assert (y1<y2); while ((r1 != r1End) && (r2 != r2End)) { if (r1->x1 < r2->x1) { MERGERECT(r1); } else { MERGERECT(r2); } } if (r1 != r1End) { do { MERGERECT(r1); } while (r1 != r1End); } else while (r2 != r2End) { MERGERECT(r2); } return 0; /* lint */}intXUnionRegion(reg1, reg2, newReg) XRegion reg1; XRegion reg2; /* source XRegions */ XRegion newReg; /* destination Region */{ /* checks all the simple cases */ /* * Region 1 and 2 are the same or region 1 is empty */ if ( (reg1 == reg2) || (!(reg1->numRects)) ) { if (newReg != reg2) miRegionCopy(newReg, reg2); return 1; } /* * if nothing to union (region 2 empty) */ if (!(reg2->numRects)) { if (newReg != reg1) miRegionCopy(newReg, reg1); return 1; } /* * Region 1 completely subsumes region 2 */ if ((reg1->numRects == 1) && (reg1->extents.x1 <= reg2->extents.x1) && (reg1->extents.y1 <= reg2->extents.y1) && (reg1->extents.x2 >= reg2->extents.x2) && (reg1->extents.y2 >= reg2->extents.y2)) { if (newReg != reg1) miRegionCopy(newReg, reg1); return 1; } /* * Region 2 completely subsumes region 1 */ if ((reg2->numRects == 1) && (reg2->extents.x1 <= reg1->extents.x1) && (reg2->extents.y1 <= reg1->extents.y1) && (reg2->extents.x2 >= reg1->extents.x2) && (reg2->extents.y2 >= reg1->extents.y2)) { if (newReg != reg2) miRegionCopy(newReg, reg2); return 1; } miRegionOp (newReg, reg1, reg2, (voidProcp) miUnionO, (voidProcp) miUnionNonO, (voidProcp) miUnionNonO); newReg->extents.x1 = min(reg1->extents.x1, reg2->extents.x1); newReg->extents.y1 = min(reg1->extents.y1, reg2->extents.y1); newReg->extents.x2 = max(reg1->extents.x2, reg2->extents.x2); newReg->extents.y2 = max(reg1->extents.y2, reg2->extents.y2); return 1;}/*====================================================================== * Region Subtraction *====================================================================*//*- *----------------------------------------------------------------------- * miSubtractNonO -- * Deal with non-overlapping band for subtraction. Any parts from * region 2 we discard. Anything from region 1 we add to the region. * * Results: * None. * * Side Effects: * pReg may be affected. * *----------------------------------------------------------------------- *//* static void*/static intmiSubtractNonO1 (pReg, r, rEnd, y1, y2) register XRegion pReg; register BoxPtr r; BoxPtr rEnd; register short y1; register short y2;{ register BoxPtr pNextRect; pNextRect = &pReg->rects[pReg->numRects]; assert(y1<y2); while (r != rEnd) { assert(r->x1<r->x2); MEMCHECK(pReg, pNextRect, pReg->rects); pNextRect->x1 = r->x1; pNextRect->y1 = y1; pNextRect->x2 = r->x2; pNextRect->y2 = y2; pReg->numRects += 1; pNextRect++; assert(pReg->numRects <= pReg->size); r++; } return 0; /* lint */}/*- *----------------------------------------------------------------------- * miSubtractO -- * Overlapping band subtraction. x1 is the left-most point not yet * checked. * * Results: * None. * * Side Effects: * pReg may have rectangles added to it. * *----------------------------------------------------------------------- *//* static void*/static intmiSubtractO (pReg, r1, r1End, r2, r2End, y1, y2) register XRegion pReg; register BoxPtr r1; BoxPtr r1End; register BoxPtr r2; BoxPtr r2End; register short y1; register short y2;{ register BoxPtr pNextRect; register int x1; x1 = r1->x1; assert(y1<y2); pNextRect = &pReg->rects[pReg->numRects]; while ((r1 != r1End) && (r2 != r2End)) { if (r2->x2 <= x1) { /* * Subtrahend missed the boat: go to next subtrahend. */ r2++; } else if (r2->x1 <= x1) { /* * Subtrahend preceeds minuend: nuke left edge of minuend. */ x1 = r2->x2; if (x1 >= r1->x2) { /* * Minuend completely covered: advance to next minuend and * reset left fence to edge of new minuend. */ r1++; if (r1 != r1End) x1 = r1->x1; } else { /* * Subtrahend now used up since it doesn't extend beyond * minuend */ r2++; } } else if (r2->x1 < r1->x2) { /* * Left part of subtrahend covers part of minuend: add uncovered * part of minuend to region and skip to next subtrahend. */ assert(x1<r2->x1); MEMCHECK(pReg, pNextRect, pReg->rects); pNextRect->x1 = x1; pNextRect->y1 = y1; pNextRect->x2 = r2->x1; pNextRect->y2 = y2; pReg->numRects += 1; pNextRect++; assert(pReg->numRects<=pReg->size); x1 = r2->x2; if (x1 >= r1->x2) { /* * Minuend used up: advance to new... */ r1++; if (r1 != r1End) x1 = r1->x1; } else { /* * Subtrahend used up */ r2++; } } else { /* * Minuend used up: add any remaining piece before advancing. */ if (r1->x2 > x1) { MEMCHECK(pReg, pNextRect, pReg->rects); pNextRect->x1 = x1; pNextRect->y1 = y1; pNextRect->x2 = r1->x2; pNextRect->y2 = y2; pReg->numRects += 1; pNextRect++; assert(pReg->numRects<=pReg->size); } r1++; x1 = r1->x1; } } /* * Add remaining minuend rectangles to region. */ while (r1 != r1End) { assert(x1<r1->x2); MEMCHECK(pReg, pNextRect, pReg->rects); pNextRect->x1 = x1; pNextRect->y1 = y1; pNextRect->x2 = r1->x2; pNextRect->y2 = y2; pReg->numRects += 1; pNextRect++; assert(pReg->numRects<=pReg->size); r1++; if (r1 != r1End) { x1 = r1->x1; } } return 0; /* lint */} /*- *----------------------------------------------------------------------- * miSubtract -- * Subtract regS from regM and leave the result in regD. * S stands for subtrahend, M for minuend and D for difference. * * Results: * TRUE. * * Side Effects: * regD is overwritten. * *----------------------------------------------------------------------- */intXSubtractRegion(regM, regS, regD) XRegion regM; XRegion regS; register XRegion regD;{ /* check for trivial reject */ if ( (!(regM->numRects)) || (!(regS->numRects)) || (!EXTENTCHECK(®M->extents, ®S->extents)) ) { miRegionCopy(regD, regM); return 1; } miRegionOp (regD, regM, regS, (voidProcp) miSubtractO, (voidProcp) miSubtractNonO1, (voidProcp) NULL); /* * Can't alter newReg's extents before we call miRegionOp because * it might be one of the source regions and miRegionOp depends * on the extents of those regions being the unaltered. Besides, this * way there's no checking against rectangles that will be nuked * due to coalescing, so we have to examine fewer rectangles. */ miSetExtents (regD); return 1;}intXXorRegion( sra, srb, dr ) XRegion sra, srb, dr;{ XRegion tra, trb; if ((! (tra = XCreateRegion())) || (! (trb = XCreateRegion()))) return 0; (void) XSubtractRegion(sra,srb,tra); (void) XSubtractRegion(srb,sra,trb); (void) XUnionRegion(tra,trb,dr); XDestroyRegion(tra); XDestroyRegion(trb); return 0;}/* * Check to see if the region is empty. Assumes a region is passed * as a parameter */int XEmptyRegion( r ) XRegion r;{ if( r->numRects == 0 ) return TRUE; else return FALSE;}/* * Check to see if two regions are equal */int XEqualRegion( r1, r2 ) XRegion r1, r2;{ int i; if( r1->numRects != r2->numRects ) return FALSE; else if( r1->numRects == 0 ) return TRUE; else if ( r1->extents.x1 != r2->extents.x1 ) return FALSE; else if ( r1->extents.x2 != r2->extents.x2 ) return FALSE; else if ( r1->extents.y1 != r2->extents.y1 ) return FALSE; else if ( r1->extents.y2 != r2->extents.y2 ) return FALSE; else for( i=0; i < r1->numRects; i++ ) { if ( r1->rects[i].x1 != r2->rects[i].x1 ) return FALSE; else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return FALSE; else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return FALSE; else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return FALSE; } return TRUE;}int XPointInRegion( pRegion, x, y ) XRegion pRegion; int x, y;{ int i; if (pRegion->numRects == 0) return FALSE; if (!INBOX(pRegion->extents, x, y)) return FALSE; for (i=0; i<pRegion->numRects; i++) { if (INBOX (pRegion->rects[i], x, y)) return TRUE; } return FALSE;}int XRectInRegion(region, rx, ry, rwidth, rheight) register XRegion region; int rx, ry; unsigned int rwidth, rheight;{ register BoxPtr pbox; register BoxPtr pboxEnd; Box rect; register BoxPtr prect = ▭ int partIn, partOut; prect->x1 = rx; prect->y1 = ry; prect->x2 = rwidth + rx; prect->y2 = rheight + ry; /* this is (just) a useful optimization */ if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect)) return(RectangleOut); partOut = FALSE; partIn = FALSE; /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ for (pbox = region->rects, pboxEnd = pbox + region->numRects; pbox < pboxEnd; pbox++) { if (pbox->y2 <= ry) continue; /* getting up to speed or skipping remainder of band */ if (pbox->y1 > ry) { partOut = TRUE; /* missed part of rectangle above */ if (partIn || (pbox->y1 >= prect->y2)) break; ry = pbox->y1; /* x guaranteed to be == prect->x1 */ } if (pbox->x2 <= rx) continue; /* not far enough over yet */ if (pbox->x1 > rx) { partOut = TRUE; /* missed part of rectangle to left */ if (partIn) break; } if (pbox->x1 < prect->x2) { partIn = TRUE; /* definitely overlap */ if (partOut) break; } if (pbox->x2 >= prect->x2) { ry = pbox->y2; /* finished with this band */ if (ry >= prect->y2) break; rx = prect->x1; /* reset x out to left again */ } else { /* * Because boxes in a band are maximal width, if the first box * to overlap the rectangle doesn't completely cover it in that * band, the rectangle must be partially out, since some of it * will be uncovered in that band. partIn will have been set true * by now... */ break; } } return(partIn ? ((ry < prect->y2) ? RectanglePart : RectangleIn) : RectangleOut);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -