tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-region.c (79940B)


      1 /*
      2 * Copyright 1987, 1988, 1989, 1998  The Open Group
      3 * 
      4 * Permission to use, copy, modify, distribute, and sell this software and its
      5 * documentation for any purpose is hereby granted without fee, provided that
      6 * the above copyright notice appear in all copies and that both that
      7 * copyright notice and this permission notice appear in supporting
      8 * documentation.
      9 * 
     10 * The above copyright notice and this permission notice shall be included in
     11 * all copies or substantial portions of the Software.
     12 * 
     13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     16 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     17 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     18 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     19 * 
     20 * Except as contained in this notice, the name of The Open Group shall not be
     21 * used in advertising or otherwise to promote the sale, use or other dealings
     22 * in this Software without prior written authorization from The Open Group.
     23 * 
     24 * Copyright 1987, 1988, 1989 by
     25 * Digital Equipment Corporation, Maynard, Massachusetts.
     26 * 
     27 *                    All Rights Reserved
     28 * 
     29 * Permission to use, copy, modify, and distribute this software and its
     30 * documentation for any purpose and without fee is hereby granted,
     31 * provided that the above copyright notice appear in all copies and that
     32 * both that copyright notice and this permission notice appear in
     33 * supporting documentation, and that the name of Digital not be
     34 * used in advertising or publicity pertaining to distribution of the
     35 * software without specific, written prior permission.
     36 * 
     37 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     38 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     39 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     40 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     41 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     42 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     43 * SOFTWARE.
     44 *
     45 * Copyright © 1998 Keith Packard
     46 *
     47 * Permission to use, copy, modify, distribute, and sell this software and its
     48 * documentation for any purpose is hereby granted without fee, provided that
     49 * the above copyright notice appear in all copies and that both that
     50 * copyright notice and this permission notice appear in supporting
     51 * documentation, and that the name of Keith Packard not be used in
     52 * advertising or publicity pertaining to distribution of the software without
     53 * specific, written prior permission.  Keith Packard makes no
     54 * representations about the suitability of this software for any purpose.  It
     55 * is provided "as is" without express or implied warranty.
     56 *
     57 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     58 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     59 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     60 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     61 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     62 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     63 * PERFORMANCE OF THIS SOFTWARE.
     64 */
     65 
     66 #include <stdlib.h>
     67 #include <limits.h>
     68 #include <string.h>
     69 #include <stdio.h>
     70 #include "pixman-private.h"
     71 
     72 #define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
     73 /* not a region */
     74 #define PIXREGION_NAR(reg)      ((reg)->data == pixman_broken_data)
     75 #define PIXREGION_NUMRECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
     76 #define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
     77 #define PIXREGION_RECTS(reg) \
     78    ((reg)->data ? (box_type_t *)((reg)->data + 1) \
     79     : (box_type_t *)&(reg)->extents)
     80 #define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1))
     81 #define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR (reg)[i])
     82 #define PIXREGION_TOP(reg) PIXREGION_BOX (reg, (reg)->data->numRects)
     83 #define PIXREGION_END(reg) PIXREGION_BOX (reg, (reg)->data->numRects - 1)
     84 
     85 #define GOOD_RECT(rect) ((rect)->x1 < (rect)->x2 && (rect)->y1 < (rect)->y2)
     86 #define BAD_RECT(rect) ((rect)->x1 > (rect)->x2 || (rect)->y1 > (rect)->y2)
     87 
     88 #ifdef DEBUG
     89 
     90 #define GOOD(reg)							\
     91    do									\
     92    {									\
     93 if (!PREFIX (_selfcheck (reg)))					\
     94     _pixman_log_error (FUNC, "Malformed region " # reg);	\
     95    } while (0)
     96 
     97 #else
     98 
     99 #define GOOD(reg)
    100 
    101 #endif
    102 
    103 static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
    104 static const region_data_type_t PREFIX (_empty_data_) = { 0, 0 };
    105 #if defined (__llvm__) && !defined (__clang__)
    106 static const volatile region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
    107 #else
    108 static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
    109 #endif
    110 
    111 static box_type_t *pixman_region_empty_box =
    112    (box_type_t *)&PREFIX (_empty_box_);
    113 static region_data_type_t *pixman_region_empty_data =
    114    (region_data_type_t *)&PREFIX (_empty_data_);
    115 static region_data_type_t *pixman_broken_data =
    116    (region_data_type_t *)&PREFIX (_broken_data_);
    117 
    118 static pixman_bool_t
    119 pixman_break (region_type_t *region);
    120 
    121 /*
    122 * The functions in this file implement the Region abstraction used extensively
    123 * throughout the X11 sample server. A Region is simply a set of disjoint
    124 * (non-overlapping) rectangles, plus an "extent" rectangle which is the
    125 * smallest single rectangle that contains all the non-overlapping rectangles.
    126 *
    127 * A Region is implemented as a "y-x-banded" array of rectangles.  This array
    128 * imposes two degrees of order.  First, all rectangles are sorted by top side
    129 * y coordinate first (y1), and then by left side x coordinate (x1).
    130 *
    131 * Furthermore, the rectangles are grouped into "bands".  Each rectangle in a
    132 * band has the same top y coordinate (y1), and each has the same bottom y
    133 * coordinate (y2).  Thus all rectangles in a band differ only in their left
    134 * and right side (x1 and x2).  Bands are implicit in the array of rectangles:
    135 * there is no separate list of band start pointers.
    136 *
    137 * The y-x band representation does not minimize rectangles.  In particular,
    138 * if a rectangle vertically crosses a band (the rectangle has scanlines in
    139 * the y1 to y2 area spanned by the band), then the rectangle may be broken
    140 * down into two or more smaller rectangles stacked one atop the other.
    141 *
    142 *  -----------				    -----------
    143 *  |         |				    |         |		    band 0
    144 *  |         |  --------		    -----------  --------
    145 *  |         |  |      |  in y-x banded    |         |  |      |   band 1
    146 *  |         |  |      |  form is	    |         |  |      |
    147 *  -----------  |      |		    -----------  --------
    148 *               |      |				 |      |   band 2
    149 *               --------				 --------
    150 *
    151 * An added constraint on the rectangles is that they must cover as much
    152 * horizontal area as possible: no two rectangles within a band are allowed
    153 * to touch.
    154 *
    155 * Whenever possible, bands will be merged together to cover a greater vertical
    156 * distance (and thus reduce the number of rectangles). Two bands can be merged
    157 * only if the bottom of one touches the top of the other and they have
    158 * rectangles in the same places (of the same width, of course).
    159 *
    160 * Adam de Boor wrote most of the original region code.  Joel McCormack
    161 * substantially modified or rewrote most of the core arithmetic routines, and
    162 * added pixman_region_validate in order to support several speed improvements
    163 * to pixman_region_validate_tree.  Bob Scheifler changed the representation
    164 * to be more compact when empty or a single rectangle, and did a bunch of
    165 * gratuitous reformatting. Carl Worth did further gratuitous reformatting
    166 * while re-merging the server and client region code into libpixregion.
    167 * Soren Sandmann did even more gratuitous reformatting.
    168 */
    169 
    170 /*  true iff two Boxes overlap */
    171 #define EXTENTCHECK(r1, r2)	   \
    172    (!( ((r1)->x2 <= (r2)->x1)  || \
    173        ((r1)->x1 >= (r2)->x2)  || \
    174        ((r1)->y2 <= (r2)->y1)  || \
    175        ((r1)->y1 >= (r2)->y2) ) )
    176 
    177 /* true iff (x,y) is in Box */
    178 #define INBOX(r, x, y)	\
    179    ( ((r)->x2 >  x) && \
    180      ((r)->x1 <= x) && \
    181      ((r)->y2 >  y) && \
    182      ((r)->y1 <= y) )
    183 
    184 /* true iff Box r1 contains Box r2 */
    185 #define SUBSUMES(r1, r2)	\
    186    ( ((r1)->x1 <= (r2)->x1) && \
    187      ((r1)->x2 >= (r2)->x2) && \
    188      ((r1)->y1 <= (r2)->y1) && \
    189      ((r1)->y2 >= (r2)->y2) )
    190 
    191 static size_t
    192 PIXREGION_SZOF (size_t n)
    193 {
    194    size_t size = n * sizeof(box_type_t);
    195    
    196    if (n > UINT32_MAX / sizeof(box_type_t))
    197 return 0;
    198 
    199    if (sizeof(region_data_type_t) > UINT32_MAX - size)
    200 return 0;
    201 
    202    return size + sizeof(region_data_type_t);
    203 }
    204 
    205 static region_data_type_t *
    206 alloc_data (size_t n)
    207 {
    208    size_t sz = PIXREGION_SZOF (n);
    209 
    210    if (!sz)
    211 return NULL;
    212 
    213    return malloc (sz);
    214 }
    215 
    216 #define FREE_DATA(reg) if ((reg)->data && (reg)->data->size) free ((reg)->data)
    217 
    218 #define RECTALLOC_BAIL(region, n, bail)					\
    219    do									\
    220    {									\
    221 if (!(region)->data ||						\
    222     (((region)->data->numRects + (n)) > (region)->data->size))	\
    223 {								\
    224     if (!pixman_rect_alloc (region, n))				\
    225 	goto bail;						\
    226 }								\
    227    } while (0)
    228 
    229 #define RECTALLOC(region, n)						\
    230    do									\
    231    {									\
    232 if (!(region)->data ||						\
    233     (((region)->data->numRects + (n)) > (region)->data->size))	\
    234 {								\
    235     if (!pixman_rect_alloc (region, n)) {			\
    236 	return FALSE;						\
    237     }								\
    238 }								\
    239    } while (0)
    240 
    241 #define ADDRECT(next_rect, nx1, ny1, nx2, ny2)      \
    242    do						    \
    243    {						    \
    244 next_rect->x1 = nx1;                        \
    245 next_rect->y1 = ny1;                        \
    246 next_rect->x2 = nx2;                        \
    247 next_rect->y2 = ny2;                        \
    248 next_rect++;                                \
    249    }						    \
    250    while (0)
    251 
    252 #define NEWRECT(region, next_rect, nx1, ny1, nx2, ny2)			\
    253    do									\
    254    {									\
    255 if (!(region)->data ||						\
    256     ((region)->data->numRects == (region)->data->size))		\
    257 {								\
    258     if (!pixman_rect_alloc (region, 1))				\
    259 	return FALSE;						\
    260     next_rect = PIXREGION_TOP (region);				\
    261 }								\
    262 ADDRECT (next_rect, nx1, ny1, nx2, ny2);			\
    263 region->data->numRects++;					\
    264 critical_if_fail (region->data->numRects <= region->data->size);		\
    265    } while (0)
    266 
    267 #define DOWNSIZE(reg, numRects)						\
    268    do									\
    269    {									\
    270 if (((numRects) < ((reg)->data->size >> 1)) &&			\
    271     ((reg)->data->size > 50))					\
    272 {								\
    273     region_data_type_t * new_data;				\
    274     size_t data_size = PIXREGION_SZOF (numRects);		\
    275 								\
    276     if (!data_size)						\
    277     {								\
    278 	new_data = NULL;					\
    279     }								\
    280     else							\
    281     {								\
    282 	new_data = (region_data_type_t *)			\
    283 	    realloc ((reg)->data, data_size);			\
    284     }								\
    285 								\
    286     if (new_data)						\
    287     {								\
    288 	new_data->size = (numRects);				\
    289 	(reg)->data = new_data;					\
    290     }								\
    291 }								\
    292    } while (0)
    293 
    294 PIXMAN_EXPORT pixman_bool_t
    295 PREFIX (_equal) (const region_type_t *reg1, const region_type_t *reg2)
    296 {
    297    int i;
    298    box_type_t *rects1;
    299    box_type_t *rects2;
    300 
    301    if (reg1->extents.x1 != reg2->extents.x1)
    302 return FALSE;
    303    
    304    if (reg1->extents.x2 != reg2->extents.x2)
    305 return FALSE;
    306    
    307    if (reg1->extents.y1 != reg2->extents.y1)
    308 return FALSE;
    309    
    310    if (reg1->extents.y2 != reg2->extents.y2)
    311 return FALSE;
    312    
    313    if (PIXREGION_NUMRECTS (reg1) != PIXREGION_NUMRECTS (reg2))
    314 return FALSE;
    315 
    316    rects1 = PIXREGION_RECTS (reg1);
    317    rects2 = PIXREGION_RECTS (reg2);
    318    
    319    for (i = 0; i != PIXREGION_NUMRECTS (reg1); i++)
    320    {
    321 if (rects1[i].x1 != rects2[i].x1)
    322     return FALSE;
    323 
    324 if (rects1[i].x2 != rects2[i].x2)
    325     return FALSE;
    326 
    327 if (rects1[i].y1 != rects2[i].y1)
    328     return FALSE;
    329 
    330 if (rects1[i].y2 != rects2[i].y2)
    331     return FALSE;
    332    }
    333 
    334    return TRUE;
    335 }
    336 
    337 int
    338 PREFIX (_print) (region_type_t *rgn)
    339 {
    340    int num, size;
    341    int i;
    342    box_type_t * rects;
    343 
    344    num = PIXREGION_NUMRECTS (rgn);
    345    size = PIXREGION_SIZE (rgn);
    346    rects = PIXREGION_RECTS (rgn);
    347 
    348    fprintf (stderr, "num: %d size: %d\n", num, size);
    349    fprintf (stderr, "extents: "
    350 	     PRINT_SPECIFIER " "
    351 	     PRINT_SPECIFIER " "
    352 	     PRINT_SPECIFIER " "
    353 	     PRINT_SPECIFIER "\n",
    354             rgn->extents.x1,
    355      rgn->extents.y1,
    356      rgn->extents.x2,
    357      rgn->extents.y2);
    358    
    359    for (i = 0; i < num; i++)
    360    {
    361 fprintf (stderr, PRINT_SPECIFIER " "
    362 		 PRINT_SPECIFIER " "
    363 		 PRINT_SPECIFIER " "
    364 		 PRINT_SPECIFIER " \n",
    365          rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
    366    }
    367    
    368    fprintf (stderr, "\n");
    369 
    370    return(num);
    371 }
    372 
    373 
    374 PIXMAN_EXPORT void
    375 PREFIX (_init) (region_type_t *region)
    376 {
    377    region->extents = *pixman_region_empty_box;
    378    region->data = pixman_region_empty_data;
    379 }
    380 
    381 PIXMAN_EXPORT void
    382 PREFIX (_init_rect) (region_type_t *	region,
    383                     int		x,
    384 	     int		y,
    385 	     unsigned int	width,
    386 	     unsigned int	height)
    387 {
    388    region->extents.x1 = x;
    389    region->extents.y1 = y;
    390    region->extents.x2 = x + width;
    391    region->extents.y2 = y + height;
    392 
    393    if (!GOOD_RECT (&region->extents))
    394    {
    395        if (BAD_RECT (&region->extents))
    396            _pixman_log_error (FUNC, "Invalid rectangle passed");
    397        PREFIX (_init) (region);
    398        return;
    399    }
    400 
    401    region->data = NULL;
    402 }
    403 
    404 PIXMAN_EXPORT void
    405 PREFIX (_init_rectf) (region_type_t *	region,
    406                      double		x,
    407 	      double		y,
    408 	      double		width,
    409 	      double		height)
    410 {
    411    region->extents.x1 = x;
    412    region->extents.y1 = y;
    413    region->extents.x2 = x + width;
    414    region->extents.y2 = y + height;
    415 
    416    if (!GOOD_RECT (&region->extents))
    417    {
    418        if (BAD_RECT (&region->extents))
    419            _pixman_log_error (FUNC, "Invalid rectangle passed");
    420        PREFIX (_init) (region);
    421        return;
    422    }
    423 
    424    region->data = NULL;
    425 }
    426 
    427 PIXMAN_EXPORT void
    428 PREFIX (_init_with_extents) (region_type_t *region, const box_type_t *extents)
    429 {
    430    if (!GOOD_RECT (extents))
    431    {
    432        if (BAD_RECT (extents))
    433            _pixman_log_error (FUNC, "Invalid rectangle passed");
    434        PREFIX (_init) (region);
    435        return;
    436    }
    437    region->extents = *extents;
    438 
    439    region->data = NULL;
    440 }
    441 
    442 PIXMAN_EXPORT void
    443 PREFIX (_fini) (region_type_t *region)
    444 {
    445    GOOD (region);
    446    FREE_DATA (region);
    447 }
    448 
    449 PIXMAN_EXPORT int
    450 PREFIX (_n_rects) (const region_type_t *region)
    451 {
    452    return PIXREGION_NUMRECTS (region);
    453 }
    454 
    455 PIXMAN_EXPORT box_type_t *
    456 PREFIX (_rectangles) (const region_type_t *region,
    457                      int               *n_rects)
    458 {
    459    if (n_rects)
    460 *n_rects = PIXREGION_NUMRECTS (region);
    461 
    462    return PIXREGION_RECTS (region);
    463 }
    464 
    465 static pixman_bool_t
    466 pixman_break (region_type_t *region)
    467 {
    468    FREE_DATA (region);
    469 
    470    region->extents = *pixman_region_empty_box;
    471    region->data = pixman_broken_data;
    472 
    473    return FALSE;
    474 }
    475 
    476 static pixman_bool_t
    477 pixman_rect_alloc (region_type_t * region,
    478                   int             n)
    479 {
    480    region_data_type_t *data;
    481 
    482    if (!region->data)
    483    {
    484 n++;
    485 region->data = alloc_data (n);
    486 
    487 if (!region->data)
    488     return pixman_break (region);
    489 
    490 region->data->numRects = 1;
    491 *PIXREGION_BOXPTR (region) = region->extents;
    492    }
    493    else if (!region->data->size)
    494    {
    495 region->data = alloc_data (n);
    496 
    497 if (!region->data)
    498     return pixman_break (region);
    499 
    500 region->data->numRects = 0;
    501    }
    502    else
    503    {
    504 size_t data_size;
    505 
    506 if (n == 1)
    507 {
    508     n = region->data->numRects;
    509     if (n > 500) /* XXX pick numbers out of a hat */
    510 	n = 250;
    511 }
    512 
    513 n += region->data->numRects;
    514 data_size = PIXREGION_SZOF (n);
    515 
    516 if (!data_size)
    517 {
    518     data = NULL;
    519 }
    520 else
    521 {
    522     data = (region_data_type_t *)
    523 	realloc (region->data, PIXREGION_SZOF (n));
    524 }
    525 
    526 if (!data)
    527     return pixman_break (region);
    528 
    529 region->data = data;
    530    }
    531    
    532    region->data->size = n;
    533 
    534    return TRUE;
    535 }
    536 
    537 PIXMAN_EXPORT pixman_bool_t
    538 PREFIX (_copy) (region_type_t *dst, const region_type_t *src)
    539 {
    540    GOOD (dst);
    541    GOOD (src);
    542 
    543    if (dst == src)
    544 return TRUE;
    545    
    546    dst->extents = src->extents;
    547 
    548    if (!src->data || !src->data->size)
    549    {
    550 FREE_DATA (dst);
    551 dst->data = src->data;
    552 return TRUE;
    553    }
    554    
    555    if (!dst->data || (dst->data->size < src->data->numRects))
    556    {
    557 FREE_DATA (dst);
    558 
    559 dst->data = alloc_data (src->data->numRects);
    560 
    561 if (!dst->data)
    562     return pixman_break (dst);
    563 
    564 dst->data->size = src->data->numRects;
    565    }
    566 
    567    dst->data->numRects = src->data->numRects;
    568 
    569    memmove ((char *)PIXREGION_BOXPTR (dst), (char *)PIXREGION_BOXPTR (src),
    570             dst->data->numRects * sizeof(box_type_t));
    571 
    572    return TRUE;
    573 }
    574 
    575 /*======================================================================
    576 *	    Generic Region Operator
    577 *====================================================================*/
    578 
    579 /*-
    580 *-----------------------------------------------------------------------
    581 * pixman_coalesce --
    582 *	Attempt to merge the boxes in the current band with those in the
    583 *	previous one.  We are guaranteed that the current band extends to
    584 *      the end of the rects array.  Used only by pixman_op.
    585 *
    586 * Results:
    587 *	The new index for the previous band.
    588 *
    589 * Side Effects:
    590 *	If coalescing takes place:
    591 *	    - rectangles in the previous band will have their y2 fields
    592 *	      altered.
    593 *	    - region->data->numRects will be decreased.
    594 *
    595 *-----------------------------------------------------------------------
    596 */
    597 static inline int
    598 pixman_coalesce (region_type_t * region,      /* Region to coalesce		 */
    599 	 int             prev_start,  /* Index of start of previous band */
    600 	 int             cur_start)   /* Index of start of current band  */
    601 {
    602    box_type_t *prev_box;       /* Current box in previous band	     */
    603    box_type_t *cur_box;        /* Current box in current band       */
    604    int numRects;               /* Number rectangles in both bands   */
    605    primitive_t y2;             /* Bottom of current band	     */
    606 
    607    /*
    608     * Figure out how many rectangles are in the band.
    609     */
    610    numRects = cur_start - prev_start;
    611    critical_if_fail (numRects == region->data->numRects - cur_start);
    612 
    613    if (!numRects) return cur_start;
    614 
    615    /*
    616     * The bands may only be coalesced if the bottom of the previous
    617     * matches the top scanline of the current.
    618     */
    619    prev_box = PIXREGION_BOX (region, prev_start);
    620    cur_box = PIXREGION_BOX (region, cur_start);
    621    if (prev_box->y2 != cur_box->y1) return cur_start;
    622 
    623    /*
    624     * Make sure the bands have boxes in the same places. This
    625     * assumes that boxes have been added in such a way that they
    626     * cover the most area possible. I.e. two boxes in a band must
    627     * have some horizontal space between them.
    628     */
    629    y2 = cur_box->y2;
    630 
    631    do
    632    {
    633 if ((prev_box->x1 != cur_box->x1) || (prev_box->x2 != cur_box->x2))
    634     return (cur_start);
    635 
    636 prev_box++;
    637 cur_box++;
    638 numRects--;
    639    }
    640    while (numRects);
    641 
    642    /*
    643     * The bands may be merged, so set the bottom y of each box
    644     * in the previous band to the bottom y of the current band.
    645     */
    646    numRects = cur_start - prev_start;
    647    region->data->numRects -= numRects;
    648 
    649    do
    650    {
    651 prev_box--;
    652 prev_box->y2 = y2;
    653 numRects--;
    654    }
    655    while (numRects);
    656 
    657    return prev_start;
    658 }
    659 
    660 /* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
    661 
    662 #define COALESCE(new_reg, prev_band, cur_band)                          \
    663    do									\
    664    {									\
    665 if (cur_band - prev_band == new_reg->data->numRects - cur_band)	\
    666     prev_band = pixman_coalesce (new_reg, prev_band, cur_band);	\
    667 else								\
    668     prev_band = cur_band;					\
    669    } while (0)
    670 
    671 /*-
    672 *-----------------------------------------------------------------------
    673 * pixman_region_append_non_o --
    674 *	Handle a non-overlapping band for the union and subtract operations.
    675 *      Just adds the (top/bottom-clipped) rectangles into the region.
    676 *      Doesn't have to check for subsumption or anything.
    677 *
    678 * Results:
    679 *	None.
    680 *
    681 * Side Effects:
    682 *	region->data->numRects is incremented and the rectangles overwritten
    683 *	with the rectangles we're passed.
    684 *
    685 *-----------------------------------------------------------------------
    686 */
    687 static inline pixman_bool_t
    688 pixman_region_append_non_o (region_type_t * region,
    689 		    box_type_t *    r,
    690 		    box_type_t *    r_end,
    691 		    primitive_t     y1,
    692 		    primitive_t     y2)
    693 {
    694    box_type_t *next_rect;
    695    int new_rects;
    696 
    697    new_rects = r_end - r;
    698 
    699    critical_if_fail (y1 < y2);
    700    critical_if_fail (new_rects != 0);
    701 
    702    /* Make sure we have enough space for all rectangles to be added */
    703    RECTALLOC (region, new_rects);
    704    next_rect = PIXREGION_TOP (region);
    705    region->data->numRects += new_rects;
    706 
    707    do
    708    {
    709 critical_if_fail (r->x1 < r->x2);
    710 ADDRECT (next_rect, r->x1, y1, r->x2, y2);
    711 r++;
    712    }
    713    while (r != r_end);
    714 
    715    return TRUE;
    716 }
    717 
    718 #define FIND_BAND(r, r_band_end, r_end, ry1)			     \
    719    do								     \
    720    {								     \
    721 ry1 = r->y1;						     \
    722 r_band_end = r + 1;					     \
    723 while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) {   \
    724     r_band_end++;					     \
    725 }							     \
    726    } while (0)
    727 
    728 #define APPEND_REGIONS(new_reg, r, r_end)				\
    729    do									\
    730    {									\
    731 int new_rects;							\
    732 if ((new_rects = r_end - r)) {					\
    733     RECTALLOC_BAIL (new_reg, new_rects, bail);			\
    734     memmove ((char *)PIXREGION_TOP (new_reg), (char *)r,	\
    735 	     new_rects * sizeof(box_type_t));			\
    736     new_reg->data->numRects += new_rects;			\
    737 }								\
    738    } while (0)
    739 
    740 /*-
    741 *-----------------------------------------------------------------------
    742 * pixman_op --
    743 *	Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
    744 *	pixman_region_subtract, pixman_region_intersect....  Both regions MUST have at least one
    745 *      rectangle, and cannot be the same object.
    746 *
    747 * Results:
    748 *	TRUE if successful.
    749 *
    750 * Side Effects:
    751 *	The new region is overwritten.
    752 *	overlap set to TRUE if overlap_func ever returns TRUE.
    753 *
    754 * Notes:
    755 *	The idea behind this function is to view the two regions as sets.
    756 *	Together they cover a rectangle of area that this function divides
    757 *	into horizontal bands where points are covered only by one region
    758 *	or by both. For the first case, the non_overlap_func is called with
    759 *	each the band and the band's upper and lower extents. For the
    760 *	second, the overlap_func is called to process the entire band. It
    761 *	is responsible for clipping the rectangles in the band, though
    762 *	this function provides the boundaries.
    763 *	At the end of each band, the new region is coalesced, if possible,
    764 *	to reduce the number of rectangles in the region.
    765 *
    766 *-----------------------------------------------------------------------
    767 */
    768 
    769 typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region,
    770 				   box_type_t *   r1,
    771 				   box_type_t *   r1_end,
    772 				   box_type_t *   r2,
    773 				   box_type_t *   r2_end,
    774 				   primitive_t    y1,
    775 				   primitive_t    y2);
    776 
    777 static pixman_bool_t
    778 pixman_op (region_type_t *  new_reg,               /* Place to store result	    */
    779    const region_type_t *  reg1,                  /* First region in operation     */
    780    const region_type_t *  reg2,                  /* 2d region in operation        */
    781    overlap_proc_ptr overlap_func,          /* Function to call for over-
    782 					    * lapping bands		    */
    783    int              append_non1,           /* Append non-overlapping bands  
    784 					    * in region 1 ?
    785 					    */
    786    int              append_non2            /* Append non-overlapping bands
    787 					    * in region 2 ?
    788 					    */
    789    )
    790 {
    791    box_type_t *r1;                 /* Pointer into first region     */
    792    box_type_t *r2;                 /* Pointer into 2d region	     */
    793    box_type_t *r1_end;             /* End of 1st region	     */
    794    box_type_t *r2_end;             /* End of 2d region		     */
    795    primitive_t ybot;               /* Bottom of intersection	     */
    796    primitive_t ytop;               /* Top of intersection	     */
    797    region_data_type_t *old_data;   /* Old data for new_reg	     */
    798    int prev_band;                  /* Index of start of
    799 			     * previous band in new_reg       */
    800    int cur_band;                   /* Index of start of current
    801 			     * band in new_reg		     */
    802    box_type_t * r1_band_end;       /* End of current band in r1     */
    803    box_type_t * r2_band_end;       /* End of current band in r2     */
    804    primitive_t top;                /* Top of non-overlapping band   */
    805    primitive_t bot;                /* Bottom of non-overlapping band*/
    806    primitive_t r1y1;               /* Temps for r1->y1 and r2->y1   */
    807    primitive_t r2y1;
    808    int new_size;
    809    int numRects;
    810 
    811    /*
    812     * Break any region computed from a broken region
    813     */
    814    if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
    815 return pixman_break (new_reg);
    816 
    817    /*
    818     * Initialization:
    819     *	set r1, r2, r1_end and r2_end appropriately, save the rectangles
    820     * of the destination region until the end in case it's one of
    821     * the two source regions, then mark the "new" region empty, allocating
    822     * another array of rectangles for it to use.
    823     */
    824 
    825    r1 = PIXREGION_RECTS (reg1);
    826    new_size = PIXREGION_NUMRECTS (reg1);
    827    r1_end = r1 + new_size;
    828 
    829    numRects = PIXREGION_NUMRECTS (reg2);
    830    r2 = PIXREGION_RECTS (reg2);
    831    r2_end = r2 + numRects;
    832    
    833    critical_if_fail (r1 != r1_end);
    834    critical_if_fail (r2 != r2_end);
    835 
    836    old_data = (region_data_type_t *)NULL;
    837 
    838    if (((new_reg == reg1) && (new_size > 1)) ||
    839        ((new_reg == reg2) && (numRects > 1)))
    840    {
    841        old_data = new_reg->data;
    842        new_reg->data = pixman_region_empty_data;
    843    }
    844 
    845    /* guess at new size */
    846    if (numRects > new_size)
    847 new_size = numRects;
    848 
    849    new_size <<= 1;
    850 
    851    if (!new_reg->data)
    852 new_reg->data = pixman_region_empty_data;
    853    else if (new_reg->data->size)
    854 new_reg->data->numRects = 0;
    855 
    856    if (new_size > new_reg->data->size)
    857    {
    858        if (!pixman_rect_alloc (new_reg, new_size))
    859        {
    860            free (old_data);
    861            return FALSE;
    862 }
    863    }
    864 
    865    /*
    866     * Initialize ybot.
    867     * In the upcoming loop, ybot and ytop serve different functions depending
    868     * on whether the band being handled is an overlapping or non-overlapping
    869     * band.
    870     *  In the case of a non-overlapping band (only one of the regions
    871     * has points in the band), ybot is the bottom of the most recent
    872     * intersection and thus clips the top of the rectangles in that band.
    873     * ytop is the top of the next intersection between the two regions and
    874     * serves to clip the bottom of the rectangles in the current band.
    875     *	For an overlapping band (where the two regions intersect), ytop clips
    876     * the top of the rectangles of both regions and ybot clips the bottoms.
    877     */
    878 
    879    ybot = MIN (r1->y1, r2->y1);
    880 
    881    /*
    882     * prev_band serves to mark the start of the previous band so rectangles
    883     * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
    884     * In the beginning, there is no previous band, so prev_band == cur_band
    885     * (cur_band is set later on, of course, but the first band will always
    886     * start at index 0). prev_band and cur_band must be indices because of
    887     * the possible expansion, and resultant moving, of the new region's
    888     * array of rectangles.
    889     */
    890    prev_band = 0;
    891 
    892    do
    893    {
    894        /*
    895  * This algorithm proceeds one source-band (as opposed to a
    896  * destination band, which is determined by where the two regions
    897  * intersect) at a time. r1_band_end and r2_band_end serve to mark the
    898  * rectangle after the last one in the current band for their
    899  * respective regions.
    900  */
    901        critical_if_fail (r1 != r1_end);
    902        critical_if_fail (r2 != r2_end);
    903 
    904        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
    905        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
    906 
    907        /*
    908  * First handle the band that doesn't intersect, if any.
    909  *
    910  * Note that attention is restricted to one band in the
    911  * non-intersecting region at once, so if a region has n
    912  * bands between the current position and the next place it overlaps
    913  * the other, this entire loop will be passed through n times.
    914  */
    915        if (r1y1 < r2y1)
    916        {
    917            if (append_non1)
    918            {
    919                top = MAX (r1y1, ybot);
    920                bot = MIN (r1->y2, r2y1);
    921                if (top != bot)
    922                {
    923                    cur_band = new_reg->data->numRects;
    924                    if (!pixman_region_append_non_o (new_reg, r1, r1_band_end, top, bot))
    925 		goto bail;
    926                    COALESCE (new_reg, prev_band, cur_band);
    927 	}
    928     }
    929            ytop = r2y1;
    930 }
    931        else if (r2y1 < r1y1)
    932        {
    933            if (append_non2)
    934            {
    935                top = MAX (r2y1, ybot);
    936                bot = MIN (r2->y2, r1y1);
    937 	
    938                if (top != bot)
    939                {
    940                    cur_band = new_reg->data->numRects;
    941 
    942                    if (!pixman_region_append_non_o (new_reg, r2, r2_band_end, top, bot))
    943 		goto bail;
    944 
    945                    COALESCE (new_reg, prev_band, cur_band);
    946 	}
    947     }
    948            ytop = r1y1;
    949 }
    950        else
    951        {
    952            ytop = r1y1;
    953 }
    954 
    955        /*
    956  * Now see if we've hit an intersecting band. The two bands only
    957  * intersect if ybot > ytop
    958  */
    959        ybot = MIN (r1->y2, r2->y2);
    960        if (ybot > ytop)
    961        {
    962            cur_band = new_reg->data->numRects;
    963 
    964            if (!(*overlap_func)(new_reg,
    965                                 r1, r1_band_end,
    966                                 r2, r2_band_end,
    967                                 ytop, ybot))
    968     {
    969 	goto bail;
    970     }
    971     
    972            COALESCE (new_reg, prev_band, cur_band);
    973 }
    974 
    975        /*
    976  * If we've finished with a band (y2 == ybot) we skip forward
    977  * in the region to the next band.
    978  */
    979        if (r1->y2 == ybot)
    980     r1 = r1_band_end;
    981 
    982        if (r2->y2 == ybot)
    983     r2 = r2_band_end;
    984 
    985    }
    986    while (r1 != r1_end && r2 != r2_end);
    987 
    988    /*
    989     * Deal with whichever region (if any) still has rectangles left.
    990     *
    991     * We only need to worry about banding and coalescing for the very first
    992     * band left.  After that, we can just group all remaining boxes,
    993     * regardless of how many bands, into one final append to the list.
    994     */
    995 
    996    if ((r1 != r1_end) && append_non1)
    997    {
    998        /* Do first non_overlap1Func call, which may be able to coalesce */
    999        FIND_BAND (r1, r1_band_end, r1_end, r1y1);
   1000 
   1001        cur_band = new_reg->data->numRects;
   1002 
   1003        if (!pixman_region_append_non_o (new_reg,
   1004                                         r1, r1_band_end,
   1005                                         MAX (r1y1, ybot), r1->y2))
   1006 {
   1007     goto bail;
   1008 }
   1009 
   1010        COALESCE (new_reg, prev_band, cur_band);
   1011 
   1012        /* Just append the rest of the boxes  */
   1013        APPEND_REGIONS (new_reg, r1_band_end, r1_end);
   1014    }
   1015    else if ((r2 != r2_end) && append_non2)
   1016    {
   1017        /* Do first non_overlap2Func call, which may be able to coalesce */
   1018        FIND_BAND (r2, r2_band_end, r2_end, r2y1);
   1019 
   1020 cur_band = new_reg->data->numRects;
   1021 
   1022        if (!pixman_region_append_non_o (new_reg,
   1023                                         r2, r2_band_end,
   1024                                         MAX (r2y1, ybot), r2->y2))
   1025 {
   1026     goto bail;
   1027 }
   1028 
   1029        COALESCE (new_reg, prev_band, cur_band);
   1030 
   1031        /* Append rest of boxes */
   1032        APPEND_REGIONS (new_reg, r2_band_end, r2_end);
   1033    }
   1034 
   1035    free (old_data);
   1036 
   1037    if (!(numRects = new_reg->data->numRects))
   1038    {
   1039        FREE_DATA (new_reg);
   1040        new_reg->data = pixman_region_empty_data;
   1041    }
   1042    else if (numRects == 1)
   1043    {
   1044        new_reg->extents = *PIXREGION_BOXPTR (new_reg);
   1045        FREE_DATA (new_reg);
   1046        new_reg->data = (region_data_type_t *)NULL;
   1047    }
   1048    else
   1049    {
   1050        DOWNSIZE (new_reg, numRects);
   1051    }
   1052 
   1053    return TRUE;
   1054 
   1055 bail:
   1056    free (old_data);
   1057 
   1058    return pixman_break (new_reg);
   1059 }
   1060 
   1061 /*-
   1062 *-----------------------------------------------------------------------
   1063 * pixman_set_extents --
   1064 *	Reset the extents of a region to what they should be. Called by
   1065 *	pixman_region_subtract and pixman_region_intersect as they can't
   1066 *      figure it out along the way or do so easily, as pixman_region_union can.
   1067 *
   1068 * Results:
   1069 *	None.
   1070 *
   1071 * Side Effects:
   1072 *	The region's 'extents' structure is overwritten.
   1073 *
   1074 *-----------------------------------------------------------------------
   1075 */
   1076 static void
   1077 pixman_set_extents (region_type_t *region)
   1078 {
   1079    box_type_t *box, *box_end;
   1080 
   1081    if (!region->data)
   1082 return;
   1083 
   1084    if (!region->data->size)
   1085    {
   1086        region->extents.x2 = region->extents.x1;
   1087        region->extents.y2 = region->extents.y1;
   1088        return;
   1089    }
   1090 
   1091    box = PIXREGION_BOXPTR (region);
   1092    box_end = PIXREGION_END (region);
   1093 
   1094    /*
   1095     * Since box is the first rectangle in the region, it must have the
   1096     * smallest y1 and since box_end is the last rectangle in the region,
   1097     * it must have the largest y2, because of banding. Initialize x1 and
   1098     * x2 from  box and box_end, resp., as good things to initialize them
   1099     * to...
   1100     */
   1101    region->extents.x1 = box->x1;
   1102    region->extents.y1 = box->y1;
   1103    region->extents.x2 = box_end->x2;
   1104    region->extents.y2 = box_end->y2;
   1105 
   1106    critical_if_fail (region->extents.y1 < region->extents.y2);
   1107 
   1108    while (box <= box_end)
   1109    {
   1110        if (box->x1 < region->extents.x1)
   1111     region->extents.x1 = box->x1;
   1112        if (box->x2 > region->extents.x2)
   1113     region->extents.x2 = box->x2;
   1114        box++;
   1115    }
   1116 
   1117    critical_if_fail (region->extents.x1 < region->extents.x2);
   1118 }
   1119 
   1120 /*======================================================================
   1121 *	    Region Intersection
   1122 *====================================================================*/
   1123 /*-
   1124 *-----------------------------------------------------------------------
   1125 * pixman_region_intersect_o --
   1126 *	Handle an overlapping band for pixman_region_intersect.
   1127 *
   1128 * Results:
   1129 *	TRUE if successful.
   1130 *
   1131 * Side Effects:
   1132 *	Rectangles may be added to the region.
   1133 *
   1134 *-----------------------------------------------------------------------
   1135 */
   1136 /*ARGSUSED*/
   1137 static pixman_bool_t
   1138 pixman_region_intersect_o (region_type_t *region,
   1139                           box_type_t *   r1,
   1140                           box_type_t *   r1_end,
   1141                           box_type_t *   r2,
   1142                           box_type_t *   r2_end,
   1143                           primitive_t    y1,
   1144                           primitive_t    y2)
   1145 {
   1146    primitive_t x1;
   1147    primitive_t x2;
   1148    box_type_t *        next_rect;
   1149 
   1150    next_rect = PIXREGION_TOP (region);
   1151 
   1152    critical_if_fail (y1 < y2);
   1153    critical_if_fail (r1 != r1_end && r2 != r2_end);
   1154 
   1155    do
   1156    {
   1157        x1 = MAX (r1->x1, r2->x1);
   1158        x2 = MIN (r1->x2, r2->x2);
   1159 
   1160        /*
   1161  * If there's any overlap between the two rectangles, add that
   1162  * overlap to the new region.
   1163  */
   1164        if (x1 < x2)
   1165     NEWRECT (region, next_rect, x1, y1, x2, y2);
   1166 
   1167        /*
   1168  * Advance the pointer(s) with the leftmost right side, since the next
   1169  * rectangle on that list may still overlap the other region's
   1170  * current rectangle.
   1171  */
   1172        if (r1->x2 == x2)
   1173        {
   1174            r1++;
   1175 }
   1176        if (r2->x2 == x2)
   1177        {
   1178            r2++;
   1179 }
   1180    }
   1181    while ((r1 != r1_end) && (r2 != r2_end));
   1182 
   1183    return TRUE;
   1184 }
   1185 
   1186 PIXMAN_EXPORT pixman_bool_t
   1187 PREFIX (_intersect) (region_type_t *     new_reg,
   1188                     const region_type_t *        reg1,
   1189                     const region_type_t *        reg2)
   1190 {
   1191    GOOD (reg1);
   1192    GOOD (reg2);
   1193    GOOD (new_reg);
   1194 
   1195    /* check for trivial reject */
   1196    if (PIXREGION_NIL (reg1) || PIXREGION_NIL (reg2) ||
   1197        !EXTENTCHECK (&reg1->extents, &reg2->extents))
   1198    {
   1199        /* Covers about 20% of all cases */
   1200        FREE_DATA (new_reg);
   1201        new_reg->extents.x2 = new_reg->extents.x1;
   1202        new_reg->extents.y2 = new_reg->extents.y1;
   1203        if (PIXREGION_NAR (reg1) || PIXREGION_NAR (reg2))
   1204        {
   1205            new_reg->data = pixman_broken_data;
   1206            return FALSE;
   1207 }
   1208        else
   1209 {
   1210     new_reg->data = pixman_region_empty_data;
   1211 }
   1212    }
   1213    else if (!reg1->data && !reg2->data)
   1214    {
   1215        /* Covers about 80% of cases that aren't trivially rejected */
   1216        new_reg->extents.x1 = MAX (reg1->extents.x1, reg2->extents.x1);
   1217        new_reg->extents.y1 = MAX (reg1->extents.y1, reg2->extents.y1);
   1218        new_reg->extents.x2 = MIN (reg1->extents.x2, reg2->extents.x2);
   1219        new_reg->extents.y2 = MIN (reg1->extents.y2, reg2->extents.y2);
   1220 
   1221        FREE_DATA (new_reg);
   1222 
   1223 new_reg->data = (region_data_type_t *)NULL;
   1224    }
   1225    else if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
   1226    {
   1227        return PREFIX (_copy) (new_reg, reg1);
   1228    }
   1229    else if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
   1230    {
   1231        return PREFIX (_copy) (new_reg, reg2);
   1232    }
   1233    else if (reg1 == reg2)
   1234    {
   1235        return PREFIX (_copy) (new_reg, reg1);
   1236    }
   1237    else
   1238    {
   1239        /* General purpose intersection */
   1240 
   1241        if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE))
   1242     return FALSE;
   1243 
   1244        pixman_set_extents (new_reg);
   1245    }
   1246 
   1247    GOOD (new_reg);
   1248    return(TRUE);
   1249 }
   1250 
   1251 #define MERGERECT(r)							\
   1252    do									\
   1253    {									\
   1254        if (r->x1 <= x2)						\
   1255 {								\
   1256            /* Merge with current rectangle */				\
   1257            if (x2 < r->x2)						\
   1258 	x2 = r->x2;						\
   1259 }								\
   1260 else								\
   1261 {								\
   1262            /* Add current rectangle, start new one */			\
   1263            NEWRECT (region, next_rect, x1, y1, x2, y2);		\
   1264            x1 = r->x1;							\
   1265            x2 = r->x2;							\
   1266 }								\
   1267        r++;								\
   1268    } while (0)
   1269 
   1270 /*======================================================================
   1271 *	    Region Union
   1272 *====================================================================*/
   1273 
   1274 /*-
   1275 *-----------------------------------------------------------------------
   1276 * pixman_region_union_o --
   1277 *	Handle an overlapping band for the union operation. Picks the
   1278 *	left-most rectangle each time and merges it into the region.
   1279 *
   1280 * Results:
   1281 *	TRUE if successful.
   1282 *
   1283 * Side Effects:
   1284 *	region is overwritten.
   1285 *	overlap is set to TRUE if any boxes overlap.
   1286 *
   1287 *-----------------------------------------------------------------------
   1288 */
   1289 static pixman_bool_t
   1290 pixman_region_union_o (region_type_t *region,
   1291 	       box_type_t *   r1,
   1292 	       box_type_t *   r1_end,
   1293 	       box_type_t *   r2,
   1294 	       box_type_t *   r2_end,
   1295 	       primitive_t    y1,
   1296 	       primitive_t    y2)
   1297 {
   1298    box_type_t *next_rect;
   1299    primitive_t x1;    /* left and right side of current union */
   1300    primitive_t x2;
   1301 
   1302    critical_if_fail (y1 < y2);
   1303    critical_if_fail (r1 != r1_end && r2 != r2_end);
   1304 
   1305    next_rect = PIXREGION_TOP (region);
   1306 
   1307    /* Start off current rectangle */
   1308    if (r1->x1 < r2->x1)
   1309    {
   1310        x1 = r1->x1;
   1311        x2 = r1->x2;
   1312        r1++;
   1313    }
   1314    else
   1315    {
   1316        x1 = r2->x1;
   1317        x2 = r2->x2;
   1318        r2++;
   1319    }
   1320    while (r1 != r1_end && r2 != r2_end)
   1321    {
   1322        if (r1->x1 < r2->x1)
   1323     MERGERECT (r1);
   1324 else
   1325     MERGERECT (r2);
   1326    }
   1327 
   1328    /* Finish off whoever (if any) is left */
   1329    if (r1 != r1_end)
   1330    {
   1331        do
   1332        {
   1333            MERGERECT (r1);
   1334 }
   1335        while (r1 != r1_end);
   1336    }
   1337    else if (r2 != r2_end)
   1338    {
   1339        do
   1340        {
   1341            MERGERECT (r2);
   1342 }
   1343        while (r2 != r2_end);
   1344    }
   1345 
   1346    /* Add current rectangle */
   1347    NEWRECT (region, next_rect, x1, y1, x2, y2);
   1348 
   1349    return TRUE;
   1350 }
   1351 
   1352 PIXMAN_EXPORT pixman_bool_t
   1353 PREFIX(_intersect_rect) (region_type_t *dest,
   1354 		 const region_type_t *source,
   1355 		 int x, int y,
   1356 		 unsigned int width,
   1357 		 unsigned int height)
   1358 {
   1359    region_type_t region;
   1360 
   1361    region.data = NULL;
   1362    region.extents.x1 = x;
   1363    region.extents.y1 = y;
   1364    region.extents.x2 = x + width;
   1365    region.extents.y2 = y + height;
   1366 
   1367    return PREFIX(_intersect) (dest, source, &region);
   1368 }
   1369 
   1370 PIXMAN_EXPORT pixman_bool_t
   1371 PREFIX(_intersect_rectf) (region_type_t *dest,
   1372 		  const region_type_t *source,
   1373 		  double x, double y,
   1374 		  double width,
   1375 		  double height)
   1376 {
   1377    region_type_t region;
   1378 
   1379    region.data = NULL;
   1380    region.extents.x1 = x;
   1381    region.extents.y1 = y;
   1382    region.extents.x2 = x + width;
   1383    region.extents.y2 = y + height;
   1384 
   1385    return PREFIX(_intersect) (dest, source, &region);
   1386 }
   1387 
   1388 /* Convenience function for performing union of region with a
   1389 * single rectangle
   1390 */
   1391 PIXMAN_EXPORT pixman_bool_t
   1392 PREFIX (_union_rect) (region_type_t *dest,
   1393                      const region_type_t *source,
   1394                      int            x,
   1395 	      int            y,
   1396                      unsigned int   width,
   1397 	      unsigned int   height)
   1398 {
   1399    region_type_t region;
   1400 
   1401    region.extents.x1 = x;
   1402    region.extents.y1 = y;
   1403    region.extents.x2 = x + width;
   1404    region.extents.y2 = y + height;
   1405 
   1406    if (!GOOD_RECT (&region.extents))
   1407    {
   1408        if (BAD_RECT (&region.extents))
   1409            _pixman_log_error (FUNC, "Invalid rectangle passed");
   1410 return PREFIX (_copy) (dest, source);
   1411    }
   1412 
   1413    region.data = NULL;
   1414 
   1415    return PREFIX (_union) (dest, source, &region);
   1416 }
   1417 
   1418 PIXMAN_EXPORT pixman_bool_t
   1419 PREFIX (_union_rectf) (region_type_t *dest,
   1420                       const region_type_t *source,
   1421                       double         x,
   1422 	       double         y,
   1423                       double         width,
   1424 	       double         height)
   1425 {
   1426    region_type_t region;
   1427 
   1428    region.extents.x1 = x;
   1429    region.extents.y1 = y;
   1430    region.extents.x2 = x + width;
   1431    region.extents.y2 = y + height;
   1432 
   1433    if (!GOOD_RECT (&region.extents))
   1434    {
   1435        if (BAD_RECT (&region.extents))
   1436            _pixman_log_error (FUNC, "Invalid rectangle passed");
   1437 return PREFIX (_copy) (dest, source);
   1438    }
   1439 
   1440    region.data = NULL;
   1441 
   1442    return PREFIX (_union) (dest, source, &region);
   1443 }
   1444 
   1445 PIXMAN_EXPORT pixman_bool_t
   1446 PREFIX (_union) (region_type_t *      new_reg,
   1447                 const region_type_t *reg1,
   1448                 const region_type_t *reg2)
   1449 {
   1450    /* Return TRUE if some overlap
   1451     * between reg1, reg2
   1452     */
   1453    GOOD (reg1);
   1454    GOOD (reg2);
   1455    GOOD (new_reg);
   1456 
   1457    /*  checks all the simple cases */
   1458 
   1459    /*
   1460     * Region 1 and 2 are the same
   1461     */
   1462    if (reg1 == reg2)
   1463        return PREFIX (_copy) (new_reg, reg1);
   1464 
   1465    /*
   1466     * Region 1 is empty
   1467     */
   1468    if (PIXREGION_NIL (reg1))
   1469    {
   1470        if (PIXREGION_NAR (reg1))
   1471     return pixman_break (new_reg);
   1472 
   1473        if (new_reg != reg2)
   1474     return PREFIX (_copy) (new_reg, reg2);
   1475 
   1476 return TRUE;
   1477    }
   1478 
   1479    /*
   1480     * Region 2 is empty
   1481     */
   1482    if (PIXREGION_NIL (reg2))
   1483    {
   1484        if (PIXREGION_NAR (reg2))
   1485     return pixman_break (new_reg);
   1486 
   1487 if (new_reg != reg1)
   1488     return PREFIX (_copy) (new_reg, reg1);
   1489 
   1490 return TRUE;
   1491    }
   1492 
   1493    /*
   1494     * Region 1 completely subsumes region 2
   1495     */
   1496    if (!reg1->data && SUBSUMES (&reg1->extents, &reg2->extents))
   1497    {
   1498        if (new_reg != reg1)
   1499     return PREFIX (_copy) (new_reg, reg1);
   1500 
   1501 return TRUE;
   1502    }
   1503 
   1504    /*
   1505     * Region 2 completely subsumes region 1
   1506     */
   1507    if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
   1508    {
   1509        if (new_reg != reg2)
   1510     return PREFIX (_copy) (new_reg, reg2);
   1511 
   1512 return TRUE;
   1513    }
   1514 
   1515    if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
   1516 return FALSE;
   1517 
   1518    new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
   1519    new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
   1520    new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
   1521    new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
   1522    
   1523    GOOD (new_reg);
   1524 
   1525    return TRUE;
   1526 }
   1527 
   1528 /*======================================================================
   1529 *	    Batch Rectangle Union
   1530 *====================================================================*/
   1531 
   1532 #define EXCHANGE_RECTS(a, b)	\
   1533    {                           \
   1534        box_type_t t;		\
   1535        t = rects[a];           \
   1536        rects[a] = rects[b];    \
   1537        rects[b] = t;           \
   1538    }
   1539 
   1540 static void
   1541 quick_sort_rects (
   1542    box_type_t rects[],
   1543    int        numRects)
   1544 {
   1545    primitive_t y1;
   1546    primitive_t x1;
   1547    int i, j;
   1548    box_type_t *r;
   1549 
   1550    /* Always called with numRects > 1 */
   1551 
   1552    do
   1553    {
   1554        if (numRects == 2)
   1555        {
   1556            if (rects[0].y1 > rects[1].y1 ||
   1557                (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
   1558     {
   1559 	EXCHANGE_RECTS (0, 1);
   1560     }
   1561 
   1562            return;
   1563 }
   1564 
   1565        /* Choose partition element, stick in location 0 */
   1566        EXCHANGE_RECTS (0, numRects >> 1);
   1567        y1 = rects[0].y1;
   1568        x1 = rects[0].x1;
   1569 
   1570        /* Partition array */
   1571        i = 0;
   1572        j = numRects;
   1573 
   1574        do
   1575        {
   1576            r = &(rects[i]);
   1577            do
   1578            {
   1579                r++;
   1580                i++;
   1581     }
   1582     while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
   1583 
   1584     r = &(rects[j]);
   1585            do
   1586            {
   1587                r--;
   1588                j--;
   1589     }
   1590            while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
   1591     
   1592            if (i < j)
   1593 	EXCHANGE_RECTS (i, j);
   1594 }
   1595        while (i < j);
   1596 
   1597        /* Move partition element back to middle */
   1598        EXCHANGE_RECTS (0, j);
   1599 
   1600        /* Recurse */
   1601        if (numRects - j - 1 > 1)
   1602     quick_sort_rects (&rects[j + 1], numRects - j - 1);
   1603 
   1604        numRects = j;
   1605    }
   1606    while (numRects > 1);
   1607 }
   1608 
   1609 /*-
   1610 *-----------------------------------------------------------------------
   1611 * pixman_region_validate --
   1612 *
   1613 *      Take a ``region'' which is a non-y-x-banded random collection of
   1614 *      rectangles, and compute a nice region which is the union of all the
   1615 *      rectangles.
   1616 *
   1617 * Results:
   1618 *	TRUE if successful.
   1619 *
   1620 * Side Effects:
   1621 *      The passed-in ``region'' may be modified.
   1622 *	overlap set to TRUE if any retangles overlapped,
   1623 *      else FALSE;
   1624 *
   1625 * Strategy:
   1626 *      Step 1. Sort the rectangles into ascending order with primary key y1
   1627 *		and secondary key x1.
   1628 *
   1629 *      Step 2. Split the rectangles into the minimum number of proper y-x
   1630 *		banded regions.  This may require horizontally merging
   1631 *		rectangles, and vertically coalescing bands.  With any luck,
   1632 *		this step in an identity transformation (ala the Box widget),
   1633 *		or a coalescing into 1 box (ala Menus).
   1634 *
   1635 *	Step 3. Merge the separate regions down to a single region by calling
   1636 *		pixman_region_union.  Maximize the work each pixman_region_union call does by using
   1637 *		a binary merge.
   1638 *
   1639 *-----------------------------------------------------------------------
   1640 */
   1641 
   1642 static pixman_bool_t
   1643 validate (region_type_t * badreg)
   1644 {
   1645    /* Descriptor for regions under construction  in Step 2. */
   1646    typedef struct
   1647    {
   1648        region_type_t reg;
   1649        int prev_band;
   1650        int cur_band;
   1651    } region_info_t;
   1652 
   1653    region_info_t stack_regions[64];
   1654 
   1655    int numRects;                   /* Original numRects for badreg	    */
   1656    region_info_t *ri;              /* Array of current regions		    */
   1657    int num_ri;                     /* Number of entries used in ri	    */
   1658    int size_ri;                    /* Number of entries available in ri    */
   1659    int i;                          /* Index into rects			    */
   1660    int j;                          /* Index into ri			    */
   1661    region_info_t *rit;             /* &ri[j]				    */
   1662    region_type_t *reg;             /* ri[j].reg			    */
   1663    box_type_t *box;                /* Current box in rects		    */
   1664    box_type_t *ri_box;             /* Last box in ri[j].reg		    */
   1665    region_type_t *hreg;            /* ri[j_half].reg			    */
   1666    pixman_bool_t ret = TRUE;
   1667 
   1668    if (!badreg->data)
   1669    {
   1670        GOOD (badreg);
   1671        return TRUE;
   1672    }
   1673    
   1674    numRects = badreg->data->numRects;
   1675    if (!numRects)
   1676    {
   1677        if (PIXREGION_NAR (badreg))
   1678     return FALSE;
   1679        GOOD (badreg);
   1680        return TRUE;
   1681    }
   1682    
   1683    if (badreg->extents.x1 < badreg->extents.x2)
   1684    {
   1685        if ((numRects) == 1)
   1686        {
   1687            FREE_DATA (badreg);
   1688            badreg->data = (region_data_type_t *) NULL;
   1689 }
   1690        else
   1691        {
   1692            DOWNSIZE (badreg, numRects);
   1693 }
   1694 
   1695        GOOD (badreg);
   1696 
   1697 return TRUE;
   1698    }
   1699 
   1700    /* Step 1: Sort the rects array into ascending (y1, x1) order */
   1701    quick_sort_rects (PIXREGION_BOXPTR (badreg), numRects);
   1702 
   1703    /* Step 2: Scatter the sorted array into the minimum number of regions */
   1704 
   1705    /* Set up the first region to be the first rectangle in badreg */
   1706    /* Note that step 2 code will never overflow the ri[0].reg rects array */
   1707    ri = stack_regions;
   1708    size_ri = sizeof (stack_regions) / sizeof (stack_regions[0]);
   1709    num_ri = 1;
   1710    ri[0].prev_band = 0;
   1711    ri[0].cur_band = 0;
   1712    ri[0].reg = *badreg;
   1713    box = PIXREGION_BOXPTR (&ri[0].reg);
   1714    ri[0].reg.extents = *box;
   1715    ri[0].reg.data->numRects = 1;
   1716    badreg->extents = *pixman_region_empty_box;
   1717    badreg->data = pixman_region_empty_data;
   1718 
   1719    /* Now scatter rectangles into the minimum set of valid regions.  If the
   1720     * next rectangle to be added to a region would force an existing rectangle
   1721     * in the region to be split up in order to maintain y-x banding, just
   1722     * forget it.  Try the next region.  If it doesn't fit cleanly into any
   1723     * region, make a new one.
   1724     */
   1725 
   1726    for (i = numRects; --i > 0;)
   1727    {
   1728        box++;
   1729        /* Look for a region to append box to */
   1730        for (j = num_ri, rit = ri; --j >= 0; rit++)
   1731        {
   1732            reg = &rit->reg;
   1733            ri_box = PIXREGION_END (reg);
   1734 
   1735            if (box->y1 == ri_box->y1 && box->y2 == ri_box->y2)
   1736            {
   1737                /* box is in same band as ri_box.  Merge or append it */
   1738                if (box->x1 <= ri_box->x2)
   1739                {
   1740                    /* Merge it with ri_box */
   1741                    if (box->x2 > ri_box->x2)
   1742 		ri_box->x2 = box->x2;
   1743 	}
   1744                else
   1745                {
   1746                    RECTALLOC_BAIL (reg, 1, bail);
   1747                    *PIXREGION_TOP (reg) = *box;
   1748                    reg->data->numRects++;
   1749 	}
   1750 	
   1751                goto next_rect;   /* So sue me */
   1752     }
   1753            else if (box->y1 >= ri_box->y2)
   1754            {
   1755                /* Put box into new band */
   1756                if (reg->extents.x2 < ri_box->x2)
   1757 	    reg->extents.x2 = ri_box->x2;
   1758 	
   1759                if (reg->extents.x1 > box->x1)
   1760 	    reg->extents.x1 = box->x1;
   1761 	
   1762                COALESCE (reg, rit->prev_band, rit->cur_band);
   1763                rit->cur_band = reg->data->numRects;
   1764                RECTALLOC_BAIL (reg, 1, bail);
   1765                *PIXREGION_TOP (reg) = *box;
   1766                reg->data->numRects++;
   1767 
   1768                goto next_rect;
   1769     }
   1770            /* Well, this region was inappropriate.  Try the next one. */
   1771 } /* for j */
   1772 
   1773        /* Uh-oh.  No regions were appropriate.  Create a new one. */
   1774        if (size_ri == num_ri)
   1775        {
   1776            size_t data_size;
   1777 
   1778            /* Oops, allocate space for new region information */
   1779            size_ri <<= 1;
   1780 
   1781            data_size = size_ri * sizeof(region_info_t);
   1782            if (data_size / size_ri != sizeof(region_info_t))
   1783 	goto bail;
   1784 
   1785            if (ri == stack_regions)
   1786            {
   1787                rit = malloc (data_size);
   1788                if (!rit)
   1789 	    goto bail;
   1790                memcpy (rit, ri, num_ri * sizeof (region_info_t));
   1791     }
   1792            else
   1793            {
   1794                rit = (region_info_t *) realloc (ri, data_size);
   1795                if (!rit)
   1796 	    goto bail;
   1797     }
   1798            ri = rit;
   1799            rit = &ri[num_ri];
   1800 }
   1801        num_ri++;
   1802        rit->prev_band = 0;
   1803        rit->cur_band = 0;
   1804        rit->reg.extents = *box;
   1805        rit->reg.data = (region_data_type_t *)NULL;
   1806 
   1807 /* MUST force allocation */
   1808        if (!pixman_rect_alloc (&rit->reg, (i + num_ri) / num_ri))
   1809     goto bail;
   1810 
   1811    next_rect: ;
   1812    } /* for i */
   1813 
   1814    /* Make a final pass over each region in order to COALESCE and set
   1815     * extents.x2 and extents.y2
   1816     */
   1817    for (j = num_ri, rit = ri; --j >= 0; rit++)
   1818    {
   1819        reg = &rit->reg;
   1820        ri_box = PIXREGION_END (reg);
   1821        reg->extents.y2 = ri_box->y2;
   1822 
   1823        if (reg->extents.x2 < ri_box->x2)
   1824     reg->extents.x2 = ri_box->x2;
   1825 
   1826        COALESCE (reg, rit->prev_band, rit->cur_band);
   1827 
   1828 if (reg->data->numRects == 1) /* keep unions happy below */
   1829        {
   1830            FREE_DATA (reg);
   1831            reg->data = (region_data_type_t *)NULL;
   1832 }
   1833    }
   1834 
   1835    /* Step 3: Union all regions into a single region */
   1836    while (num_ri > 1)
   1837    {
   1838        int half = num_ri / 2;
   1839        for (j = num_ri & 1; j < (half + (num_ri & 1)); j++)
   1840        {
   1841            reg = &ri[j].reg;
   1842            hreg = &ri[j + half].reg;
   1843 
   1844            if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE))
   1845 	ret = FALSE;
   1846 
   1847            if (hreg->extents.x1 < reg->extents.x1)
   1848 	reg->extents.x1 = hreg->extents.x1;
   1849 
   1850            if (hreg->extents.y1 < reg->extents.y1)
   1851 	reg->extents.y1 = hreg->extents.y1;
   1852 
   1853            if (hreg->extents.x2 > reg->extents.x2)
   1854 	reg->extents.x2 = hreg->extents.x2;
   1855 
   1856            if (hreg->extents.y2 > reg->extents.y2)
   1857 	reg->extents.y2 = hreg->extents.y2;
   1858 
   1859            FREE_DATA (hreg);
   1860 }
   1861 
   1862        num_ri -= half;
   1863 
   1864 if (!ret)
   1865     goto bail;
   1866    }
   1867 
   1868    *badreg = ri[0].reg;
   1869 
   1870    if (ri != stack_regions)
   1871 free (ri);
   1872 
   1873    GOOD (badreg);
   1874    return ret;
   1875 
   1876 bail:
   1877    for (i = 0; i < num_ri; i++)
   1878 FREE_DATA (&ri[i].reg);
   1879 
   1880    if (ri != stack_regions)
   1881 free (ri);
   1882 
   1883    return pixman_break (badreg);
   1884 }
   1885 
   1886 /*======================================================================
   1887 *                Region Subtraction
   1888 *====================================================================*/
   1889 
   1890 /*-
   1891 *-----------------------------------------------------------------------
   1892 * pixman_region_subtract_o --
   1893 *	Overlapping band subtraction. x1 is the left-most point not yet
   1894 *	checked.
   1895 *
   1896 * Results:
   1897 *	TRUE if successful.
   1898 *
   1899 * Side Effects:
   1900 *	region may have rectangles added to it.
   1901 *
   1902 *-----------------------------------------------------------------------
   1903 */
   1904 /*ARGSUSED*/
   1905 static pixman_bool_t
   1906 pixman_region_subtract_o (region_type_t * region,
   1907 		  box_type_t *    r1,
   1908 		  box_type_t *    r1_end,
   1909 		  box_type_t *    r2,
   1910 		  box_type_t *    r2_end,
   1911 		  primitive_t     y1,
   1912 		  primitive_t     y2)
   1913 {
   1914    box_type_t *        next_rect;
   1915    primitive_t x1;
   1916 
   1917    x1 = r1->x1;
   1918 
   1919    critical_if_fail (y1 < y2);
   1920    critical_if_fail (r1 != r1_end && r2 != r2_end);
   1921 
   1922    next_rect = PIXREGION_TOP (region);
   1923 
   1924    do
   1925    {
   1926        if (r2->x2 <= x1)
   1927        {
   1928            /*
   1929      * Subtrahend entirely to left of minuend: go to next subtrahend.
   1930      */
   1931            r2++;
   1932 }
   1933        else if (r2->x1 <= x1)
   1934        {
   1935            /*
   1936      * Subtrahend precedes minuend: nuke left edge of minuend.
   1937      */
   1938            x1 = r2->x2;
   1939            if (x1 >= r1->x2)
   1940            {
   1941                /*
   1942 	 * Minuend completely covered: advance to next minuend and
   1943 	 * reset left fence to edge of new minuend.
   1944 	 */
   1945                r1++;
   1946                if (r1 != r1_end)
   1947 	    x1 = r1->x1;
   1948     }
   1949            else
   1950            {
   1951                /*
   1952 	 * Subtrahend now used up since it doesn't extend beyond
   1953 	 * minuend
   1954 	 */
   1955                r2++;
   1956     }
   1957 }
   1958        else if (r2->x1 < r1->x2)
   1959        {
   1960            /*
   1961      * Left part of subtrahend covers part of minuend: add uncovered
   1962      * part of minuend to region and skip to next subtrahend.
   1963      */
   1964            critical_if_fail (x1 < r2->x1);
   1965            NEWRECT (region, next_rect, x1, y1, r2->x1, y2);
   1966 
   1967            x1 = r2->x2;
   1968            if (x1 >= r1->x2)
   1969            {
   1970                /*
   1971 	 * Minuend used up: advance to new...
   1972 	 */
   1973                r1++;
   1974                if (r1 != r1_end)
   1975 	    x1 = r1->x1;
   1976     }
   1977            else
   1978            {
   1979                /*
   1980 	 * Subtrahend used up
   1981 	 */
   1982                r2++;
   1983     }
   1984 }
   1985        else
   1986        {
   1987            /*
   1988      * Minuend used up: add any remaining piece before advancing.
   1989      */
   1990            if (r1->x2 > x1)
   1991 	NEWRECT (region, next_rect, x1, y1, r1->x2, y2);
   1992 
   1993            r1++;
   1994 
   1995     if (r1 != r1_end)
   1996 	x1 = r1->x1;
   1997 }
   1998    }
   1999    while ((r1 != r1_end) && (r2 != r2_end));
   2000 
   2001    /*
   2002     * Add remaining minuend rectangles to region.
   2003     */
   2004    while (r1 != r1_end)
   2005    {
   2006        critical_if_fail (x1 < r1->x2);
   2007 
   2008        NEWRECT (region, next_rect, x1, y1, r1->x2, y2);
   2009 
   2010        r1++;
   2011        if (r1 != r1_end)
   2012     x1 = r1->x1;
   2013    }
   2014    return TRUE;
   2015 }
   2016 
   2017 /*-
   2018 *-----------------------------------------------------------------------
   2019 * pixman_region_subtract --
   2020 *	Subtract reg_s from reg_m and leave the result in reg_d.
   2021 *	S stands for subtrahend, M for minuend and D for difference.
   2022 *
   2023 * Results:
   2024 *	TRUE if successful.
   2025 *
   2026 * Side Effects:
   2027 *	reg_d is overwritten.
   2028 *
   2029 *-----------------------------------------------------------------------
   2030 */
   2031 PIXMAN_EXPORT pixman_bool_t
   2032 PREFIX (_subtract) (region_type_t *      reg_d,
   2033                    const region_type_t *reg_m,
   2034                    const region_type_t *reg_s)
   2035 {
   2036    GOOD (reg_m);
   2037    GOOD (reg_s);
   2038    GOOD (reg_d);
   2039    
   2040    /* check for trivial rejects */
   2041    if (PIXREGION_NIL (reg_m) || PIXREGION_NIL (reg_s) ||
   2042        !EXTENTCHECK (&reg_m->extents, &reg_s->extents))
   2043    {
   2044        if (PIXREGION_NAR (reg_s))
   2045     return pixman_break (reg_d);
   2046 
   2047        return PREFIX (_copy) (reg_d, reg_m);
   2048    }
   2049    else if (reg_m == reg_s)
   2050    {
   2051        FREE_DATA (reg_d);
   2052        reg_d->extents.x2 = reg_d->extents.x1;
   2053        reg_d->extents.y2 = reg_d->extents.y1;
   2054        reg_d->data = pixman_region_empty_data;
   2055 
   2056        return TRUE;
   2057    }
   2058 
   2059    /* Add those rectangles in region 1 that aren't in region 2,
   2060       do yucky subtraction for overlaps, and
   2061       just throw away rectangles in region 2 that aren't in region 1 */
   2062    if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE))
   2063 return FALSE;
   2064 
   2065    /*
   2066     * Can't alter reg_d's extents before we call pixman_op because
   2067     * it might be one of the source regions and pixman_op depends
   2068     * on the extents of those regions being unaltered. Besides, this
   2069     * way there's no checking against rectangles that will be nuked
   2070     * due to coalescing, so we have to examine fewer rectangles.
   2071     */
   2072    pixman_set_extents (reg_d);
   2073    GOOD (reg_d);
   2074    return TRUE;
   2075 }
   2076 
   2077 /*======================================================================
   2078 *	    Region Inversion
   2079 *====================================================================*/
   2080 
   2081 /*-
   2082 *-----------------------------------------------------------------------
   2083 * pixman_region_inverse --
   2084 *	Take a region and a box and return a region that is everything
   2085 *	in the box but not in the region. The careful reader will note
   2086 *	that this is the same as subtracting the region from the box...
   2087 *
   2088 * Results:
   2089 *	TRUE.
   2090 *
   2091 * Side Effects:
   2092 *	new_reg is overwritten.
   2093 *
   2094 *-----------------------------------------------------------------------
   2095 */
   2096 PIXMAN_EXPORT pixman_bool_t
   2097 PREFIX (_inverse) (region_type_t *      new_reg,  /* Destination region */
   2098 	   const region_type_t *reg1,     /* Region to invert */
   2099 	   const box_type_t *   inv_rect) /* Bounding box for inversion */
   2100 {
   2101    region_type_t inv_reg; /* Quick and dirty region made from the
   2102 		    * bounding box */
   2103    GOOD (reg1);
   2104    GOOD (new_reg);
   2105    
   2106    /* check for trivial rejects */
   2107    if (PIXREGION_NIL (reg1) || !EXTENTCHECK (inv_rect, &reg1->extents))
   2108    {
   2109        if (PIXREGION_NAR (reg1))
   2110     return pixman_break (new_reg);
   2111 
   2112        new_reg->extents = *inv_rect;
   2113        FREE_DATA (new_reg);
   2114        new_reg->data = (region_data_type_t *)NULL;
   2115 
   2116        return TRUE;
   2117    }
   2118 
   2119    /* Add those rectangles in region 1 that aren't in region 2,
   2120     * do yucky subtraction for overlaps, and
   2121     * just throw away rectangles in region 2 that aren't in region 1
   2122     */
   2123    inv_reg.extents = *inv_rect;
   2124    inv_reg.data = (region_data_type_t *)NULL;
   2125    if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE))
   2126 return FALSE;
   2127 
   2128    /*
   2129     * Can't alter new_reg's extents before we call pixman_op because
   2130     * it might be one of the source regions and pixman_op depends
   2131     * on the extents of those regions being unaltered. Besides, this
   2132     * way there's no checking against rectangles that will be nuked
   2133     * due to coalescing, so we have to examine fewer rectangles.
   2134     */
   2135    pixman_set_extents (new_reg);
   2136    GOOD (new_reg);
   2137    return TRUE;
   2138 }
   2139 
   2140 /* In time O(log n), locate the first box whose y2 is greater than y.
   2141 * Return @end if no such box exists.
   2142 */
   2143 static box_type_t *
   2144 find_box_for_y (box_type_t *begin, box_type_t *end, primitive_t y)
   2145 {
   2146    box_type_t *mid;
   2147 
   2148    if (end == begin)
   2149 return end;
   2150 
   2151    if (end - begin == 1)
   2152    {
   2153 if (begin->y2 > y)
   2154     return begin;
   2155 else
   2156     return end;
   2157    }
   2158 
   2159    mid = begin + (end - begin) / 2;
   2160    if (mid->y2 > y)
   2161    {
   2162 /* If no box is found in [begin, mid], the function
   2163  * will return @mid, which is then known to be the
   2164  * correct answer.
   2165  */
   2166 return find_box_for_y (begin, mid, y);
   2167    }
   2168    else
   2169    {
   2170 return find_box_for_y (mid, end, y);
   2171    }
   2172 }
   2173 
   2174 /*
   2175 *   rect_in(region, rect)
   2176 *   This routine takes a pointer to a region and a pointer to a box
   2177 *   and determines if the box is outside/inside/partly inside the region.
   2178 *
   2179 *   The idea is to travel through the list of rectangles trying to cover the
   2180 *   passed box with them. Anytime a piece of the rectangle isn't covered
   2181 *   by a band of rectangles, part_out is set TRUE. Any time a rectangle in
   2182 *   the region covers part of the box, part_in is set TRUE. The process ends
   2183 *   when either the box has been completely covered (we reached a band that
   2184 *   doesn't overlap the box, part_in is TRUE and part_out is false), the
   2185 *   box has been partially covered (part_in == part_out == TRUE -- because of
   2186 *   the banding, the first time this is true we know the box is only
   2187 *   partially in the region) or is outside the region (we reached a band
   2188 *   that doesn't overlap the box at all and part_in is false)
   2189 */
   2190 PIXMAN_EXPORT pixman_region_overlap_t
   2191 PREFIX (_contains_rectangle) (const region_type_t *  region,
   2192 		      const box_type_t *     prect)
   2193 {
   2194    box_type_t *     pbox;
   2195    box_type_t *     pbox_end;
   2196    int part_in, part_out;
   2197    int numRects;
   2198    primitive_t x, y;
   2199 
   2200    GOOD (region);
   2201 
   2202    numRects = PIXREGION_NUMRECTS (region);
   2203 
   2204    /* useful optimization */
   2205    if (!numRects || !EXTENTCHECK (&region->extents, prect))
   2206 return(PIXMAN_REGION_OUT);
   2207 
   2208    if (numRects == 1)
   2209    {
   2210        /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
   2211        if (SUBSUMES (&region->extents, prect))
   2212     return(PIXMAN_REGION_IN);
   2213        else
   2214     return(PIXMAN_REGION_PART);
   2215    }
   2216 
   2217    part_out = FALSE;
   2218    part_in = FALSE;
   2219 
   2220    /* (x,y) starts at upper left of rect, moving to the right and down */
   2221    x = prect->x1;
   2222    y = prect->y1;
   2223 
   2224    /* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
   2225    for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
   2226  pbox != pbox_end;
   2227  pbox++)
   2228    {
   2229 /* getting up to speed or skipping remainder of band */
   2230 if (pbox->y2 <= y)
   2231 {
   2232     if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end)
   2233 	break;
   2234 }
   2235 
   2236        if (pbox->y1 > y)
   2237        {
   2238            part_out = TRUE;     /* missed part of rectangle above */
   2239            if (part_in || (pbox->y1 >= prect->y2))
   2240 	break;
   2241            y = pbox->y1;       /* x guaranteed to be == prect->x1 */
   2242 }
   2243 
   2244        if (pbox->x2 <= x)
   2245     continue;           /* not far enough over yet */
   2246 
   2247        if (pbox->x1 > x)
   2248        {
   2249            part_out = TRUE;     /* missed part of rectangle to left */
   2250            if (part_in)
   2251 	break;
   2252 }
   2253 
   2254        if (pbox->x1 < prect->x2)
   2255        {
   2256            part_in = TRUE;      /* definitely overlap */
   2257            if (part_out)
   2258 	break;
   2259 }
   2260 
   2261        if (pbox->x2 >= prect->x2)
   2262        {
   2263            y = pbox->y2;       /* finished with this band */
   2264            if (y >= prect->y2)
   2265 	break;
   2266            x = prect->x1;      /* reset x out to left again */
   2267 }
   2268        else
   2269        {
   2270            /*
   2271      * Because boxes in a band are maximal width, if the first box
   2272      * to overlap the rectangle doesn't completely cover it in that
   2273      * band, the rectangle must be partially out, since some of it
   2274      * will be uncovered in that band. part_in will have been set true
   2275      * by now...
   2276      */
   2277            part_out = TRUE;
   2278            break;
   2279 }
   2280    }
   2281 
   2282    if (part_in)
   2283    {
   2284        if (y < prect->y2)
   2285     return PIXMAN_REGION_PART;
   2286        else
   2287     return PIXMAN_REGION_IN;
   2288    }
   2289    else
   2290    {
   2291        return PIXMAN_REGION_OUT;
   2292    }
   2293 }
   2294 
   2295 /* PREFIX(_translate) (region, x, y)
   2296 * translates in place
   2297 */
   2298 
   2299 PIXMAN_EXPORT void
   2300 PREFIX (_translate) (region_type_t *region, int x, int y)
   2301 {
   2302    overflow_int_t x1, x2, y1, y2;
   2303    int nbox;
   2304    box_type_t * pbox;
   2305 
   2306    GOOD (region);
   2307 
   2308    if (x == 0 && y == 0)
   2309        return;
   2310 
   2311    region->extents.x1 = x1 = region->extents.x1 + x;
   2312    region->extents.y1 = y1 = region->extents.y1 + y;
   2313    region->extents.x2 = x2 = region->extents.x2 + x;
   2314    region->extents.y2 = y2 = region->extents.y2 + y;
   2315    
   2316    if (((x1 - PIXMAN_REGION_MIN) | (y1 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x2) | (PIXMAN_REGION_MAX - y2)) >= 0)
   2317    {
   2318        if (region->data && (nbox = region->data->numRects))
   2319        {
   2320            for (pbox = PIXREGION_BOXPTR (region); nbox--; pbox++)
   2321            {
   2322                pbox->x1 += x;
   2323                pbox->y1 += y;
   2324                pbox->x2 += x;
   2325                pbox->y2 += y;
   2326     }
   2327 }
   2328        return;
   2329    }
   2330 
   2331    if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) | (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0)
   2332    {
   2333        region->extents.x2 = region->extents.x1;
   2334        region->extents.y2 = region->extents.y1;
   2335        FREE_DATA (region);
   2336        region->data = pixman_region_empty_data;
   2337        return;
   2338    }
   2339 
   2340    if (x1 < PIXMAN_REGION_MIN)
   2341 region->extents.x1 = PIXMAN_REGION_MIN;
   2342    else if (x2 > PIXMAN_REGION_MAX)
   2343 region->extents.x2 = PIXMAN_REGION_MAX;
   2344 
   2345    if (y1 < PIXMAN_REGION_MIN)
   2346 region->extents.y1 = PIXMAN_REGION_MIN;
   2347    else if (y2 > PIXMAN_REGION_MAX)
   2348 region->extents.y2 = PIXMAN_REGION_MAX;
   2349 
   2350    if (region->data && (nbox = region->data->numRects))
   2351    {
   2352        box_type_t * pbox_out;
   2353 
   2354        for (pbox_out = pbox = PIXREGION_BOXPTR (region); nbox--; pbox++)
   2355        {
   2356            pbox_out->x1 = x1 = pbox->x1 + x;
   2357            pbox_out->y1 = y1 = pbox->y1 + y;
   2358            pbox_out->x2 = x2 = pbox->x2 + x;
   2359            pbox_out->y2 = y2 = pbox->y2 + y;
   2360 
   2361            if (((x2 - PIXMAN_REGION_MIN) | (y2 - PIXMAN_REGION_MIN) |
   2362                 (PIXMAN_REGION_MAX - x1) | (PIXMAN_REGION_MAX - y1)) <= 0)
   2363            {
   2364                region->data->numRects--;
   2365                continue;
   2366     }
   2367 
   2368            if (x1 < PIXMAN_REGION_MIN)
   2369 	pbox_out->x1 = PIXMAN_REGION_MIN;
   2370            else if (x2 > PIXMAN_REGION_MAX)
   2371 	pbox_out->x2 = PIXMAN_REGION_MAX;
   2372 
   2373            if (y1 < PIXMAN_REGION_MIN)
   2374 	pbox_out->y1 = PIXMAN_REGION_MIN;
   2375            else if (y2 > PIXMAN_REGION_MAX)
   2376 	pbox_out->y2 = PIXMAN_REGION_MAX;
   2377 
   2378            pbox_out++;
   2379 }
   2380 
   2381        if (pbox_out != pbox)
   2382        {
   2383            if (region->data->numRects == 1)
   2384            {
   2385                region->extents = *PIXREGION_BOXPTR (region);
   2386                FREE_DATA (region);
   2387                region->data = (region_data_type_t *)NULL;
   2388     }
   2389            else
   2390     {
   2391 	pixman_set_extents (region);
   2392     }
   2393 }
   2394    }
   2395 
   2396    GOOD (region);
   2397 }
   2398 
   2399 PIXMAN_EXPORT void
   2400 PREFIX (_reset) (region_type_t *region, const box_type_t *box)
   2401 {
   2402    GOOD (region);
   2403 
   2404    critical_if_fail (GOOD_RECT (box));
   2405 
   2406    region->extents = *box;
   2407 
   2408    FREE_DATA (region);
   2409 
   2410    region->data = NULL;
   2411 }
   2412 
   2413 PIXMAN_EXPORT void
   2414 PREFIX (_clear) (region_type_t *region)
   2415 {
   2416    GOOD (region);
   2417    FREE_DATA (region);
   2418 
   2419    region->extents = *pixman_region_empty_box;
   2420    region->data = pixman_region_empty_data;
   2421 }
   2422 
   2423 /* box is "return" value */
   2424 PIXMAN_EXPORT int
   2425 PREFIX (_contains_point) (const region_type_t * region,
   2426                          int x, int y,
   2427                          box_type_t * box)
   2428 {
   2429    box_type_t *pbox, *pbox_end;
   2430    int numRects;
   2431 
   2432    GOOD (region);
   2433    numRects = PIXREGION_NUMRECTS (region);
   2434 
   2435    if (!numRects || !INBOX (&region->extents, x, y))
   2436 return(FALSE);
   2437 
   2438    if (numRects == 1)
   2439    {
   2440        if (box)
   2441     *box = region->extents;
   2442 
   2443        return(TRUE);
   2444    }
   2445 
   2446    pbox = PIXREGION_BOXPTR (region);
   2447    pbox_end = pbox + numRects;
   2448 
   2449    pbox = find_box_for_y (pbox, pbox_end, y);
   2450 
   2451    for (;pbox != pbox_end; pbox++)
   2452    {
   2453        if ((y < pbox->y1) || (x < pbox->x1))
   2454     break;              /* missed it */
   2455 
   2456        if (x >= pbox->x2)
   2457     continue;           /* not there yet */
   2458 
   2459        if (box)
   2460     *box = *pbox;
   2461 
   2462        return(TRUE);
   2463    }
   2464 
   2465    return(FALSE);
   2466 }
   2467 
   2468 PIXMAN_EXPORT int
   2469 PREFIX (_empty) (const region_type_t * region)
   2470 {
   2471    GOOD (region);
   2472 
   2473    return(PIXREGION_NIL (region));
   2474 }
   2475 
   2476 PIXMAN_EXPORT int
   2477 PREFIX (_not_empty) (const region_type_t * region)
   2478 {
   2479    GOOD (region);
   2480 
   2481    return(!PIXREGION_NIL (region));
   2482 }
   2483 
   2484 PIXMAN_EXPORT box_type_t *
   2485 PREFIX (_extents) (const region_type_t * region)
   2486 {
   2487    GOOD (region);
   2488 
   2489    return(box_type_t *)(&region->extents);
   2490 }
   2491 
   2492 /*
   2493 * Clip a list of scanlines to a region.  The caller has allocated the
   2494 * space.  FSorted is non-zero if the scanline origins are in ascending order.
   2495 *
   2496 * returns the number of new, clipped scanlines.
   2497 */
   2498 
   2499 PIXMAN_EXPORT pixman_bool_t
   2500 PREFIX (_selfcheck) (region_type_t *reg)
   2501 {
   2502    int i, numRects;
   2503 
   2504    if ((reg->extents.x1 > reg->extents.x2) ||
   2505        (reg->extents.y1 > reg->extents.y2))
   2506    {
   2507 return FALSE;
   2508    }
   2509 
   2510    numRects = PIXREGION_NUMRECTS (reg);
   2511    if (!numRects)
   2512    {
   2513 return ((reg->extents.x1 == reg->extents.x2) &&
   2514         (reg->extents.y1 == reg->extents.y2) &&
   2515         (reg->data->size || (reg->data == pixman_region_empty_data)));
   2516    }
   2517    else if (numRects == 1)
   2518    {
   2519 return (!reg->data);
   2520    }
   2521    else
   2522    {
   2523        box_type_t * pbox_p, * pbox_n;
   2524        box_type_t box;
   2525 
   2526        pbox_p = PIXREGION_RECTS (reg);
   2527        box = *pbox_p;
   2528        box.y2 = pbox_p[numRects - 1].y2;
   2529        pbox_n = pbox_p + 1;
   2530 
   2531        for (i = numRects; --i > 0; pbox_p++, pbox_n++)
   2532        {
   2533            if ((pbox_n->x1 >= pbox_n->x2) ||
   2534                (pbox_n->y1 >= pbox_n->y2))
   2535     {
   2536 	return FALSE;
   2537     }
   2538 
   2539            if (pbox_n->x1 < box.x1)
   2540 	box.x1 = pbox_n->x1;
   2541     
   2542            if (pbox_n->x2 > box.x2)
   2543 	box.x2 = pbox_n->x2;
   2544     
   2545            if ((pbox_n->y1 < pbox_p->y1) ||
   2546                ((pbox_n->y1 == pbox_p->y1) &&
   2547                 ((pbox_n->x1 < pbox_p->x2) || (pbox_n->y2 != pbox_p->y2))))
   2548     {
   2549 	return FALSE;
   2550     }
   2551 }
   2552 
   2553        return ((box.x1 == reg->extents.x1) &&
   2554                (box.x2 == reg->extents.x2) &&
   2555                (box.y1 == reg->extents.y1) &&
   2556                (box.y2 == reg->extents.y2));
   2557    }
   2558 }
   2559 
   2560 PIXMAN_EXPORT pixman_bool_t
   2561 PREFIX (_init_rects) (region_type_t *region,
   2562                      const box_type_t *boxes, int count)
   2563 {
   2564    box_type_t *rects;
   2565    int displacement;
   2566    int i;
   2567 
   2568    /* if it's 1, then we just want to set the extents, so call
   2569     * the existing method. */
   2570    if (count == 1)
   2571    {
   2572        PREFIX (_init_rect) (region,
   2573                             boxes[0].x1,
   2574                             boxes[0].y1,
   2575                             boxes[0].x2 - boxes[0].x1,
   2576                             boxes[0].y2 - boxes[0].y1);
   2577        return TRUE;
   2578    }
   2579 
   2580    PREFIX (_init) (region);
   2581 
   2582    /* if it's 0, don't call pixman_rect_alloc -- 0 rectangles is
   2583     * a special case, and causing pixman_rect_alloc would cause
   2584     * us to leak memory (because the 0-rect case should be the
   2585     * static pixman_region_empty_data data).
   2586     */
   2587    if (count == 0)
   2588 return TRUE;
   2589 
   2590    if (!pixman_rect_alloc (region, count))
   2591 return FALSE;
   2592 
   2593    rects = PIXREGION_RECTS (region);
   2594 
   2595    /* Copy in the rects */
   2596    memcpy (rects, boxes, sizeof(box_type_t) * count);
   2597    region->data->numRects = count;
   2598 
   2599    /* Eliminate empty and malformed rectangles */
   2600    displacement = 0;
   2601 
   2602    for (i = 0; i < count; ++i)
   2603    {
   2604        box_type_t *box = &rects[i];
   2605 
   2606        if (box->x1 >= box->x2 || box->y1 >= box->y2)
   2607     displacement++;
   2608        else if (displacement)
   2609     rects[i - displacement] = rects[i];
   2610    }
   2611 
   2612    region->data->numRects -= displacement;
   2613 
   2614    /* If eliminating empty rectangles caused there
   2615     * to be only 0 or 1 rectangles, deal with that.
   2616     */
   2617    if (region->data->numRects == 0)
   2618    {
   2619        FREE_DATA (region);
   2620        PREFIX (_init) (region);
   2621 
   2622        return TRUE;
   2623    }
   2624 
   2625    if (region->data->numRects == 1)
   2626    {
   2627        region->extents = rects[0];
   2628 
   2629        FREE_DATA (region);
   2630        region->data = NULL;
   2631 
   2632        GOOD (region);
   2633 
   2634        return TRUE;
   2635    }
   2636 
   2637    /* Validate */
   2638    region->extents.x1 = region->extents.x2 = 0;
   2639 
   2640    return validate (region);
   2641 }
   2642 
   2643 #define READ(_ptr) (*(_ptr))
   2644 
   2645 static inline box_type_t *
   2646 bitmap_addrect (region_type_t *reg,
   2647                box_type_t *r,
   2648                box_type_t **first_rect,
   2649                primitive_t rx1, primitive_t ry1,
   2650                primitive_t rx2, primitive_t ry2)
   2651 {
   2652    if ((rx1 < rx2) && (ry1 < ry2) &&
   2653 (!(reg->data->numRects &&
   2654    ((r-1)->y1 == ry1) && ((r-1)->y2 == ry2) &&
   2655    ((r-1)->x1 <= rx1) && ((r-1)->x2 >= rx2))))
   2656    {
   2657 if (reg->data->numRects == reg->data->size)
   2658 {
   2659     if (!pixman_rect_alloc (reg, 1))
   2660 	return NULL;
   2661     *first_rect = PIXREGION_BOXPTR(reg);
   2662     r = *first_rect + reg->data->numRects;
   2663 }
   2664 r->x1 = rx1;
   2665 r->y1 = ry1;
   2666 r->x2 = rx2;
   2667 r->y2 = ry2;
   2668 reg->data->numRects++;
   2669 if (r->x1 < reg->extents.x1)
   2670     reg->extents.x1 = r->x1;
   2671 if (r->x2 > reg->extents.x2)
   2672     reg->extents.x2 = r->x2;
   2673 r++;
   2674    }
   2675    return r;
   2676 }
   2677 
   2678 /* Convert bitmap clip mask into clipping region.
   2679 * First, goes through each line and makes boxes by noting the transitions
   2680 * from 0 to 1 and 1 to 0.
   2681 * Then it coalesces the current line with the previous if they have boxes
   2682 * at the same X coordinates.
   2683 * Stride is in number of uint32_t per line.
   2684 */
   2685 PIXMAN_EXPORT void
   2686 PREFIX (_init_from_image) (region_type_t *region,
   2687                           pixman_image_t *image)
   2688 {
   2689    uint32_t mask0 = 0xffffffff & ~SCREEN_SHIFT_RIGHT(0xffffffff, 1);
   2690    box_type_t *first_rect, *rects, *prect_line_start;
   2691    box_type_t *old_rect, *new_rect;
   2692    uint32_t *pw, w, *pw_line, *pw_line_end;
   2693    int	irect_prev_start, irect_line_start;
   2694    int	h, base, rx1 = 0, crects;
   2695    int	ib;
   2696    pixman_bool_t in_box, same;
   2697    int width, height, stride;
   2698 
   2699    PREFIX(_init) (region);
   2700 
   2701    critical_if_fail (region->data);
   2702 
   2703    return_if_fail (image->type == BITS);
   2704    return_if_fail (image->bits.format == PIXMAN_a1);
   2705 
   2706    pw_line = pixman_image_get_data (image);
   2707    width = pixman_image_get_width (image);
   2708    height = pixman_image_get_height (image);
   2709    stride = pixman_image_get_stride (image) / 4;
   2710 
   2711    first_rect = PIXREGION_BOXPTR(region);
   2712    rects = first_rect;
   2713 
   2714    region->extents.x1 = width - 1;
   2715    region->extents.x2 = 0;
   2716    irect_prev_start = -1;
   2717    for (h = 0; h < height; h++)
   2718    {
   2719        pw = pw_line;
   2720        pw_line += stride;
   2721        irect_line_start = rects - first_rect;
   2722 
   2723        /* If the Screen left most bit of the word is set, we're starting in
   2724         * a box */
   2725        if (READ(pw) & mask0)
   2726        {
   2727            in_box = TRUE;
   2728            rx1 = 0;
   2729        }
   2730        else
   2731        {
   2732            in_box = FALSE;
   2733        }
   2734 
   2735        /* Process all words which are fully in the pixmap */
   2736        pw_line_end = pw + (width >> 5);
   2737        for (base = 0; pw < pw_line_end; base += 32)
   2738        {
   2739            w = READ(pw++);
   2740            if (in_box)
   2741            {
   2742                if (!~w)
   2743                    continue;
   2744            }
   2745            else
   2746            {
   2747                if (!w)
   2748                    continue;
   2749            }
   2750            for (ib = 0; ib < 32; ib++)
   2751            {
   2752                /* If the Screen left most bit of the word is set, we're
   2753                 * starting a box */
   2754                if (w & mask0)
   2755                {
   2756                    if (!in_box)
   2757                    {
   2758                        rx1 = base + ib;
   2759                        /* start new box */
   2760                        in_box = TRUE;
   2761                    }
   2762                }
   2763                else
   2764                {
   2765                    if (in_box)
   2766                    {
   2767                        /* end box */
   2768                        rects = bitmap_addrect (region, rects, &first_rect,
   2769                                                rx1, h, base + ib, h + 1);
   2770                        if (rects == NULL)
   2771                            goto error;
   2772                        in_box = FALSE;
   2773                    }
   2774                }
   2775                /* Shift the word VISUALLY left one. */
   2776                w = SCREEN_SHIFT_LEFT(w, 1);
   2777            }
   2778        }
   2779 
   2780        if (width & 31)
   2781        {
   2782            /* Process final partial word on line */
   2783             w = READ(pw++);
   2784            for (ib = 0; ib < (width & 31); ib++)
   2785            {
   2786                /* If the Screen left most bit of the word is set, we're
   2787                 * starting a box */
   2788                if (w & mask0)
   2789                {
   2790                    if (!in_box)
   2791                    {
   2792                        rx1 = base + ib;
   2793                        /* start new box */
   2794                        in_box = TRUE;
   2795                    }
   2796                }
   2797                else
   2798                {
   2799                    if (in_box)
   2800                    {
   2801                        /* end box */
   2802                        rects = bitmap_addrect(region, rects, &first_rect,
   2803 				       rx1, h, base + ib, h + 1);
   2804 		if (rects == NULL)
   2805 		    goto error;
   2806                        in_box = FALSE;
   2807                    }
   2808                }
   2809                /* Shift the word VISUALLY left one. */
   2810                w = SCREEN_SHIFT_LEFT(w, 1);
   2811            }
   2812        }
   2813        /* If scanline ended with last bit set, end the box */
   2814        if (in_box)
   2815        {
   2816            rects = bitmap_addrect(region, rects, &first_rect,
   2817 			   rx1, h, base + (width & 31), h + 1);
   2818     if (rects == NULL)
   2819 	goto error;
   2820        }
   2821        /* if all rectangles on this line have the same x-coords as
   2822         * those on the previous line, then add 1 to all the previous  y2s and
   2823         * throw away all the rectangles from this line
   2824         */
   2825        same = FALSE;
   2826        if (irect_prev_start != -1)
   2827        {
   2828            crects = irect_line_start - irect_prev_start;
   2829            if (crects != 0 &&
   2830                crects == ((rects - first_rect) - irect_line_start))
   2831            {
   2832                old_rect = first_rect + irect_prev_start;
   2833                new_rect = prect_line_start = first_rect + irect_line_start;
   2834                same = TRUE;
   2835                while (old_rect < prect_line_start)
   2836                {
   2837                    if ((old_rect->x1 != new_rect->x1) ||
   2838                        (old_rect->x2 != new_rect->x2))
   2839                    {
   2840                          same = FALSE;
   2841                          break;
   2842                    }
   2843                    old_rect++;
   2844                    new_rect++;
   2845                }
   2846                if (same)
   2847                {
   2848                    old_rect = first_rect + irect_prev_start;
   2849                    while (old_rect < prect_line_start)
   2850                    {
   2851                        old_rect->y2 += 1;
   2852                        old_rect++;
   2853                    }
   2854                    rects -= crects;
   2855                    region->data->numRects -= crects;
   2856                }
   2857            }
   2858        }
   2859        if(!same)
   2860            irect_prev_start = irect_line_start;
   2861    }
   2862    if (!region->data->numRects)
   2863    {
   2864        region->extents.x1 = region->extents.x2 = 0;
   2865    }
   2866    else
   2867    {
   2868        region->extents.y1 = PIXREGION_BOXPTR(region)->y1;
   2869        region->extents.y2 = PIXREGION_END(region)->y2;
   2870        if (region->data->numRects == 1)
   2871        {
   2872            free (region->data);
   2873            region->data = NULL;
   2874        }
   2875    }
   2876 
   2877 error:
   2878    return;
   2879 }