]>
git.saurik.com Git - wxWidgets.git/blob - src/generic/regiong.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/region.cpp 
   3 // Purpose:     generic wxRegion class 
   4 // Author:      David Elliott 
   8 // Copyright:   (c) 2004 David Elliott 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/generic/region.h" 
  15 // ======================================================================== 
  16 // Classes to interface with X.org code 
  17 // ======================================================================== 
  21     wxCoord x1
, x2
, y1
, y2
; 
  22 } Box
, BOX
, BoxRec
, *BoxPtr
; 
  24 typedef struct REGION 
*Region
; 
  29     // Default constructor initializes nothing 
  31     REGION(const wxRect
& rect
) 
  37         extents
.x2 
= rect
.x 
+ rect
.width
; 
  38         extents
.y2 
= rect
.y 
+ rect
.height
; 
  41     BoxPtr 
GetBox(int i
) { if(i
<numRects
) return rects
+i
; else return NULL
; } 
  47     static bool XOffsetRegion( 
  48         register Region pRegion
, 
  51     static bool XIntersectRegion( 
  53         Region reg2
,          /* source regions     */ 
  54         register Region newReg
);               /* destination Region */ 
  55     static bool XUnionRegion( 
  57         Region reg2
,             /* source regions     */ 
  58         Region newReg
);                  /* destination Region */ 
  59     static bool XSubtractRegion( 
  62         register Region regD
); 
  63     static bool XXorRegion(Region sra
, Region srb
, Region dr
); 
  64     static bool XEmptyRegion( 
  66     static bool XEqualRegion(Region r1
, Region r2
); 
  67     static bool XPointInRegion( 
  70     static wxRegionContain 
XRectInRegion( 
  71         register Region region
, 
  73         unsigned int rwidth
, unsigned int rheight
); 
  76     static Region 
XCreateRegion(void); 
  77     static void miSetExtents ( 
  79     static bool XDestroyRegion(Region r
); 
  80     static int miIntersectO ( 
  88     static void miRegionCopy( 
  89         register Region dstrgn
, 
  91     static int miCoalesce( 
  92         register Region pReg
, /* Region to coalesce */ 
  93         int prevStart
, /* Index of start of previous band */ 
  94         int curStart
); /* Index of start of current band */ 
  95     static void miRegionOp( 
  96         register Region newReg
, /* Place to store result */ 
  97         Region reg1
, /* First region in operation */ 
  98         Region reg2
, /* 2d region in operation */ 
 100             register Region     pReg
, 
 106             wxCoord             y2
), /* Function to call for over- 
 108         int (*nonOverlap1Func
)( 
 109             register Region     pReg
, 
 113             register wxCoord    y2
), /* Function to call for non- 
 114                                       * overlapping bands in region 
 116         int (*nonOverlap2Func
)( 
 117             register Region     pReg
, 
 121             register wxCoord    y2
)); /* Function to call for non- 
 122                                        * overlapping bands in region 
 124     static int miUnionNonO ( 
 125         register Region pReg
, 
 129         register wxCoord y2
); 
 130     static int miUnionO ( 
 131         register Region pReg
, 
 137         register wxCoord y2
); 
 138     static int miSubtractNonO1 ( 
 139         register Region pReg
, 
 143         register wxCoord y2
); 
 144     static int miSubtractO ( 
 145         register Region pReg
, 
 151         register wxCoord y2
); 
 159 // ======================================================================== 
 161 // ======================================================================== 
 162 class wxRegionRefData 
: public wxObjectRefData
, public REGION
 
 169         rects 
= ( BOX 
* )malloc( (unsigned) sizeof( BOX 
)); 
 175     wxRegionRefData(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
 178     {   rects 
= (BOX
*)malloc(sizeof(BOX
)); 
 181         extents
.x1 
= topLeft
.x
; 
 182         extents
.y1 
= topLeft
.y
; 
 183         extents
.x2 
= bottomRight
.x
; 
 184         extents
.y2 
= bottomRight
.y
; 
 187     wxRegionRefData(const wxRect
& rect
) 
 190     {   rects 
= (BOX
*)malloc(sizeof(BOX
)); 
 193     wxRegionRefData(const wxRegionRefData
& refData
) 
 198         numRects 
= refData
.numRects
; 
 199         rects 
= (Box
*)malloc(numRects
*sizeof(Box
)); 
 200         extents 
= refData
.extents
; 
 208     wxRegionRefData(const REGION
&); 
 211 // ======================================================================== 
 213 // ======================================================================== 
 214 //IMPLEMENT_DYNAMIC_CLASS(wxRegionGeneric, wxGDIObject); 
 216 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
 217 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData)) 
 219 // ---------------------------------------------------------------------------- 
 220 // wxRegionGeneric construction 
 221 // ---------------------------------------------------------------------------- 
 223 wxRegionGeneric::wxRegionGeneric() 
 227 wxRegionGeneric::~wxRegionGeneric() 
 231 wxRegionGeneric::wxRegionGeneric(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 233     m_refData 
= new wxRegionRefData(wxRect(x
,y
,w
,h
)); 
 236 wxRegionGeneric::wxRegionGeneric(const wxRect
& rect
) 
 238     m_refData 
= new wxRegionRefData(rect
); 
 241 wxRegionGeneric::wxRegionGeneric(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
 243     m_refData 
= new wxRegionRefData(topLeft
, bottomRight
); 
 246 void wxRegionGeneric::Clear() 
 251 wxObjectRefData 
*wxRegionGeneric::CreateRefData() const 
 253     return new wxRegionRefData
; 
 256 wxObjectRefData 
*wxRegionGeneric::CloneRefData(const wxObjectRefData 
*data
) const 
 258     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 261 bool wxRegionGeneric::operator== (const wxRegionGeneric
& region
) 
 263     wxASSERT(m_refData 
&& region
.m_refData
); 
 264     return REGION::XEqualRegion(M_REGIONDATA
,M_REGIONDATA_OF(region
)); 
 267 wxRect 
wxRegionGeneric::GetBox() const 
 271     REGION::XClipBox(M_REGIONDATA
,&rect
); 
 275 void wxRegionGeneric::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord 
&h
) const 
 279     REGION::XClipBox(M_REGIONDATA
,&rect
); 
 286 // ---------------------------------------------------------------------------- 
 287 // wxRegionGeneric operations 
 288 // ---------------------------------------------------------------------------- 
 290 bool wxRegionGeneric::Union(const wxRect
& rect
) 
 291 /* XUnionRectWithRegion */ 
 293     if (!rect
.width 
|| !rect
.height
) 
 298     return REGION::XUnionRegion(®ion
,M_REGIONDATA
,M_REGIONDATA
); 
 301 bool wxRegionGeneric::Union(const wxRegionGeneric
& region
) 
 304     return REGION::XUnionRegion(M_REGIONDATA_OF(region
),M_REGIONDATA
,M_REGIONDATA
); 
 307 bool wxRegionGeneric::Intersect(const wxRect
& rect
) 
 309     if (!rect
.width 
|| !rect
.height
) 
 314     return REGION::XIntersectRegion(®ion
,M_REGIONDATA
,M_REGIONDATA
); 
 317 bool wxRegionGeneric::Intersect(const wxRegionGeneric
& region
) 
 320     return REGION::XIntersectRegion(M_REGIONDATA_OF(region
),M_REGIONDATA
,M_REGIONDATA
); 
 323 bool wxRegionGeneric::Subtract(const wxRect
& rect
) 
 325     if (!rect
.width 
|| !rect
.height
) 
 330     return REGION::XSubtractRegion(®ion
,M_REGIONDATA
,M_REGIONDATA
); 
 333 bool wxRegionGeneric::Subtract(const wxRegionGeneric
& region
) 
 335     return REGION::XSubtractRegion(M_REGIONDATA_OF(region
),M_REGIONDATA
,M_REGIONDATA
); 
 338 bool wxRegionGeneric::Xor(const wxRect
& rect
) 
 340     if (!rect
.width 
|| !rect
.height
) 
 345     return REGION::XXorRegion(®ion
,M_REGIONDATA
,M_REGIONDATA
); 
 348 bool wxRegionGeneric::Xor(const wxRegionGeneric
& region
) 
 351     return REGION::XXorRegion(M_REGIONDATA_OF(region
),M_REGIONDATA
,M_REGIONDATA
); 
 354 bool wxRegionGeneric::Offset(wxCoord x
, wxCoord y
) 
 357     return REGION::XOffsetRegion(M_REGIONDATA
, x
, y
); 
 360 // ---------------------------------------------------------------------------- 
 361 // wxRegionGeneric comparison 
 362 // ---------------------------------------------------------------------------- 
 364 bool wxRegionGeneric::Empty() const 
 367     return REGION::XEmptyRegion(M_REGIONDATA
); 
 370 // Does the region contain the point (x,y)? 
 371 wxRegionContain 
wxRegionGeneric::Contains(long x
, long y
) const 
 374     return REGION::XPointInRegion(M_REGIONDATA
,x
,y
)?wxInRegion
:wxOutRegion
; 
 377 // Does the region contain the point pt? 
 378 wxRegionContain 
wxRegionGeneric::Contains(const wxPoint
& pt
) const 
 381     return REGION::XPointInRegion(M_REGIONDATA
,pt
.x
,pt
.y
)?wxInRegion
:wxOutRegion
; 
 384 // Does the region contain the rectangle (x, y, w, h)? 
 385 wxRegionContain 
wxRegionGeneric::Contains(long x
, long y
, long w
, long h
) const 
 388     return REGION::XRectInRegion(M_REGIONDATA
,x
,y
,w
,h
); 
 391 // Does the region contain the rectangle rect? 
 392 wxRegionContain 
wxRegionGeneric::Contains(const wxRect
& rect
) const 
 395     return REGION::XRectInRegion(M_REGIONDATA
,rect
.x
,rect
.y
,rect
.width
,rect
.height
); 
 398 // ======================================================================== 
 399 // wxRegionIteratorGeneric 
 400 // ======================================================================== 
 401 //IMPLEMENT_DYNAMIC_CLASS(wxRegionIteratorGeneric,wxObject); 
 403 wxRegionIteratorGeneric::wxRegionIteratorGeneric() 
 408 wxRegionIteratorGeneric::wxRegionIteratorGeneric(const wxRegionGeneric
& region
) 
 414 wxRegionIteratorGeneric::wxRegionIteratorGeneric(const wxRegionIteratorGeneric
& iterator
) 
 415 :   m_region(iterator
.m_region
) 
 417     m_current 
= iterator
.m_current
; 
 420 void wxRegionIteratorGeneric::Reset(const wxRegionGeneric
& region
) 
 426 bool wxRegionIteratorGeneric::HaveRects() const 
 428     return M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 431 wxRegionIteratorGeneric
& wxRegionIteratorGeneric::operator++() 
 437 wxRegionIteratorGeneric 
wxRegionIteratorGeneric::operator++(int) 
 439     wxRegionIteratorGeneric 
copy(*this); 
 444 wxRect 
wxRegionIteratorGeneric::GetRect() const 
 446     wxASSERT(m_region
.m_refData
); 
 447     const Box 
*box 
= M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 457 long wxRegionIteratorGeneric::GetX() const 
 459     wxASSERT(m_region
.m_refData
); 
 460     const Box 
*box 
= M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 465 long wxRegionIteratorGeneric::GetY() const 
 467     wxASSERT(m_region
.m_refData
); 
 468     const Box 
*box 
= M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 473 long wxRegionIteratorGeneric::GetW() const 
 475     wxASSERT(m_region
.m_refData
); 
 476     const Box 
*box 
= M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 478     return box
->x2 
- box
->x1
; 
 481 long wxRegionIteratorGeneric::GetH() const 
 483     wxASSERT(m_region
.m_refData
); 
 484     const Box 
*box 
= M_REGIONDATA_OF(m_region
)->GetBox(m_current
); 
 486     return box
->y2 
- box
->y1
; 
 489 wxRegionIteratorGeneric::~wxRegionIteratorGeneric() 
 494 // ======================================================================== 
 495 // The guts (from X.org) 
 496 // ======================================================================== 
 498 /************************************************************************ 
 500 Copyright 1987, 1988, 1998  The Open Group 
 502 Permission to use, copy, modify, distribute, and sell this software and its 
 503 documentation for any purpose is hereby granted without fee, provided that 
 504 the above copyright notice appear in all copies and that both that 
 505 copyright notice and this permission notice appear in supporting 
 508 The above copyright notice and this permission notice shall be included in 
 509 all copies or substantial portions of the Software. 
 511 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 512 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 513 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE 
 514 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 
 515 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 516 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 518 Except as contained in this notice, the name of The Open Group shall not be 
 519 used in advertising or otherwise to promote the sale, use or other dealings 
 520 in this Software without prior written authorization from The Open Group. 
 523 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 
 527 Permission to use, copy, modify, and distribute this software and its 
 528 documentation for any purpose and without fee is hereby granted, 
 529 provided that the above copyright notice appear in all copies and that 
 530 both that copyright notice and this permission notice appear in 
 531 supporting documentation, and that the name of Digital not be 
 532 used in advertising or publicity pertaining to distribution of the 
 533 software without specific, written prior permission. 
 535 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
 536 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
 537 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
 538 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
 539 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
 540 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
 543 ************************************************************************/ 
 545 /*  1 if two BOXs overlap. 
 546  *  0 if two BOXs do not overlap. 
 547  *  Remember, x2 and y2 are not in the region 
 549 #define EXTENTCHECK(r1, r2) \ 
 550     ((r1)->x2 > (r2)->x1 && \ 
 551      (r1)->x1 < (r2)->x2 && \ 
 552      (r1)->y2 > (r2)->y1 && \ 
 556  *   Check to see if there is enough memory in the present region. 
 558 #define MEMCHECK(reg, rect, firstrect){\ 
 559         if ((reg)->numRects >= ((reg)->size - 1)){\ 
 560           (firstrect) = (BOX *) realloc \ 
 561           ((char *)(firstrect), (unsigned) (2 * (sizeof(BOX)) * ((reg)->size)));\ 
 562           if ((firstrect) == 0)\ 
 565           (rect) = &(firstrect)[(reg)->numRects];\ 
 569 #define EMPTY_REGION(pReg) pReg->numRects = 0 
 571 #define REGION_NOT_EMPTY(pReg) pReg->numRects 
 573 #define INBOX(r, x, y) \ 
 574       ( ( ((r).x2 >  x)) && \ 
 575         ( ((r).x1 <= x)) && \ 
 580  * The functions in this file implement the Region abstraction, similar to one 
 581  * used in the X11 sample server. A Region is simply an area, as the name 
 582  * implies, and is implemented as a "y-x-banded" array of rectangles. To 
 583  * explain: Each Region is made up of a certain number of rectangles sorted 
 584  * by y coordinate first, and then by x coordinate. 
 586  * Furthermore, the rectangles are banded such that every rectangle with a 
 587  * given upper-left y coordinate (y1) will have the same lower-right y 
 588  * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it 
 589  * will span the entire vertical distance of the band. This means that some 
 590  * areas that could be merged into a taller rectangle will be represented as 
 591  * several shorter rectangles to account for shorter rectangles to its left 
 592  * or right but within its "vertical scope". 
 594  * An added constraint on the rectangles is that they must cover as much 
 595  * horizontal area as possible. E.g. no two rectangles in a band are allowed 
 598  * Whenever possible, bands will be merged together to cover a greater vertical 
 599  * distance (and thus reduce the number of rectangles). Two bands can be merged 
 600  * only if the bottom of one touches the top of the other and they have 
 601  * rectangles in the same places (of the same width, of course). This maintains 
 602  * the y-x-banding that's so nice to have... 
 605 /* Create a new empty region */ 
 611     if (! (temp 
= new REGION
)) 
 612         return (Region
) NULL
; 
 613     if (! (temp
->rects 
= ( BOX 
* )malloc( (unsigned) sizeof( BOX 
)))) { 
 615         return (Region
) NULL
; 
 618     temp
->extents
.x1 
= 0; 
 619     temp
->extents
.y1 
= 0; 
 620     temp
->extents
.x2 
= 0; 
 621     temp
->extents
.y2 
= 0; 
 631     rect
->x 
= r
->extents
.x1
; 
 632     rect
->y 
= r
->extents
.y1
; 
 633     rect
->width 
= r
->extents
.x2 
- r
->extents
.x1
; 
 634     rect
->height 
= r
->extents
.y2 
- r
->extents
.y1
; 
 639  *----------------------------------------------------------------------- 
 641  *    Reset the extents of a region to what they should be. Called by 
 642  *    miSubtract and miIntersect b/c they can't figure it out along the 
 643  *    way or do so easily, as miUnion can. 
 649  *    The region's 'extents' structure is overwritten. 
 651  *----------------------------------------------------------------------- 
 654 miSetExtents (Region pReg
) 
 656     register BoxPtr pBox
, 
 660     if (pReg
->numRects 
== 0) 
 662         pReg
->extents
.x1 
= 0; 
 663         pReg
->extents
.y1 
= 0; 
 664         pReg
->extents
.x2 
= 0; 
 665         pReg
->extents
.y2 
= 0; 
 669     pExtents 
= &pReg
->extents
; 
 671     pBoxEnd 
= &pBox
[pReg
->numRects 
- 1]; 
 674      * Since pBox is the first rectangle in the region, it must have the 
 675      * smallest y1 and since pBoxEnd is the last rectangle in the region, 
 676      * it must have the largest y2, because of banding. Initialize x1 and 
 677      * x2 from  pBox and pBoxEnd, resp., as good things to initialize them 
 680     pExtents
->x1 
= pBox
->x1
; 
 681     pExtents
->y1 
= pBox
->y1
; 
 682     pExtents
->x2 
= pBoxEnd
->x2
; 
 683     pExtents
->y2 
= pBoxEnd
->y2
; 
 685     assert(pExtents
->y1 
< pExtents
->y2
); 
 686     while (pBox 
<= pBoxEnd
) 
 688         if (pBox
->x1 
< pExtents
->x1
) 
 690             pExtents
->x1 
= pBox
->x1
; 
 692         if (pBox
->x2 
> pExtents
->x2
) 
 694             pExtents
->x2 
= pBox
->x2
; 
 698     assert(pExtents
->x1 
< pExtents
->x2
); 
 705     free( (char *) r
->rects 
); 
 710 /* TranslateRegion(pRegion, x, y) 
 717     register Region pRegion
, 
 724     pbox 
= pRegion
->rects
; 
 725     nbox 
= pRegion
->numRects
; 
 735     pRegion
->extents
.x1 
+= x
; 
 736     pRegion
->extents
.x2 
+= x
; 
 737     pRegion
->extents
.y1 
+= y
; 
 738     pRegion
->extents
.y2 
+= y
; 
 742 /*====================================================================== 
 743  *  Region Intersection 
 744  *====================================================================*/ 
 746  *----------------------------------------------------------------------- 
 748  *    Handle an overlapping band for miIntersect. 
 754  *    Rectangles may be added to the region. 
 756  *----------------------------------------------------------------------- 
 761     register Region     pReg
, 
 771     register BoxPtr     pNextRect
; 
 773     pNextRect 
= &pReg
->rects
[pReg
->numRects
]; 
 775     while ((r1 
!= r1End
) && (r2 
!= r2End
)) 
 777         x1 
= wxMax(r1
->x1
,r2
->x1
); 
 778         x2 
= wxMin(r1
->x2
,r2
->x2
); 
 781          * If there's any overlap between the two rectangles, add that 
 782          * overlap to the new region. 
 783          * There's no need to check for subsumption because the only way 
 784          * such a need could arise is if some region has two rectangles 
 785          * right next to each other. Since that should never happen... 
 791             MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
 798             assert(pReg
->numRects 
<= pReg
->size
); 
 802          * Need to advance the pointers. Shift the one that extends 
 803          * to the right the least, since the other still has a chance to 
 804          * overlap with that region's next rectangle, if you see what I mean. 
 810         else if (r2
->x2 
< r1
->x2
) 
 826     Region reg2
, /* source regions     */ 
 827     register Region newReg
) /* destination Region */ 
 829    /* check for trivial reject */ 
 830     if ( (!(reg1
->numRects
)) || (!(reg2
->numRects
))  || 
 831         (!EXTENTCHECK(®1
->extents
, ®2
->extents
))) 
 832         newReg
->numRects 
= 0; 
 834         miRegionOp (newReg
, reg1
, reg2
, 
 835                     miIntersectO
, NULL
, NULL
); 
 838      * Can't alter newReg's extents before we call miRegionOp because 
 839      * it might be one of the source regions and miRegionOp depends 
 840      * on the extents of those regions being the same. Besides, this 
 841      * way there's no checking against rectangles that will be nuked 
 842      * due to coalescing, so we have to examine fewer rectangles. 
 844     miSetExtents(newReg
); 
 850     register Region dstrgn
, 
 854     if (dstrgn 
!= rgn
) /*  don't want to copy to itself */ 
 856         if (dstrgn
->size 
< rgn
->numRects
) 
 860                 BOX 
*prevRects 
= dstrgn
->rects
; 
 862                 if (! (dstrgn
->rects 
= (BOX 
*) 
 863                        realloc((char *) dstrgn
->rects
, 
 864                                (unsigned) rgn
->numRects 
* (sizeof(BOX
))))) 
 870             dstrgn
->size 
= rgn
->numRects
; 
 872         dstrgn
->numRects 
= rgn
->numRects
; 
 873         dstrgn
->extents
.x1 
= rgn
->extents
.x1
; 
 874         dstrgn
->extents
.y1 
= rgn
->extents
.y1
; 
 875         dstrgn
->extents
.x2 
= rgn
->extents
.x2
; 
 876         dstrgn
->extents
.y2 
= rgn
->extents
.y2
; 
 878         memcpy((char *) dstrgn
->rects
, (char *) rgn
->rects
, 
 879                 (int) (rgn
->numRects 
* sizeof(BOX
))); 
 883 /*====================================================================== 
 884  * Generic Region Operator 
 885  *====================================================================*/ 
 888  *----------------------------------------------------------------------- 
 890  *    Attempt to merge the boxes in the current band with those in the 
 891  *    previous one. Used only by miRegionOp. 
 894  *    The new index for the previous band. 
 897  *    If coalescing takes place: 
 898  *        - rectangles in the previous band will have their y2 fields 
 900  *        - pReg->numRects will be decreased. 
 902  *----------------------------------------------------------------------- 
 907     register Region pReg
,     /* Region to coalesce */ 
 908     int prevStart
,            /* Index of start of previous band */ 
 909     int curStart
)             /* Index of start of current band */ 
 911     register BoxPtr pPrevBox
; /* Current box in previous band */ 
 912     register BoxPtr pCurBox
;  /* Current box in current band */ 
 913     register BoxPtr pRegEnd
;  /* End of region */ 
 914     int         curNumRects
;  /* Number of rectangles in current 
 916     int        prevNumRects
;  /* Number of rectangles in previous 
 918     int              bandY1
;  /* Y1 coordinate for current band */ 
 920     pRegEnd 
= &pReg
->rects
[pReg
->numRects
]; 
 922     pPrevBox 
= &pReg
->rects
[prevStart
]; 
 923     prevNumRects 
= curStart 
- prevStart
; 
 926      * Figure out how many rectangles are in the current band. Have to do 
 927      * this because multiple bands could have been added in miRegionOp 
 928      * at the end when one region has been exhausted. 
 930     pCurBox 
= &pReg
->rects
[curStart
]; 
 931     bandY1 
= pCurBox
->y1
; 
 932     for (curNumRects 
= 0; 
 933          (pCurBox 
!= pRegEnd
) && (pCurBox
->y1 
== bandY1
); 
 939     if (pCurBox 
!= pRegEnd
) 
 942          * If more than one band was added, we have to find the start 
 943          * of the last band added so the next coalescing job can start 
 944          * at the right place... (given when multiple bands are added, 
 945          * this may be pointless -- see above). 
 948         while (pRegEnd
[-1].y1 
== pRegEnd
->y1
) 
 952         curStart 
= pRegEnd 
- pReg
->rects
; 
 953         pRegEnd 
= pReg
->rects 
+ pReg
->numRects
; 
 956     if ((curNumRects 
== prevNumRects
) && (curNumRects 
!= 0)) 
 958         pCurBox 
-= curNumRects
; 
 960          * The bands may only be coalesced if the bottom of the previous 
 961          * matches the top scanline of the current. 
 963         if (pPrevBox
->y2 
== pCurBox
->y1
) 
 966          * Make sure the bands have boxes in the same places. This 
 967          * assumes that boxes have been added in such a way that they 
 968          * cover the most area possible. I.e. two boxes in a band must 
 969          * have some horizontal space between them. 
 973                 if ((pPrevBox
->x1 
!= pCurBox
->x1
) || 
 974                     (pPrevBox
->x2 
!= pCurBox
->x2
)) 
 977                      * The bands don't line up so they can't be coalesced. 
 984             } while (prevNumRects 
!= 0); 
 986             pReg
->numRects 
-= curNumRects
; 
 987             pCurBox 
-= curNumRects
; 
 988             pPrevBox 
-= curNumRects
; 
 991              * The bands may be merged, so set the bottom y of each box 
 992              * in the previous band to that of the corresponding box in 
 997                 pPrevBox
->y2 
= pCurBox
->y2
; 
1001             } while (curNumRects 
!= 0); 
1004              * If only one band was added to the region, we have to backup 
1005              * curStart to the start of the previous band. 
1007              * If more than one band was added to the region, copy the 
1008              * other bands down. The assumption here is that the other bands 
1009              * came from the same region as the current one and no further 
1010              * coalescing can be done on them since it's all been done 
1011              * already... curStart is already in the right place. 
1013             if (pCurBox 
== pRegEnd
) 
1015                 curStart 
= prevStart
; 
1021                     *pPrevBox
++ = *pCurBox
++; 
1022                 } while (pCurBox 
!= pRegEnd
); 
1031  *----------------------------------------------------------------------- 
1033  *        Apply an operation to two regions. Called by miUnion, miInverse, 
1034  *        miSubtract, miIntersect... 
1040  *        The new region is overwritten. 
1043  *        The idea behind this function is to view the two regions as sets. 
1044  *        Together they cover a rectangle of area that this function divides 
1045  *        into horizontal bands where points are covered only by one region 
1046  *        or by both. For the first case, the nonOverlapFunc is called with 
1047  *        each the band and the band's upper and lower extents. For the 
1048  *        second, the overlapFunc is called to process the entire band. It 
1049  *        is responsible for clipping the rectangles in the band, though 
1050  *        this function provides the boundaries. 
1051  *        At the end of each band, the new region is coalesced, if possible, 
1052  *        to reduce the number of rectangles in the region. 
1054  *----------------------------------------------------------------------- 
1059     register Region         newReg
,                              /* Place to store result */ 
1060     Region                  reg1
,                                /* First region in operation */ 
1061     Region                  reg2
,                                /* 2d region in operation */ 
1063         register Region     pReg
, 
1069         wxCoord               y2
),              /* Function to call for over- 
1071     int                      (*nonOverlap1Func
)( 
1072         register Region     pReg
, 
1075         register wxCoord      y1
, 
1076         register wxCoord      y2
),              /* Function to call for non- 
1077                                                  * overlapping bands in region 
1079     int                      (*nonOverlap2Func
)( 
1080         register Region     pReg
, 
1083         register wxCoord      y1
, 
1084         register wxCoord      y2
))              /* Function to call for non- 
1085                                                  * overlapping bands in region 
1088     register BoxPtr        r1
; /* Pointer into first region */ 
1089     register BoxPtr        r2
; /* Pointer into 2d region */ 
1090     BoxPtr              r1End
; /* End of 1st region */ 
1091     BoxPtr              r2End
; /* End of 2d region */ 
1092     register wxCoord     ybot
; /* Bottom of intersection */ 
1093     register wxCoord     ytop
; /* Top of intersection */ 
1094     BoxPtr           oldRects
; /* Old rects for newReg */ 
1095     int              prevBand
; /* Index of start of 
1096                                 * previous band in newReg */ 
1097     int               curBand
; /* Index of start of current 
1099     register BoxPtr r1BandEnd
; /* End of current band in r1 */ 
1100     register BoxPtr r2BandEnd
; /* End of current band in r2 */ 
1101     wxCoord               top
; /* Top of non-overlapping 
1103     wxCoord               bot
; /* Bottom of non-overlapping 
1108      *        set r1, r2, r1End and r2End appropriately, preserve the important 
1109      * parts of the destination region until the end in case it's one of 
1110      * the two source regions, then mark the "new" region empty, allocating 
1111      * another array of rectangles for it to use. 
1115     r1End 
= r1 
+ reg1
->numRects
; 
1116     r2End 
= r2 
+ reg2
->numRects
; 
1118     oldRects 
= newReg
->rects
; 
1120     EMPTY_REGION(newReg
); 
1123      * Allocate a reasonable number of rectangles for the new region. The idea 
1124      * is to allocate enough so the individual functions don't need to 
1125      * reallocate and copy the array, which is time consuming, yet we don't 
1126      * have to worry about using too much memory. I hope to be able to 
1127      * nuke the realloc() at the end of this function eventually. 
1129     newReg
->size 
= wxMax(reg1
->numRects
,reg2
->numRects
) * 2; 
1131     if (! (newReg
->rects 
= (BoxPtr
) 
1132            malloc ((unsigned) (sizeof(BoxRec
) * newReg
->size
)))) { 
1138      * Initialize ybot and ytop. 
1139      * In the upcoming loop, ybot and ytop serve different functions depending 
1140      * on whether the band being handled is an overlapping or non-overlapping 
1142      *         In the case of a non-overlapping band (only one of the regions 
1143      * has points in the band), ybot is the bottom of the most recent 
1144      * intersection and thus clips the top of the rectangles in that band. 
1145      * ytop is the top of the next intersection between the two regions and 
1146      * serves to clip the bottom of the rectangles in the current band. 
1147      *        For an overlapping band (where the two regions intersect), ytop clips 
1148      * the top of the rectangles of both regions and ybot clips the bottoms. 
1150     if (reg1
->extents
.y1 
< reg2
->extents
.y1
) 
1151         ybot 
= reg1
->extents
.y1
; 
1153         ybot 
= reg2
->extents
.y1
; 
1156      * prevBand serves to mark the start of the previous band so rectangles 
1157      * can be coalesced into larger rectangles. qv. miCoalesce, above. 
1158      * In the beginning, there is no previous band, so prevBand == curBand 
1159      * (curBand is set later on, of course, but the first band will always 
1160      * start at index 0). prevBand and curBand must be indices because of 
1161      * the possible expansion, and resultant moving, of the new region's 
1162      * array of rectangles. 
1168         curBand 
= newReg
->numRects
; 
1171          * This algorithm proceeds one source-band (as opposed to a 
1172          * destination band, which is determined by where the two regions 
1173          * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the 
1174          * rectangle after the last one in the current band for their 
1175          * respective regions. 
1178         while ((r1BandEnd 
!= r1End
) && (r1BandEnd
->y1 
== r1
->y1
)) 
1184         while ((r2BandEnd 
!= r2End
) && (r2BandEnd
->y1 
== r2
->y1
)) 
1190          * First handle the band that doesn't intersect, if any. 
1192          * Note that attention is restricted to one band in the 
1193          * non-intersecting region at once, so if a region has n 
1194          * bands between the current position and the next place it overlaps 
1195          * the other, this entire loop will be passed through n times. 
1197         if (r1
->y1 
< r2
->y1
) 
1199             top 
= wxMax(r1
->y1
,ybot
); 
1200             bot 
= wxMin(r1
->y2
,r2
->y1
); 
1202             if ((top 
!= bot
) && (nonOverlap1Func 
!= NULL
)) 
1204                 (* nonOverlap1Func
) (newReg
, r1
, r1BandEnd
, top
, bot
); 
1209         else if (r2
->y1 
< r1
->y1
) 
1211             top 
= wxMax(r2
->y1
,ybot
); 
1212             bot 
= wxMin(r2
->y2
,r1
->y1
); 
1214             if ((top 
!= bot
) && (nonOverlap2Func 
!= NULL
)) 
1216                 (* nonOverlap2Func
) (newReg
, r2
, r2BandEnd
, top
, bot
); 
1227          * If any rectangles got added to the region, try and coalesce them 
1228          * with rectangles from the previous band. Note we could just do 
1229          * this test in miCoalesce, but some machines incur a not 
1230          * inconsiderable cost for function calls, so... 
1232         if (newReg
->numRects 
!= curBand
) 
1234             prevBand 
= miCoalesce (newReg
, prevBand
, curBand
); 
1238          * Now see if we've hit an intersecting band. The two bands only 
1239          * intersect if ybot > ytop 
1241         ybot 
= wxMin(r1
->y2
, r2
->y2
); 
1242         curBand 
= newReg
->numRects
; 
1245             (* overlapFunc
) (newReg
, r1
, r1BandEnd
, r2
, r2BandEnd
, ytop
, ybot
); 
1249         if (newReg
->numRects 
!= curBand
) 
1251             prevBand 
= miCoalesce (newReg
, prevBand
, curBand
); 
1255          * If we've finished with a band (y2 == ybot) we skip forward 
1256          * in the region to the next band. 
1266     } while ((r1 
!= r1End
) && (r2 
!= r2End
)); 
1269      * Deal with whichever region still has rectangles left. 
1271     curBand 
= newReg
->numRects
; 
1274         if (nonOverlap1Func 
!= NULL
) 
1279                 while ((r1BandEnd 
< r1End
) && (r1BandEnd
->y1 
== r1
->y1
)) 
1283                 (* nonOverlap1Func
) (newReg
, r1
, r1BandEnd
, 
1284                                      wxMax(r1
->y1
,ybot
), r1
->y2
); 
1286             } while (r1 
!= r1End
); 
1289     else if ((r2 
!= r2End
) && (nonOverlap2Func 
!= NULL
)) 
1294             while ((r2BandEnd 
< r2End
) && (r2BandEnd
->y1 
== r2
->y1
)) 
1298             (* nonOverlap2Func
) (newReg
, r2
, r2BandEnd
, 
1299                                 wxMax(r2
->y1
,ybot
), r2
->y2
); 
1301         } while (r2 
!= r2End
); 
1304     if (newReg
->numRects 
!= curBand
) 
1306         (void) miCoalesce (newReg
, prevBand
, curBand
); 
1310      * A bit of cleanup. To keep regions from growing without bound, 
1311      * we shrink the array of rectangles to match the new number of 
1312      * rectangles in the region. This never goes to 0, however... 
1314      * Only do this stuff if the number of rectangles allocated is more than 
1315      * twice the number of rectangles in the region (a simple optimization...). 
1317     if (newReg
->numRects 
< (newReg
->size 
>> 1)) 
1319         if (REGION_NOT_EMPTY(newReg
)) 
1321             BoxPtr prev_rects 
= newReg
->rects
; 
1322             newReg
->size 
= newReg
->numRects
; 
1323             newReg
->rects 
= (BoxPtr
) realloc ((char *) newReg
->rects
, 
1324                                    (unsigned) (sizeof(BoxRec
) * newReg
->size
)); 
1325             if (! newReg
->rects
) 
1326                 newReg
->rects 
= prev_rects
; 
1331              * No point in doing the extra work involved in an realloc if 
1332              * the region is empty 
1335             free((char *) newReg
->rects
); 
1336             newReg
->rects 
= (BoxPtr
) malloc(sizeof(BoxRec
)); 
1339     free ((char *) oldRects
); 
1343 /*====================================================================== 
1345  *====================================================================*/ 
1348  *----------------------------------------------------------------------- 
1350  *        Handle a non-overlapping band for the union operation. Just 
1351  *        Adds the rectangles into the region. Doesn't have to check for 
1352  *        subsumption or anything. 
1358  *        pReg->numRects is incremented and the final rectangles overwritten 
1359  *        with the rectangles we're passed. 
1361  *----------------------------------------------------------------------- 
1366     register Region        pReg
, 
1369     register wxCoord       y1
, 
1370     register wxCoord       y2
) 
1372     register BoxPtr        pNextRect
; 
1374     pNextRect 
= &pReg
->rects
[pReg
->numRects
]; 
1380         assert(r
->x1 
< r
->x2
); 
1381         MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
1382         pNextRect
->x1 
= r
->x1
; 
1384         pNextRect
->x2 
= r
->x2
; 
1386         pReg
->numRects 
+= 1; 
1389         assert(pReg
->numRects
<=pReg
->size
); 
1392     return 0;        /* lint */ 
1397  *----------------------------------------------------------------------- 
1399  *        Handle an overlapping band for the union operation. Picks the 
1400  *        left-most rectangle each time and merges it into the region. 
1406  *        Rectangles are overwritten in pReg->rects and pReg->numRects will 
1409  *----------------------------------------------------------------------- 
1415     register Region        pReg
, 
1420     register wxCoord       y1
, 
1421     register wxCoord       y2
) 
1423     register BoxPtr        pNextRect
; 
1425     pNextRect 
= &pReg
->rects
[pReg
->numRects
]; 
1427 #define MERGERECT(r) \ 
1428     if ((pReg->numRects != 0) &&  \ 
1429         (pNextRect[-1].y1 == y1) &&  \ 
1430         (pNextRect[-1].y2 == y2) &&  \ 
1431         (pNextRect[-1].x2 >= r->x1))  \ 
1433         if (pNextRect[-1].x2 < r->x2)  \ 
1435             pNextRect[-1].x2 = r->x2;  \ 
1436             assert(pNextRect[-1].x1<pNextRect[-1].x2); \ 
1441         MEMCHECK(pReg, pNextRect, pReg->rects);  \ 
1442         pNextRect->y1 = y1;  \ 
1443         pNextRect->y2 = y2;  \ 
1444         pNextRect->x1 = r->x1;  \ 
1445         pNextRect->x2 = r->x2;  \ 
1446         pReg->numRects += 1;  \ 
1449     assert(pReg->numRects<=pReg->size);\ 
1453     while ((r1 
!= r1End
) && (r2 
!= r2End
)) 
1455         if (r1
->x1 
< r2
->x1
) 
1470         } while (r1 
!= r1End
); 
1472     else while (r2 
!= r2End
) 
1476     return 0;        /* lint */ 
1482     Region          reg2
,             /* source regions     */ 
1483     Region           newReg
)                  /* destination Region */ 
1485     /*  checks all the simple cases */ 
1488      * Region 1 and 2 are the same or region 1 is empty 
1490     if ( (reg1 
== reg2
) || (!(reg1
->numRects
)) ) 
1493             miRegionCopy(newReg
, reg2
); 
1498      * if nothing to union (region 2 empty) 
1500     if (!(reg2
->numRects
)) 
1503             miRegionCopy(newReg
, reg1
); 
1508      * Region 1 completely subsumes region 2 
1510     if ((reg1
->numRects 
== 1) && 
1511         (reg1
->extents
.x1 
<= reg2
->extents
.x1
) && 
1512         (reg1
->extents
.y1 
<= reg2
->extents
.y1
) && 
1513         (reg1
->extents
.x2 
>= reg2
->extents
.x2
) && 
1514         (reg1
->extents
.y2 
>= reg2
->extents
.y2
)) 
1517             miRegionCopy(newReg
, reg1
); 
1522      * Region 2 completely subsumes region 1 
1524     if ((reg2
->numRects 
== 1) && 
1525         (reg2
->extents
.x1 
<= reg1
->extents
.x1
) && 
1526         (reg2
->extents
.y1 
<= reg1
->extents
.y1
) && 
1527         (reg2
->extents
.x2 
>= reg1
->extents
.x2
) && 
1528         (reg2
->extents
.y2 
>= reg1
->extents
.y2
)) 
1531             miRegionCopy(newReg
, reg2
); 
1535     miRegionOp (newReg
, reg1
, reg2
, miUnionO
, 
1536                     miUnionNonO
, miUnionNonO
); 
1538     newReg
->extents
.x1 
= wxMin(reg1
->extents
.x1
, reg2
->extents
.x1
); 
1539     newReg
->extents
.y1 
= wxMin(reg1
->extents
.y1
, reg2
->extents
.y1
); 
1540     newReg
->extents
.x2 
= wxMax(reg1
->extents
.x2
, reg2
->extents
.x2
); 
1541     newReg
->extents
.y2 
= wxMax(reg1
->extents
.y2
, reg2
->extents
.y2
); 
1546 /*====================================================================== 
1547  *                       Region Subtraction 
1548  *====================================================================*/ 
1551  *----------------------------------------------------------------------- 
1553  *        Deal with non-overlapping band for subtraction. Any parts from 
1554  *        region 2 we discard. Anything from region 1 we add to the region. 
1560  *        pReg may be affected. 
1562  *----------------------------------------------------------------------- 
1567     register Region        pReg
, 
1570     register wxCoord          y1
, 
1571     register wxCoord           y2
) 
1573     register BoxPtr        pNextRect
; 
1575     pNextRect 
= &pReg
->rects
[pReg
->numRects
]; 
1581         assert(r
->x1
<r
->x2
); 
1582         MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
1583         pNextRect
->x1 
= r
->x1
; 
1585         pNextRect
->x2 
= r
->x2
; 
1587         pReg
->numRects 
+= 1; 
1590         assert(pReg
->numRects 
<= pReg
->size
); 
1594     return 0;        /* lint */ 
1598  *----------------------------------------------------------------------- 
1600  *        Overlapping band subtraction. x1 is the left-most point not yet 
1607  *        pReg may have rectangles added to it. 
1609  *----------------------------------------------------------------------- 
1614     register Region        pReg
, 
1619     register wxCoord          y1
, 
1620     register wxCoord          y2
) 
1622     register BoxPtr        pNextRect
; 
1628     pNextRect 
= &pReg
->rects
[pReg
->numRects
]; 
1630     while ((r1 
!= r1End
) && (r2 
!= r2End
)) 
1635              * Subtrahend missed the boat: go to next subtrahend. 
1639         else if (r2
->x1 
<= x1
) 
1642              * Subtrahend preceeds minuend: nuke left edge of minuend. 
1648                  * Minuend completely covered: advance to next minuend and 
1649                  * reset left fence to edge of new minuend. 
1658                  * Subtrahend now used up since it doesn't extend beyond 
1664         else if (r2
->x1 
< r1
->x2
) 
1667              * Left part of subtrahend covers part of minuend: add uncovered 
1668              * part of minuend to region and skip to next subtrahend. 
1671             MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
1674             pNextRect
->x2 
= r2
->x1
; 
1676             pReg
->numRects 
+= 1; 
1679             assert(pReg
->numRects
<=pReg
->size
); 
1685                  * Minuend used up: advance to new... 
1694                  * Subtrahend used up 
1702              * Minuend used up: add any remaining piece before advancing. 
1706                 MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
1709                 pNextRect
->x2 
= r1
->x2
; 
1711                 pReg
->numRects 
+= 1; 
1713                 assert(pReg
->numRects
<=pReg
->size
); 
1722      * Add remaining minuend rectangles to region. 
1727         MEMCHECK(pReg
, pNextRect
, pReg
->rects
); 
1730         pNextRect
->x2 
= r1
->x2
; 
1732         pReg
->numRects 
+= 1; 
1735         assert(pReg
->numRects
<=pReg
->size
); 
1743     return 0;        /* lint */ 
1747  *----------------------------------------------------------------------- 
1749  *        Subtract regS from regM and leave the result in regD. 
1750  *        S stands for subtrahend, M for minuend and D for difference. 
1756  *        regD is overwritten. 
1758  *----------------------------------------------------------------------- 
1765     register Region        regD
) 
1767    /* check for trivial reject */ 
1768     if ( (!(regM
->numRects
)) || (!(regS
->numRects
))  || 
1769         (!EXTENTCHECK(®M
->extents
, ®S
->extents
)) ) 
1771         miRegionCopy(regD
, regM
); 
1775     miRegionOp (regD
, regM
, regS
, miSubtractO
, 
1776                     miSubtractNonO1
, NULL
); 
1779      * Can't alter newReg's extents before we call miRegionOp because 
1780      * it might be one of the source regions and miRegionOp depends 
1781      * on the extents of those regions being the unaltered. Besides, this 
1782      * way there's no checking against rectangles that will be nuked 
1783      * due to coalescing, so we have to examine fewer rectangles. 
1785     miSetExtents (regD
); 
1790 XXorRegion(Region sra
, Region srb
, Region dr
) 
1794     if ((! (tra 
= XCreateRegion())) || (! (trb 
= XCreateRegion()))) 
1796     (void) XSubtractRegion(sra
,srb
,tra
); 
1797     (void) XSubtractRegion(srb
,sra
,trb
); 
1798     (void) XUnionRegion(tra
,trb
,dr
); 
1799     XDestroyRegion(tra
); 
1800     XDestroyRegion(trb
); 
1805  * Check to see if the region is empty.  Assumes a region is passed 
1812     if( r
->numRects 
== 0 ) return true; 
1817  *        Check to see if two regions are equal 
1820 XEqualRegion(Region r1
, Region r2
) 
1824     if( r1
->numRects 
!= r2
->numRects 
) return false; 
1825     else if( r1
->numRects 
== 0 ) return true; 
1826     else if ( r1
->extents
.x1 
!= r2
->extents
.x1 
) return false; 
1827     else if ( r1
->extents
.x2 
!= r2
->extents
.x2 
) return false; 
1828     else if ( r1
->extents
.y1 
!= r2
->extents
.y1 
) return false; 
1829     else if ( r1
->extents
.y2 
!= r2
->extents
.y2 
) return false; 
1830     else for( i
=0; i 
< r1
->numRects
; i
++ ) { 
1831             if ( r1
->rects
[i
].x1 
!= r2
->rects
[i
].x1 
) return false; 
1832             else if ( r1
->rects
[i
].x2 
!= r2
->rects
[i
].x2 
) return false; 
1833             else if ( r1
->rects
[i
].y1 
!= r2
->rects
[i
].y1 
) return false; 
1834             else if ( r1
->rects
[i
].y2 
!= r2
->rects
[i
].y2 
) return false; 
1846     if (pRegion
->numRects 
== 0) 
1848     if (!INBOX(pRegion
->extents
, x
, y
)) 
1850     for (i
=0; i
<pRegion
->numRects
; i
++) 
1852         if (INBOX (pRegion
->rects
[i
], x
, y
)) 
1858 wxRegionContain 
REGION:: 
1860     register Region        region
, 
1862     unsigned int rwidth
, unsigned int rheight
) 
1864     register BoxPtr pbox
; 
1865     register BoxPtr pboxEnd
; 
1867     register BoxPtr prect 
= &rect
; 
1868     int      partIn
, partOut
; 
1872     prect
->x2 
= rwidth 
+ rx
; 
1873     prect
->y2 
= rheight 
+ ry
; 
1875     /* this is (just) a useful optimization */ 
1876     if ((region
->numRects 
== 0) || !EXTENTCHECK(®ion
->extents
, prect
)) 
1877         return(wxOutRegion
); 
1882     /* can stop when both partOut and partIn are true, or we reach prect->y2 */ 
1883     for (pbox 
= region
->rects
, pboxEnd 
= pbox 
+ region
->numRects
; 
1889            continue;        /* getting up to speed or skipping remainder of band */ 
1893            partOut 
= true;        /* missed part of rectangle above */ 
1894            if (partIn 
|| (pbox
->y1 
>= prect
->y2
)) 
1896            ry 
= pbox
->y1
;        /* x guaranteed to be == prect->x1 */ 
1900            continue;                /* not far enough over yet */ 
1904            partOut 
= true;        /* missed part of rectangle to left */ 
1909         if (pbox
->x1 
< prect
->x2
) 
1911             partIn 
= true;        /* definitely overlap */ 
1916         if (pbox
->x2 
>= prect
->x2
) 
1918            ry 
= pbox
->y2
;        /* finished with this band */ 
1919            if (ry 
>= prect
->y2
) 
1921            rx 
= prect
->x1
;        /* reset x out to left again */ 
1925              * Because boxes in a band are maximal width, if the first box 
1926              * to overlap the rectangle doesn't completely cover it in that 
1927              * band, the rectangle must be partially out, since some of it 
1928              * will be uncovered in that band. partIn will have been set true 
1936     return(partIn 
? ((ry 
< prect
->y2
) ? wxPartRegion 
: wxInRegion
) :