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