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