Get rid of pixman_region_internal_set_static_pointers()
[profile/ivi/pixman.git] / pixman / pixman-region.c
1 /***********************************************************
2
3 Copyright 1987, 1988, 1989, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1987, 1988, 1989 by
26 Digital Equipment Corporation, Maynard, Massachusetts.
27
28                         All Rights Reserved
29
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
37
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
45
46 ******************************************************************/
47
48 #include <stdlib.h>
49 #include <limits.h>
50 #include <string.h>
51 #include <stdio.h>
52
53 #define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
54 /* not a region */
55 #define PIXREGION_NAR(reg)      ((reg)->data == pixman_brokendata)
56 #define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
57 #define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
58 #define PIXREGION_RECTS(reg) ((reg)->data ? (box_type_t *)((reg)->data + 1) \
59                                        : &(reg)->extents)
60 #define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1))
61 #define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
62 #define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
63 #define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
64
65
66 #undef assert
67 #ifdef DEBUG_PIXREGION
68 #define assert(expr) {if (!(expr)) \
69                 FatalError("Assertion failed file %s, line %d: expr\n", \
70                         __FILE__, __LINE__); }
71 #else
72 #define assert(expr)
73 #endif
74
75 #define good(reg) assert(PREFIX(_selfcheck) (reg))
76
77 #undef MIN
78 #define MIN(a,b) ((a) < (b) ? (a) : (b))
79 #undef MAX
80 #define MAX(a,b) ((a) > (b) ? (a) : (b))
81
82 static const box_type_t PREFIX(_emptyBox_) = {0, 0, 0, 0};
83 static const region_data_type_t PREFIX(_emptyData_) = {0, 0};
84 static const region_data_type_t PREFIX(_brokendata_) = {0, 0};
85
86 static box_type_t *pixman_region_emptyBox = (box_type_t *)&PREFIX(_emptyBox_);
87 static region_data_type_t *pixman_region_emptyData = (region_data_type_t *)&PREFIX(_emptyData_);
88 static region_data_type_t *pixman_brokendata = (region_data_type_t *)&PREFIX(_brokendata_);
89
90 static pixman_bool_t
91 pixman_break (region_type_t *pReg);
92
93 /*
94  * The functions in this file implement the Region abstraction used extensively
95  * throughout the X11 sample server. A Region is simply a set of disjoint
96  * (non-overlapping) rectangles, plus an "extent" rectangle which is the
97  * smallest single rectangle that contains all the non-overlapping rectangles.
98  *
99  * A Region is implemented as a "y-x-banded" array of rectangles.  This array
100  * imposes two degrees of order.  First, all rectangles are sorted by top side
101  * y coordinate first (y1), and then by left side x coordinate (x1).
102  *
103  * Furthermore, the rectangles are grouped into "bands".  Each rectangle in a
104  * band has the same top y coordinate (y1), and each has the same bottom y
105  * coordinate (y2).  Thus all rectangles in a band differ only in their left
106  * and right side (x1 and x2).  Bands are implicit in the array of rectangles:
107  * there is no separate list of band start pointers.
108  *
109  * The y-x band representation does not minimize rectangles.  In particular,
110  * if a rectangle vertically crosses a band (the rectangle has scanlines in
111  * the y1 to y2 area spanned by the band), then the rectangle may be broken
112  * down into two or more smaller rectangles stacked one atop the other.
113  *
114  *  -----------                             -----------
115  *  |         |                             |         |             band 0
116  *  |         |  --------                   -----------  --------
117  *  |         |  |      |  in y-x banded    |         |  |      |   band 1
118  *  |         |  |      |  form is          |         |  |      |
119  *  -----------  |      |                   -----------  --------
120  *               |      |                                |      |   band 2
121  *               --------                                --------
122  *
123  * An added constraint on the rectangles is that they must cover as much
124  * horizontal area as possible: no two rectangles within a band are allowed
125  * to touch.
126  *
127  * Whenever possible, bands will be merged together to cover a greater vertical
128  * distance (and thus reduce the number of rectangles). Two bands can be merged
129  * only if the bottom of one touches the top of the other and they have
130  * rectangles in the same places (of the same width, of course).
131  *
132  * Adam de Boor wrote most of the original region code.  Joel McCormack
133  * substantially modified or rewrote most of the core arithmetic routines, and
134  * added pixman_region_validate in order to support several speed improvements to
135  * pixman_region_validateTree.  Bob Scheifler changed the representation to be more
136  * compact when empty or a single rectangle, and did a bunch of gratuitous
137  * reformatting. Carl Worth did further gratuitous reformatting while re-merging
138  * the server and client region code into libpixregion.
139  */
140
141 /*  true iff two Boxes overlap */
142 #define EXTENTCHECK(r1,r2) \
143       (!( ((r1)->x2 <= (r2)->x1)  || \
144           ((r1)->x1 >= (r2)->x2)  || \
145           ((r1)->y2 <= (r2)->y1)  || \
146           ((r1)->y1 >= (r2)->y2) ) )
147
148 /* true iff (x,y) is in Box */
149 #define INBOX(r,x,y) \
150       ( ((r)->x2 >  x) && \
151         ((r)->x1 <= x) && \
152         ((r)->y2 >  y) && \
153         ((r)->y1 <= y) )
154
155 /* true iff Box r1 contains Box r2 */
156 #define SUBSUMES(r1,r2) \
157       ( ((r1)->x1 <= (r2)->x1) && \
158         ((r1)->x2 >= (r2)->x2) && \
159         ((r1)->y1 <= (r2)->y1) && \
160         ((r1)->y2 >= (r2)->y2) )
161
162 static size_t
163 PIXREGION_SZOF(size_t n)
164 {
165     size_t size = n * sizeof(box_type_t);
166     if (n > UINT32_MAX / sizeof(box_type_t))
167         return 0;
168
169     if (sizeof(region_data_type_t) > UINT32_MAX - size)
170         return 0;
171
172     return size + sizeof(region_data_type_t);
173 }
174
175 static void *
176 allocData(size_t n)
177 {
178     size_t sz = PIXREGION_SZOF(n);
179     if (!sz)
180         return NULL;
181
182     return malloc(sz);
183 }
184
185 #define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
186
187 #define RECTALLOC_BAIL(pReg,n,bail) \
188 if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
189     if (!pixman_rect_alloc(pReg, n)) { goto bail; }
190
191 #define RECTALLOC(pReg,n) \
192 if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
193     if (!pixman_rect_alloc(pReg, n)) { return FALSE; }
194
195 #define ADDRECT(pNextRect,nx1,ny1,nx2,ny2)      \
196 {                                               \
197     pNextRect->x1 = nx1;                        \
198     pNextRect->y1 = ny1;                        \
199     pNextRect->x2 = nx2;                        \
200     pNextRect->y2 = ny2;                        \
201     pNextRect++;                                \
202 }
203
204 #define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2)                 \
205 {                                                                       \
206     if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
207     {                                                                   \
208         if (!pixman_rect_alloc(pReg, 1))                                        \
209             return FALSE;                                               \
210         pNextRect = PIXREGION_TOP(pReg);                                        \
211     }                                                                   \
212     ADDRECT(pNextRect,nx1,ny1,nx2,ny2);                                 \
213     pReg->data->numRects++;                                             \
214     assert(pReg->data->numRects<=pReg->data->size);                     \
215 }
216
217 #define DOWNSIZE(reg,numRects)                                          \
218     if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
219     {                                                                   \
220         region_data_type_t * NewData;                           \
221         size_t data_size = PIXREGION_SZOF(numRects);                    \
222         if (!data_size)                                                 \
223             NewData = NULL;                                             \
224         else                                                            \
225             NewData = (region_data_type_t *)realloc((reg)->data, data_size); \
226         if (NewData)                                                    \
227         {                                                               \
228             NewData->size = (numRects);                                 \
229             (reg)->data = NewData;                                      \
230         }                                                               \
231     }
232
233 PIXMAN_EXPORT pixman_bool_t
234 PREFIX(_equal) (reg1, reg2)
235     region_type_t * reg1;
236     region_type_t * reg2;
237 {
238     int i;
239     box_type_t *rects1;
240     box_type_t *rects2;
241
242     if (reg1->extents.x1 != reg2->extents.x1) return FALSE;
243     if (reg1->extents.x2 != reg2->extents.x2) return FALSE;
244     if (reg1->extents.y1 != reg2->extents.y1) return FALSE;
245     if (reg1->extents.y2 != reg2->extents.y2) return FALSE;
246     if (PIXREGION_NUM_RECTS(reg1) != PIXREGION_NUM_RECTS(reg2)) return FALSE;
247
248     rects1 = PIXREGION_RECTS(reg1);
249     rects2 = PIXREGION_RECTS(reg2);
250     for (i = 0; i != PIXREGION_NUM_RECTS(reg1); i++) {
251         if (rects1[i].x1 != rects2[i].x1) return FALSE;
252         if (rects1[i].x2 != rects2[i].x2) return FALSE;
253         if (rects1[i].y1 != rects2[i].y1) return FALSE;
254         if (rects1[i].y2 != rects2[i].y2) return FALSE;
255     }
256     return TRUE;
257 }
258
259 int
260 PREFIX(_print) (rgn)
261     region_type_t * rgn;
262 {
263     int num, size;
264     int i;
265     box_type_t * rects;
266
267     num = PIXREGION_NUM_RECTS(rgn);
268     size = PIXREGION_SIZE(rgn);
269     rects = PIXREGION_RECTS(rgn);
270     fprintf(stderr, "num: %d size: %d\n", num, size);
271     fprintf(stderr, "extents: %d %d %d %d\n",
272            rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
273     for (i = 0; i < num; i++)
274         fprintf(stderr, "%d %d %d %d \n",
275                 rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
276     fprintf(stderr, "\n");
277     return(num);
278 }
279
280
281 PIXMAN_EXPORT void
282 PREFIX(_init) (region_type_t *region)
283 {
284     region->extents = *pixman_region_emptyBox;
285     region->data = pixman_region_emptyData;
286 }
287
288 PIXMAN_EXPORT void
289 PREFIX(_init_rect) (region_type_t *region,
290                     int x, int y, unsigned int width, unsigned int height)
291 {
292     region->extents.x1 = x;
293     region->extents.y1 = y;
294     region->extents.x2 = x + width;
295     region->extents.y2 = y + height;
296     region->data = NULL;
297 }
298
299 PIXMAN_EXPORT void
300 PREFIX(_init_with_extents) (region_type_t *region, box_type_t *extents)
301 {
302     region->extents = *extents;
303     region->data = NULL;
304 }
305
306 PIXMAN_EXPORT void
307 PREFIX(_fini) (region_type_t *region)
308 {
309     good (region);
310     freeData (region);
311 }
312
313 PIXMAN_EXPORT int
314 PREFIX(_n_rects) (region_type_t *region)
315 {
316     return PIXREGION_NUM_RECTS (region);
317 }
318
319 PIXMAN_EXPORT box_type_t *
320 PREFIX(_rectangles) (region_type_t *region,
321                                   int               *n_rects)
322 {
323     if (n_rects)
324         *n_rects = PIXREGION_NUM_RECTS (region);
325
326     return PIXREGION_RECTS (region);
327 }
328
329 static pixman_bool_t
330 pixman_break (region_type_t *region)
331 {
332     freeData (region);
333     region->extents = *pixman_region_emptyBox;
334     region->data = pixman_brokendata;
335     return FALSE;
336 }
337
338 static pixman_bool_t
339 pixman_rect_alloc (region_type_t * region, int n)
340 {
341     region_data_type_t *data;
342
343     if (!region->data)
344     {
345         n++;
346         region->data = allocData(n);
347         if (!region->data)
348             return pixman_break (region);
349         region->data->numRects = 1;
350         *PIXREGION_BOXPTR(region) = region->extents;
351     }
352     else if (!region->data->size)
353     {
354         region->data = allocData(n);
355         if (!region->data)
356             return pixman_break (region);
357         region->data->numRects = 0;
358     }
359     else
360     {
361         size_t data_size;
362         if (n == 1)
363         {
364             n = region->data->numRects;
365             if (n > 500) /* XXX pick numbers out of a hat */
366                 n = 250;
367         }
368         n += region->data->numRects;
369         data_size = PIXREGION_SZOF(n);
370         if (!data_size)
371             data = NULL;
372         else
373             data = (region_data_type_t *)realloc(region->data, PIXREGION_SZOF(n));
374         if (!data)
375             return pixman_break (region);
376         region->data = data;
377     }
378     region->data->size = n;
379     return TRUE;
380 }
381
382 PIXMAN_EXPORT pixman_bool_t
383 PREFIX(_copy) (region_type_t *dst, region_type_t *src)
384 {
385     good(dst);
386     good(src);
387     if (dst == src)
388         return TRUE;
389     dst->extents = src->extents;
390     if (!src->data || !src->data->size)
391     {
392         freeData(dst);
393         dst->data = src->data;
394         return TRUE;
395     }
396     if (!dst->data || (dst->data->size < src->data->numRects))
397     {
398         freeData(dst);
399         dst->data = allocData(src->data->numRects);
400         if (!dst->data)
401             return pixman_break (dst);
402         dst->data->size = src->data->numRects;
403     }
404     dst->data->numRects = src->data->numRects;
405     memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src),
406           dst->data->numRects * sizeof(box_type_t));
407     return TRUE;
408 }
409
410 /*======================================================================
411  *          Generic Region Operator
412  *====================================================================*/
413
414 /*-
415  *-----------------------------------------------------------------------
416  * pixman_coalesce --
417  *      Attempt to merge the boxes in the current band with those in the
418  *      previous one.  We are guaranteed that the current band extends to
419  *      the end of the rects array.  Used only by pixman_op.
420  *
421  * Results:
422  *      The new index for the previous band.
423  *
424  * Side Effects:
425  *      If coalescing takes place:
426  *          - rectangles in the previous band will have their y2 fields
427  *            altered.
428  *          - region->data->numRects will be decreased.
429  *
430  *-----------------------------------------------------------------------
431  */
432 static inline int
433 pixman_coalesce (
434     region_type_t *     region,         /* Region to coalesce                */
435     int                 prevStart,      /* Index of start of previous band   */
436     int                 curStart)       /* Index of start of current band    */
437 {
438     box_type_t *        pPrevBox;       /* Current box in previous band      */
439     box_type_t *        pCurBox;        /* Current box in current band       */
440     int         numRects;       /* Number rectangles in both bands   */
441     int y2;             /* Bottom of current band            */
442     /*
443      * Figure out how many rectangles are in the band.
444      */
445     numRects = curStart - prevStart;
446     assert(numRects == region->data->numRects - curStart);
447
448     if (!numRects) return curStart;
449
450     /*
451      * The bands may only be coalesced if the bottom of the previous
452      * matches the top scanline of the current.
453      */
454     pPrevBox = PIXREGION_BOX(region, prevStart);
455     pCurBox = PIXREGION_BOX(region, curStart);
456     if (pPrevBox->y2 != pCurBox->y1) return curStart;
457
458     /*
459      * Make sure the bands have boxes in the same places. This
460      * assumes that boxes have been added in such a way that they
461      * cover the most area possible. I.e. two boxes in a band must
462      * have some horizontal space between them.
463      */
464     y2 = pCurBox->y2;
465
466     do {
467         if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
468             return (curStart);
469         }
470         pPrevBox++;
471         pCurBox++;
472         numRects--;
473     } while (numRects);
474
475     /*
476      * The bands may be merged, so set the bottom y of each box
477      * in the previous band to the bottom y of the current band.
478      */
479     numRects = curStart - prevStart;
480     region->data->numRects -= numRects;
481     do {
482         pPrevBox--;
483         pPrevBox->y2 = y2;
484         numRects--;
485     } while (numRects);
486     return prevStart;
487 }
488
489 /* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
490
491 #define Coalesce(newReg, prevBand, curBand)                             \
492     if (curBand - prevBand == newReg->data->numRects - curBand) {       \
493         prevBand = pixman_coalesce(newReg, prevBand, curBand);          \
494     } else {                                                            \
495         prevBand = curBand;                                             \
496     }
497
498 /*-
499  *-----------------------------------------------------------------------
500  * pixman_region_appendNonO --
501  *      Handle a non-overlapping band for the union and subtract operations.
502  *      Just adds the (top/bottom-clipped) rectangles into the region.
503  *      Doesn't have to check for subsumption or anything.
504  *
505  * Results:
506  *      None.
507  *
508  * Side Effects:
509  *      region->data->numRects is incremented and the rectangles overwritten
510  *      with the rectangles we're passed.
511  *
512  *-----------------------------------------------------------------------
513  */
514
515 static inline pixman_bool_t
516 pixman_region_appendNonO (
517     region_type_t *     region,
518     box_type_t *        r,
519     box_type_t *                rEnd,
520     int         y1,
521     int         y2)
522 {
523     box_type_t *        pNextRect;
524     int newRects;
525
526     newRects = rEnd - r;
527
528     assert(y1 < y2);
529     assert(newRects != 0);
530
531     /* Make sure we have enough space for all rectangles to be added */
532     RECTALLOC(region, newRects);
533     pNextRect = PIXREGION_TOP(region);
534     region->data->numRects += newRects;
535     do {
536         assert(r->x1 < r->x2);
537         ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
538         r++;
539     } while (r != rEnd);
540
541     return TRUE;
542 }
543
544 #define FindBand(r, rBandEnd, rEnd, ry1)                    \
545 {                                                           \
546     ry1 = r->y1;                                            \
547     rBandEnd = r+1;                                         \
548     while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) {   \
549         rBandEnd++;                                         \
550     }                                                       \
551 }
552
553 #define AppendRegions(newReg, r, rEnd)                                  \
554 {                                                                       \
555     int newRects;                                                       \
556     if ((newRects = rEnd - r)) {                                        \
557         RECTALLOC_BAIL(newReg, newRects, bail);                                 \
558         memmove((char *)PIXREGION_TOP(newReg),(char *)r,                        \
559               newRects * sizeof(box_type_t));                           \
560         newReg->data->numRects += newRects;                             \
561     }                                                                   \
562 }
563
564 /*-
565  *-----------------------------------------------------------------------
566  * pixman_op --
567  *      Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
568  *      pixman_region_subtract, pixman_region_intersect....  Both regions MUST have at least one
569  *      rectangle, and cannot be the same object.
570  *
571  * Results:
572  *      TRUE if successful.
573  *
574  * Side Effects:
575  *      The new region is overwritten.
576  *      pOverlap set to TRUE if overlapFunc ever returns TRUE.
577  *
578  * Notes:
579  *      The idea behind this function is to view the two regions as sets.
580  *      Together they cover a rectangle of area that this function divides
581  *      into horizontal bands where points are covered only by one region
582  *      or by both. For the first case, the nonOverlapFunc is called with
583  *      each the band and the band's upper and lower extents. For the
584  *      second, the overlapFunc is called to process the entire band. It
585  *      is responsible for clipping the rectangles in the band, though
586  *      this function provides the boundaries.
587  *      At the end of each band, the new region is coalesced, if possible,
588  *      to reduce the number of rectangles in the region.
589  *
590  *-----------------------------------------------------------------------
591  */
592
593 typedef pixman_bool_t (*OverlapProcPtr)(
594     region_type_t        *region,
595     box_type_t *r1,
596     box_type_t *r1End,
597     box_type_t *r2,
598     box_type_t *r2End,
599     int          y1,
600     int          y2,
601     int          *pOverlap);
602
603 static pixman_bool_t
604 pixman_op(
605     region_type_t *newReg,                  /* Place to store result         */
606     region_type_t *       reg1,             /* First region in operation     */
607     region_type_t *       reg2,             /* 2d region in operation        */
608     OverlapProcPtr  overlapFunc,            /* Function to call for over-
609                                              * lapping bands                 */
610     int     appendNon1,             /* Append non-overlapping bands  */
611                                             /* in region 1 ? */
612     int     appendNon2,             /* Append non-overlapping bands  */
613                                             /* in region 2 ? */
614     int     *pOverlap)
615 {
616     box_type_t * r1;                        /* Pointer into first region     */
617     box_type_t * r2;                        /* Pointer into 2d region        */
618     box_type_t *            r1End;                  /* End of 1st region             */
619     box_type_t *            r2End;                  /* End of 2d region              */
620     int     ybot;                   /* Bottom of intersection        */
621     int     ytop;                   /* Top of intersection           */
622     region_data_type_t *            oldData;                /* Old data for newReg           */
623     int             prevBand;               /* Index of start of
624                                              * previous band in newReg       */
625     int             curBand;                /* Index of start of current
626                                              * band in newReg                */
627     box_type_t * r1BandEnd;                 /* End of current band in r1     */
628     box_type_t * r2BandEnd;                 /* End of current band in r2     */
629     int     top;                    /* Top of non-overlapping band   */
630     int     bot;                    /* Bottom of non-overlapping band*/
631     int    r1y1;                    /* Temps for r1->y1 and r2->y1   */
632     int    r2y1;
633     int             newSize;
634     int             numRects;
635
636     /*
637      * Break any region computed from a broken region
638      */
639     if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))
640         return pixman_break (newReg);
641
642     /*
643      * Initialization:
644      *  set r1, r2, r1End and r2End appropriately, save the rectangles
645      * of the destination region until the end in case it's one of
646      * the two source regions, then mark the "new" region empty, allocating
647      * another array of rectangles for it to use.
648      */
649
650     r1 = PIXREGION_RECTS(reg1);
651     newSize = PIXREGION_NUM_RECTS(reg1);
652     r1End = r1 + newSize;
653     numRects = PIXREGION_NUM_RECTS(reg2);
654     r2 = PIXREGION_RECTS(reg2);
655     r2End = r2 + numRects;
656     assert(r1 != r1End);
657     assert(r2 != r2End);
658
659     oldData = (region_data_type_t *)NULL;
660     if (((newReg == reg1) && (newSize > 1)) ||
661         ((newReg == reg2) && (numRects > 1)))
662     {
663         oldData = newReg->data;
664         newReg->data = pixman_region_emptyData;
665     }
666     /* guess at new size */
667     if (numRects > newSize)
668         newSize = numRects;
669     newSize <<= 1;
670     if (!newReg->data)
671         newReg->data = pixman_region_emptyData;
672     else if (newReg->data->size)
673         newReg->data->numRects = 0;
674     if (newSize > newReg->data->size) {
675         if (!pixman_rect_alloc(newReg, newSize)) {
676             if (oldData)
677                 free (oldData);
678             return FALSE;
679         }
680     }
681
682     /*
683      * Initialize ybot.
684      * In the upcoming loop, ybot and ytop serve different functions depending
685      * on whether the band being handled is an overlapping or non-overlapping
686      * band.
687      *  In the case of a non-overlapping band (only one of the regions
688      * has points in the band), ybot is the bottom of the most recent
689      * intersection and thus clips the top of the rectangles in that band.
690      * ytop is the top of the next intersection between the two regions and
691      * serves to clip the bottom of the rectangles in the current band.
692      *  For an overlapping band (where the two regions intersect), ytop clips
693      * the top of the rectangles of both regions and ybot clips the bottoms.
694      */
695
696     ybot = MIN(r1->y1, r2->y1);
697
698     /*
699      * prevBand serves to mark the start of the previous band so rectangles
700      * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
701      * In the beginning, there is no previous band, so prevBand == curBand
702      * (curBand is set later on, of course, but the first band will always
703      * start at index 0). prevBand and curBand must be indices because of
704      * the possible expansion, and resultant moving, of the new region's
705      * array of rectangles.
706      */
707     prevBand = 0;
708
709     do {
710         /*
711          * This algorithm proceeds one source-band (as opposed to a
712          * destination band, which is determined by where the two regions
713          * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
714          * rectangle after the last one in the current band for their
715          * respective regions.
716          */
717         assert(r1 != r1End);
718         assert(r2 != r2End);
719
720         FindBand(r1, r1BandEnd, r1End, r1y1);
721         FindBand(r2, r2BandEnd, r2End, r2y1);
722
723         /*
724          * First handle the band that doesn't intersect, if any.
725          *
726          * Note that attention is restricted to one band in the
727          * non-intersecting region at once, so if a region has n
728          * bands between the current position and the next place it overlaps
729          * the other, this entire loop will be passed through n times.
730          */
731         if (r1y1 < r2y1) {
732             if (appendNon1) {
733                 top = MAX(r1y1, ybot);
734                 bot = MIN(r1->y2, r2y1);
735                 if (top != bot) {
736                     curBand = newReg->data->numRects;
737                     if (!pixman_region_appendNonO(newReg, r1, r1BandEnd, top, bot))
738                         goto bail;
739                     Coalesce(newReg, prevBand, curBand);
740                 }
741             }
742             ytop = r2y1;
743         } else if (r2y1 < r1y1) {
744             if (appendNon2) {
745                 top = MAX(r2y1, ybot);
746                 bot = MIN(r2->y2, r1y1);
747                 if (top != bot) {
748                     curBand = newReg->data->numRects;
749                     if (!pixman_region_appendNonO(newReg, r2, r2BandEnd, top, bot))
750                         goto bail;
751                     Coalesce(newReg, prevBand, curBand);
752                 }
753             }
754             ytop = r1y1;
755         } else {
756             ytop = r1y1;
757         }
758
759         /*
760          * Now see if we've hit an intersecting band. The two bands only
761          * intersect if ybot > ytop
762          */
763         ybot = MIN(r1->y2, r2->y2);
764         if (ybot > ytop) {
765             curBand = newReg->data->numRects;
766             if (!(* overlapFunc)(newReg,
767                                  r1, r1BandEnd,
768                                  r2, r2BandEnd,
769                                  ytop, ybot,
770                                  pOverlap))
771                 goto bail;
772             Coalesce(newReg, prevBand, curBand);
773         }
774
775         /*
776          * If we've finished with a band (y2 == ybot) we skip forward
777          * in the region to the next band.
778          */
779         if (r1->y2 == ybot) r1 = r1BandEnd;
780         if (r2->y2 == ybot) r2 = r2BandEnd;
781
782     } while (r1 != r1End && r2 != r2End);
783
784     /*
785      * Deal with whichever region (if any) still has rectangles left.
786      *
787      * We only need to worry about banding and coalescing for the very first
788      * band left.  After that, we can just group all remaining boxes,
789      * regardless of how many bands, into one final append to the list.
790      */
791
792     if ((r1 != r1End) && appendNon1) {
793         /* Do first nonOverlap1Func call, which may be able to coalesce */
794         FindBand(r1, r1BandEnd, r1End, r1y1);
795         curBand = newReg->data->numRects;
796         if (!pixman_region_appendNonO(newReg,
797                                       r1, r1BandEnd,
798                                       MAX(r1y1, ybot), r1->y2))
799             goto bail;
800         Coalesce(newReg, prevBand, curBand);
801         /* Just append the rest of the boxes  */
802         AppendRegions(newReg, r1BandEnd, r1End);
803
804     } else if ((r2 != r2End) && appendNon2) {
805         /* Do first nonOverlap2Func call, which may be able to coalesce */
806         FindBand(r2, r2BandEnd, r2End, r2y1);
807         curBand = newReg->data->numRects;
808         if (!pixman_region_appendNonO(newReg,
809                                       r2, r2BandEnd,
810                                       MAX(r2y1, ybot), r2->y2))
811             goto bail;
812         Coalesce(newReg, prevBand, curBand);
813         /* Append rest of boxes */
814         AppendRegions(newReg, r2BandEnd, r2End);
815     }
816
817     if (oldData)
818         free(oldData);
819
820     if (!(numRects = newReg->data->numRects))
821     {
822         freeData(newReg);
823         newReg->data = pixman_region_emptyData;
824     }
825     else if (numRects == 1)
826     {
827         newReg->extents = *PIXREGION_BOXPTR(newReg);
828         freeData(newReg);
829         newReg->data = (region_data_type_t *)NULL;
830     }
831     else
832     {
833         DOWNSIZE(newReg, numRects);
834     }
835
836     return TRUE;
837
838 bail:
839     if (oldData)
840         free(oldData);
841     return pixman_break (newReg);
842 }
843
844 /*-
845  *-----------------------------------------------------------------------
846  * pixman_set_extents --
847  *      Reset the extents of a region to what they should be. Called by
848  *      pixman_region_subtract and pixman_region_intersect as they can't figure it out along the
849  *      way or do so easily, as pixman_region_union can.
850  *
851  * Results:
852  *      None.
853  *
854  * Side Effects:
855  *      The region's 'extents' structure is overwritten.
856  *
857  *-----------------------------------------------------------------------
858  */
859 static void
860 pixman_set_extents (region_type_t *region)
861 {
862     box_type_t *box, *boxEnd;
863
864     if (!region->data)
865         return;
866     if (!region->data->size)
867     {
868         region->extents.x2 = region->extents.x1;
869         region->extents.y2 = region->extents.y1;
870         return;
871     }
872
873     box = PIXREGION_BOXPTR(region);
874     boxEnd = PIXREGION_END(region);
875
876     /*
877      * Since box is the first rectangle in the region, it must have the
878      * smallest y1 and since boxEnd is the last rectangle in the region,
879      * it must have the largest y2, because of banding. Initialize x1 and
880      * x2 from  box and boxEnd, resp., as good things to initialize them
881      * to...
882      */
883     region->extents.x1 = box->x1;
884     region->extents.y1 = box->y1;
885     region->extents.x2 = boxEnd->x2;
886     region->extents.y2 = boxEnd->y2;
887
888     assert(region->extents.y1 < region->extents.y2);
889     while (box <= boxEnd) {
890         if (box->x1 < region->extents.x1)
891             region->extents.x1 = box->x1;
892         if (box->x2 > region->extents.x2)
893             region->extents.x2 = box->x2;
894         box++;
895     };
896
897     assert(region->extents.x1 < region->extents.x2);
898 }
899
900 /*======================================================================
901  *          Region Intersection
902  *====================================================================*/
903 /*-
904  *-----------------------------------------------------------------------
905  * pixman_region_intersectO --
906  *      Handle an overlapping band for pixman_region_intersect.
907  *
908  * Results:
909  *      TRUE if successful.
910  *
911  * Side Effects:
912  *      Rectangles may be added to the region.
913  *
914  *-----------------------------------------------------------------------
915  */
916 /*ARGSUSED*/
917 static pixman_bool_t
918 pixman_region_intersectO (region_type_t *region,
919                           box_type_t    *r1,
920                           box_type_t    *r1End,
921                           box_type_t    *r2,
922                           box_type_t    *r2End,
923                           int                y1,
924                           int                y2,
925                           int               *pOverlap)
926 {
927     int         x1;
928     int         x2;
929     box_type_t *        pNextRect;
930
931     pNextRect = PIXREGION_TOP(region);
932
933     assert(y1 < y2);
934     assert(r1 != r1End && r2 != r2End);
935
936     do {
937         x1 = MAX(r1->x1, r2->x1);
938         x2 = MIN(r1->x2, r2->x2);
939
940         /*
941          * If there's any overlap between the two rectangles, add that
942          * overlap to the new region.
943          */
944         if (x1 < x2)
945             NEWRECT(region, pNextRect, x1, y1, x2, y2);
946
947         /*
948          * Advance the pointer(s) with the leftmost right side, since the next
949          * rectangle on that list may still overlap the other region's
950          * current rectangle.
951          */
952         if (r1->x2 == x2) {
953             r1++;
954         }
955         if (r2->x2 == x2) {
956             r2++;
957         }
958     } while ((r1 != r1End) && (r2 != r2End));
959
960     return TRUE;
961 }
962
963 PIXMAN_EXPORT pixman_bool_t
964 PREFIX(_intersect) (region_type_t *     newReg,
965                          region_type_t *        reg1,
966                          region_type_t *        reg2)
967 {
968     good(reg1);
969     good(reg2);
970     good(newReg);
971    /* check for trivial reject */
972     if (PIXREGION_NIL(reg1)  || PIXREGION_NIL(reg2) ||
973         !EXTENTCHECK(&reg1->extents, &reg2->extents))
974     {
975         /* Covers about 20% of all cases */
976         freeData(newReg);
977         newReg->extents.x2 = newReg->extents.x1;
978         newReg->extents.y2 = newReg->extents.y1;
979         if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2))
980         {
981             newReg->data = pixman_brokendata;
982             return FALSE;
983         }
984         else
985             newReg->data = pixman_region_emptyData;
986     }
987     else if (!reg1->data && !reg2->data)
988     {
989         /* Covers about 80% of cases that aren't trivially rejected */
990         newReg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1);
991         newReg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1);
992         newReg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2);
993         newReg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2);
994         freeData(newReg);
995         newReg->data = (region_data_type_t *)NULL;
996     }
997     else if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
998     {
999         return PREFIX(_copy) (newReg, reg1);
1000     }
1001     else if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
1002     {
1003         return PREFIX(_copy) (newReg, reg2);
1004     }
1005     else if (reg1 == reg2)
1006     {
1007         return PREFIX(_copy) (newReg, reg1);
1008     }
1009     else
1010     {
1011         /* General purpose intersection */
1012         int overlap; /* result ignored */
1013         if (!pixman_op(newReg, reg1, reg2, pixman_region_intersectO, FALSE, FALSE,
1014                         &overlap))
1015             return FALSE;
1016         pixman_set_extents(newReg);
1017     }
1018
1019     good(newReg);
1020     return(TRUE);
1021 }
1022
1023 #define MERGERECT(r)                                            \
1024 {                                                               \
1025     if (r->x1 <= x2) {                                          \
1026         /* Merge with current rectangle */                      \
1027         if (r->x1 < x2) *pOverlap = TRUE;                               \
1028         if (x2 < r->x2) x2 = r->x2;                             \
1029     } else {                                                    \
1030         /* Add current rectangle, start new one */              \
1031         NEWRECT(region, pNextRect, x1, y1, x2, y2);             \
1032         x1 = r->x1;                                             \
1033         x2 = r->x2;                                             \
1034     }                                                           \
1035     r++;                                                        \
1036 }
1037
1038 /*======================================================================
1039  *          Region Union
1040  *====================================================================*/
1041
1042 /*-
1043  *-----------------------------------------------------------------------
1044  * pixman_region_unionO --
1045  *      Handle an overlapping band for the union operation. Picks the
1046  *      left-most rectangle each time and merges it into the region.
1047  *
1048  * Results:
1049  *      TRUE if successful.
1050  *
1051  * Side Effects:
1052  *      region is overwritten.
1053  *      pOverlap is set to TRUE if any boxes overlap.
1054  *
1055  *-----------------------------------------------------------------------
1056  */
1057 static pixman_bool_t
1058 pixman_region_unionO (
1059     region_type_t        *region,
1060     box_type_t *r1,
1061     box_type_t *r1End,
1062     box_type_t *r2,
1063     box_type_t *r2End,
1064     int   y1,
1065     int   y2,
1066     int           *pOverlap)
1067 {
1068     box_type_t *     pNextRect;
1069     int        x1;     /* left and right side of current union */
1070     int        x2;
1071
1072     assert (y1 < y2);
1073     assert(r1 != r1End && r2 != r2End);
1074
1075     pNextRect = PIXREGION_TOP(region);
1076
1077     /* Start off current rectangle */
1078     if (r1->x1 < r2->x1)
1079     {
1080         x1 = r1->x1;
1081         x2 = r1->x2;
1082         r1++;
1083     }
1084     else
1085     {
1086         x1 = r2->x1;
1087         x2 = r2->x2;
1088         r2++;
1089     }
1090     while (r1 != r1End && r2 != r2End)
1091     {
1092         if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
1093     }
1094
1095     /* Finish off whoever (if any) is left */
1096     if (r1 != r1End)
1097     {
1098         do
1099         {
1100             MERGERECT(r1);
1101         } while (r1 != r1End);
1102     }
1103     else if (r2 != r2End)
1104     {
1105         do
1106         {
1107             MERGERECT(r2);
1108         } while (r2 != r2End);
1109     }
1110
1111     /* Add current rectangle */
1112     NEWRECT(region, pNextRect, x1, y1, x2, y2);
1113
1114     return TRUE;
1115 }
1116
1117 /* Convenience function for performing union of region with a
1118  * single rectangle
1119  */
1120 PIXMAN_EXPORT pixman_bool_t
1121 PREFIX(_union_rect) (region_type_t *dest,
1122                           region_type_t *source,
1123                           int x, int y,
1124                           unsigned int width, unsigned int height)
1125 {
1126     region_type_t region;
1127
1128     if (!width || !height)
1129         return PREFIX(_copy) (dest, source);
1130     region.data = NULL;
1131     region.extents.x1 = x;
1132     region.extents.y1 = y;
1133     region.extents.x2 = x + width;
1134     region.extents.y2 = y + height;
1135
1136     return PREFIX(_union) (dest, source, &region);
1137 }
1138
1139 PIXMAN_EXPORT pixman_bool_t
1140 PREFIX(_union) (region_type_t *newReg,
1141                      region_type_t *reg1,
1142                      region_type_t *reg2)
1143 {
1144     int overlap; /* result ignored */
1145
1146     /* Return TRUE if some overlap
1147      * between reg1, reg2
1148      */
1149     good(reg1);
1150     good(reg2);
1151     good(newReg);
1152     /*  checks all the simple cases */
1153
1154     /*
1155      * Region 1 and 2 are the same
1156      */
1157     if (reg1 == reg2)
1158     {
1159         return PREFIX(_copy) (newReg, reg1);
1160     }
1161
1162     /*
1163      * Region 1 is empty
1164      */
1165     if (PIXREGION_NIL(reg1))
1166     {
1167         if (PIXREGION_NAR(reg1))
1168             return pixman_break (newReg);
1169         if (newReg != reg2)
1170             return PREFIX(_copy) (newReg, reg2);
1171         return TRUE;
1172     }
1173
1174     /*
1175      * Region 2 is empty
1176      */
1177     if (PIXREGION_NIL(reg2))
1178     {
1179         if (PIXREGION_NAR(reg2))
1180             return pixman_break (newReg);
1181         if (newReg != reg1)
1182             return PREFIX(_copy) (newReg, reg1);
1183         return TRUE;
1184     }
1185
1186     /*
1187      * Region 1 completely subsumes region 2
1188      */
1189     if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
1190     {
1191         if (newReg != reg1)
1192             return PREFIX(_copy) (newReg, reg1);
1193         return TRUE;
1194     }
1195
1196     /*
1197      * Region 2 completely subsumes region 1
1198      */
1199     if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
1200     {
1201         if (newReg != reg2)
1202             return PREFIX(_copy) (newReg, reg2);
1203         return TRUE;
1204     }
1205
1206     if (!pixman_op(newReg, reg1, reg2, pixman_region_unionO, TRUE, TRUE, &overlap))
1207         return FALSE;
1208
1209     newReg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1);
1210     newReg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1);
1211     newReg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2);
1212     newReg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2);
1213     good(newReg);
1214     return TRUE;
1215 }
1216
1217 /*======================================================================
1218  *          Batch Rectangle Union
1219  *====================================================================*/
1220
1221 #define ExchangeRects(a, b) \
1222 {                           \
1223     box_type_t     t;       \
1224     t = rects[a];           \
1225     rects[a] = rects[b];    \
1226     rects[b] = t;           \
1227 }
1228
1229 static void
1230 QuickSortRects(
1231     box_type_t     rects[],
1232     int        numRects)
1233 {
1234     int y1;
1235     int x1;
1236     int        i, j;
1237     box_type_t *r;
1238
1239     /* Always called with numRects > 1 */
1240
1241     do
1242     {
1243         if (numRects == 2)
1244         {
1245             if (rects[0].y1 > rects[1].y1 ||
1246                     (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
1247                 ExchangeRects(0, 1);
1248             return;
1249         }
1250
1251         /* Choose partition element, stick in location 0 */
1252         ExchangeRects(0, numRects >> 1);
1253         y1 = rects[0].y1;
1254         x1 = rects[0].x1;
1255
1256         /* Partition array */
1257         i = 0;
1258         j = numRects;
1259         do
1260         {
1261             r = &(rects[i]);
1262             do
1263             {
1264                 r++;
1265                 i++;
1266             } while (i != numRects &&
1267                      (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
1268             r = &(rects[j]);
1269             do
1270             {
1271                 r--;
1272                 j--;
1273             } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
1274             if (i < j)
1275                 ExchangeRects(i, j);
1276         } while (i < j);
1277
1278         /* Move partition element back to middle */
1279         ExchangeRects(0, j);
1280
1281         /* Recurse */
1282         if (numRects-j-1 > 1)
1283             QuickSortRects(&rects[j+1], numRects-j-1);
1284         numRects = j;
1285     } while (numRects > 1);
1286 }
1287
1288 /*-
1289  *-----------------------------------------------------------------------
1290  * pixman_region_validate --
1291  *
1292  *      Take a ``region'' which is a non-y-x-banded random collection of
1293  *      rectangles, and compute a nice region which is the union of all the
1294  *      rectangles.
1295  *
1296  * Results:
1297  *      TRUE if successful.
1298  *
1299  * Side Effects:
1300  *      The passed-in ``region'' may be modified.
1301  *      pOverlap set to TRUE if any retangles overlapped,
1302  *      else FALSE;
1303  *
1304  * Strategy:
1305  *      Step 1. Sort the rectangles into ascending order with primary key y1
1306  *              and secondary key x1.
1307  *
1308  *      Step 2. Split the rectangles into the minimum number of proper y-x
1309  *              banded regions.  This may require horizontally merging
1310  *              rectangles, and vertically coalescing bands.  With any luck,
1311  *              this step in an identity transformation (ala the Box widget),
1312  *              or a coalescing into 1 box (ala Menus).
1313  *
1314  *      Step 3. Merge the separate regions down to a single region by calling
1315  *              pixman_region_union.  Maximize the work each pixman_region_union call does by using
1316  *              a binary merge.
1317  *
1318  *-----------------------------------------------------------------------
1319  */
1320
1321 static pixman_bool_t
1322 validate (region_type_t * badreg,
1323           int *pOverlap)
1324 {
1325     /* Descriptor for regions under construction  in Step 2. */
1326     typedef struct {
1327         region_type_t   reg;
1328         int         prevBand;
1329         int         curBand;
1330     } RegionInfo;
1331
1332     RegionInfo stack_regions[64];
1333
1334              int        numRects;   /* Original numRects for badreg         */
1335              RegionInfo *ri;        /* Array of current regions             */
1336              int        numRI;      /* Number of entries used in ri         */
1337              int        sizeRI;     /* Number of entries available in ri    */
1338              int        i;          /* Index into rects                     */
1339     int j;          /* Index into ri                        */
1340     RegionInfo *rit;       /* &ri[j]                                */
1341     region_type_t *  reg;        /* ri[j].reg                       */
1342     box_type_t *        box;        /* Current box in rects                 */
1343     box_type_t *        riBox;      /* Last box in ri[j].reg                */
1344     region_type_t *  hreg;       /* ri[j_half].reg                          */
1345     pixman_bool_t ret = TRUE;
1346
1347     *pOverlap = FALSE;
1348     if (!badreg->data)
1349     {
1350         good(badreg);
1351         return TRUE;
1352     }
1353     numRects = badreg->data->numRects;
1354     if (!numRects)
1355     {
1356         if (PIXREGION_NAR(badreg))
1357             return FALSE;
1358         good(badreg);
1359         return TRUE;
1360     }
1361     if (badreg->extents.x1 < badreg->extents.x2)
1362     {
1363         if ((numRects) == 1)
1364         {
1365             freeData(badreg);
1366             badreg->data = (region_data_type_t *) NULL;
1367         }
1368         else
1369         {
1370             DOWNSIZE(badreg, numRects);
1371         }
1372         good(badreg);
1373         return TRUE;
1374     }
1375
1376     /* Step 1: Sort the rects array into ascending (y1, x1) order */
1377     QuickSortRects(PIXREGION_BOXPTR(badreg), numRects);
1378
1379     /* Step 2: Scatter the sorted array into the minimum number of regions */
1380
1381     /* Set up the first region to be the first rectangle in badreg */
1382     /* Note that step 2 code will never overflow the ri[0].reg rects array */
1383     ri = stack_regions;
1384     sizeRI = sizeof (stack_regions) / sizeof (stack_regions[0]);
1385     numRI = 1;
1386     ri[0].prevBand = 0;
1387     ri[0].curBand = 0;
1388     ri[0].reg = *badreg;
1389     box = PIXREGION_BOXPTR(&ri[0].reg);
1390     ri[0].reg.extents = *box;
1391     ri[0].reg.data->numRects = 1;
1392     badreg->extents = *pixman_region_emptyBox;
1393     badreg->data = pixman_region_emptyData;
1394
1395     /* Now scatter rectangles into the minimum set of valid regions.  If the
1396        next rectangle to be added to a region would force an existing rectangle
1397        in the region to be split up in order to maintain y-x banding, just
1398        forget it.  Try the next region.  If it doesn't fit cleanly into any
1399        region, make a new one. */
1400
1401     for (i = numRects; --i > 0;)
1402     {
1403         box++;
1404         /* Look for a region to append box to */
1405         for (j = numRI, rit = ri; --j >= 0; rit++)
1406         {
1407             reg = &rit->reg;
1408             riBox = PIXREGION_END(reg);
1409
1410             if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
1411             {
1412                 /* box is in same band as riBox.  Merge or append it */
1413                 if (box->x1 <= riBox->x2)
1414                 {
1415                     /* Merge it with riBox */
1416                     if (box->x1 < riBox->x2) *pOverlap = TRUE;
1417                     if (box->x2 > riBox->x2) riBox->x2 = box->x2;
1418                 }
1419                 else
1420                 {
1421                     RECTALLOC_BAIL(reg, 1, bail);
1422                     *PIXREGION_TOP(reg) = *box;
1423                     reg->data->numRects++;
1424                 }
1425                 goto NextRect;   /* So sue me */
1426             }
1427             else if (box->y1 >= riBox->y2)
1428             {
1429                 /* Put box into new band */
1430                 if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
1431                 if (reg->extents.x1 > box->x1)   reg->extents.x1 = box->x1;
1432                 Coalesce(reg, rit->prevBand, rit->curBand);
1433                 rit->curBand = reg->data->numRects;
1434                 RECTALLOC_BAIL(reg, 1, bail);
1435                 *PIXREGION_TOP(reg) = *box;
1436                 reg->data->numRects++;
1437                 goto NextRect;
1438             }
1439             /* Well, this region was inappropriate.  Try the next one. */
1440         } /* for j */
1441
1442         /* Uh-oh.  No regions were appropriate.  Create a new one. */
1443         if (sizeRI == numRI)
1444         {
1445             size_t data_size;
1446             
1447             /* Oops, allocate space for new region information */
1448             sizeRI <<= 1;
1449
1450             data_size = sizeRI * sizeof(RegionInfo);
1451             if (data_size / sizeRI != sizeof(RegionInfo))
1452                 goto bail;
1453             if (ri == stack_regions) {
1454                 rit = malloc (data_size);
1455                 if (!rit)
1456                     goto bail;
1457                 memcpy (rit, ri, numRI * sizeof (RegionInfo));
1458             } else {
1459                 rit = (RegionInfo *) realloc(ri, data_size);
1460                 if (!rit)
1461                     goto bail;
1462             }
1463             ri = rit;
1464             rit = &ri[numRI];
1465         }
1466         numRI++;
1467         rit->prevBand = 0;
1468         rit->curBand = 0;
1469         rit->reg.extents = *box;
1470         rit->reg.data = (region_data_type_t *)NULL;
1471         if (!pixman_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
1472             goto bail;
1473 NextRect: ;
1474     } /* for i */
1475
1476     /* Make a final pass over each region in order to Coalesce and set
1477        extents.x2 and extents.y2 */
1478
1479     for (j = numRI, rit = ri; --j >= 0; rit++)
1480     {
1481         reg = &rit->reg;
1482         riBox = PIXREGION_END(reg);
1483         reg->extents.y2 = riBox->y2;
1484         if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
1485         Coalesce(reg, rit->prevBand, rit->curBand);
1486         if (reg->data->numRects == 1) /* keep unions happy below */
1487         {
1488             freeData(reg);
1489             reg->data = (region_data_type_t *)NULL;
1490         }
1491     }
1492
1493     /* Step 3: Union all regions into a single region */
1494     while (numRI > 1)
1495     {
1496         int half = numRI/2;
1497         for (j = numRI & 1; j < (half + (numRI & 1)); j++)
1498         {
1499             reg = &ri[j].reg;
1500             hreg = &ri[j+half].reg;
1501             if (!pixman_op(reg, reg, hreg, pixman_region_unionO, TRUE, TRUE, pOverlap))
1502                 ret = FALSE;
1503             if (hreg->extents.x1 < reg->extents.x1)
1504                 reg->extents.x1 = hreg->extents.x1;
1505             if (hreg->extents.y1 < reg->extents.y1)
1506                 reg->extents.y1 = hreg->extents.y1;
1507             if (hreg->extents.x2 > reg->extents.x2)
1508                 reg->extents.x2 = hreg->extents.x2;
1509             if (hreg->extents.y2 > reg->extents.y2)
1510                 reg->extents.y2 = hreg->extents.y2;
1511             freeData(hreg);
1512         }
1513         numRI -= half;
1514         if (!ret)
1515             goto bail;
1516     }
1517     *badreg = ri[0].reg;
1518     if (ri != stack_regions)
1519         free(ri);
1520     good(badreg);
1521     return ret;
1522 bail:
1523     for (i = 0; i < numRI; i++)
1524         freeData(&ri[i].reg);
1525     if (ri != stack_regions)
1526         free (ri);
1527
1528     return pixman_break (badreg);
1529 }
1530
1531 /*======================================================================
1532  *                Region Subtraction
1533  *====================================================================*/
1534
1535 /*-
1536  *-----------------------------------------------------------------------
1537  * pixman_region_subtractO --
1538  *      Overlapping band subtraction. x1 is the left-most point not yet
1539  *      checked.
1540  *
1541  * Results:
1542  *      TRUE if successful.
1543  *
1544  * Side Effects:
1545  *      region may have rectangles added to it.
1546  *
1547  *-----------------------------------------------------------------------
1548  */
1549 /*ARGSUSED*/
1550 static pixman_bool_t
1551 pixman_region_subtractO (
1552     region_type_t *     region,
1553     box_type_t *        r1,
1554     box_type_t *                r1End,
1555     box_type_t *        r2,
1556     box_type_t *                r2End,
1557     int         y1,
1558     int         y2,
1559     int         *pOverlap)
1560 {
1561     box_type_t *        pNextRect;
1562     int         x1;
1563
1564     x1 = r1->x1;
1565
1566     assert(y1<y2);
1567     assert(r1 != r1End && r2 != r2End);
1568
1569     pNextRect = PIXREGION_TOP(region);
1570
1571     do
1572     {
1573         if (r2->x2 <= x1)
1574         {
1575             /*
1576              * Subtrahend entirely to left of minuend: go to next subtrahend.
1577              */
1578             r2++;
1579         }
1580         else if (r2->x1 <= x1)
1581         {
1582             /*
1583              * Subtrahend preceeds minuend: nuke left edge of minuend.
1584              */
1585             x1 = r2->x2;
1586             if (x1 >= r1->x2)
1587             {
1588                 /*
1589                  * Minuend completely covered: advance to next minuend and
1590                  * reset left fence to edge of new minuend.
1591                  */
1592                 r1++;
1593                 if (r1 != r1End)
1594                     x1 = r1->x1;
1595             }
1596             else
1597             {
1598                 /*
1599                  * Subtrahend now used up since it doesn't extend beyond
1600                  * minuend
1601                  */
1602                 r2++;
1603             }
1604         }
1605         else if (r2->x1 < r1->x2)
1606         {
1607             /*
1608              * Left part of subtrahend covers part of minuend: add uncovered
1609              * part of minuend to region and skip to next subtrahend.
1610              */
1611             assert(x1<r2->x1);
1612             NEWRECT(region, pNextRect, x1, y1, r2->x1, y2);
1613
1614             x1 = r2->x2;
1615             if (x1 >= r1->x2)
1616             {
1617                 /*
1618                  * Minuend used up: advance to new...
1619                  */
1620                 r1++;
1621                 if (r1 != r1End)
1622                     x1 = r1->x1;
1623             }
1624             else
1625             {
1626                 /*
1627                  * Subtrahend used up
1628                  */
1629                 r2++;
1630             }
1631         }
1632         else
1633         {
1634             /*
1635              * Minuend used up: add any remaining piece before advancing.
1636              */
1637             if (r1->x2 > x1)
1638                 NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
1639             r1++;
1640             if (r1 != r1End)
1641                 x1 = r1->x1;
1642         }
1643     } while ((r1 != r1End) && (r2 != r2End));
1644
1645     /*
1646      * Add remaining minuend rectangles to region.
1647      */
1648     while (r1 != r1End)
1649     {
1650         assert(x1<r1->x2);
1651         NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
1652         r1++;
1653         if (r1 != r1End)
1654             x1 = r1->x1;
1655     }
1656     return TRUE;
1657 }
1658
1659 /*-
1660  *-----------------------------------------------------------------------
1661  * pixman_region_subtract --
1662  *      Subtract regS from regM and leave the result in regD.
1663  *      S stands for subtrahend, M for minuend and D for difference.
1664  *
1665  * Results:
1666  *      TRUE if successful.
1667  *
1668  * Side Effects:
1669  *      regD is overwritten.
1670  *
1671  *-----------------------------------------------------------------------
1672  */
1673 PIXMAN_EXPORT pixman_bool_t
1674 PREFIX(_subtract) (region_type_t *      regD,
1675                        region_type_t *  regM,
1676                        region_type_t *  regS)
1677 {
1678     int overlap; /* result ignored */
1679
1680     good(regM);
1681     good(regS);
1682     good(regD);
1683    /* check for trivial rejects */
1684     if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) ||
1685         !EXTENTCHECK(&regM->extents, &regS->extents))
1686     {
1687         if (PIXREGION_NAR (regS))
1688             return pixman_break (regD);
1689         return PREFIX(_copy) (regD, regM);
1690     }
1691     else if (regM == regS)
1692     {
1693         freeData(regD);
1694         regD->extents.x2 = regD->extents.x1;
1695         regD->extents.y2 = regD->extents.y1;
1696         regD->data = pixman_region_emptyData;
1697         return TRUE;
1698     }
1699
1700     /* Add those rectangles in region 1 that aren't in region 2,
1701        do yucky substraction for overlaps, and
1702        just throw away rectangles in region 2 that aren't in region 1 */
1703     if (!pixman_op(regD, regM, regS, pixman_region_subtractO, TRUE, FALSE, &overlap))
1704         return FALSE;
1705
1706     /*
1707      * Can't alter RegD's extents before we call pixman_op because
1708      * it might be one of the source regions and pixman_op depends
1709      * on the extents of those regions being unaltered. Besides, this
1710      * way there's no checking against rectangles that will be nuked
1711      * due to coalescing, so we have to examine fewer rectangles.
1712      */
1713     pixman_set_extents(regD);
1714     good(regD);
1715     return TRUE;
1716 }
1717
1718 /*======================================================================
1719  *          Region Inversion
1720  *====================================================================*/
1721
1722 /*-
1723  *-----------------------------------------------------------------------
1724  * pixman_region_inverse --
1725  *      Take a region and a box and return a region that is everything
1726  *      in the box but not in the region. The careful reader will note
1727  *      that this is the same as subtracting the region from the box...
1728  *
1729  * Results:
1730  *      TRUE.
1731  *
1732  * Side Effects:
1733  *      newReg is overwritten.
1734  *
1735  *-----------------------------------------------------------------------
1736  */
1737 pixman_bool_t
1738 PIXMAN_EXPORT PREFIX(_inverse) (region_type_t *           newReg,       /* Destination region */
1739                       region_type_t *     reg1,         /* Region to invert */
1740                       box_type_t *        invRect)      /* Bounding box for inversion */
1741 {
1742     region_type_t         invReg;       /* Quick and dirty region made from the
1743                                  * bounding box */
1744     int   overlap;      /* result ignored */
1745
1746     good(reg1);
1747     good(newReg);
1748    /* check for trivial rejects */
1749     if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, &reg1->extents))
1750     {
1751         if (PIXREGION_NAR(reg1))
1752             return pixman_break (newReg);
1753         newReg->extents = *invRect;
1754         freeData(newReg);
1755         newReg->data = (region_data_type_t *)NULL;
1756         return TRUE;
1757     }
1758
1759     /* Add those rectangles in region 1 that aren't in region 2,
1760        do yucky substraction for overlaps, and
1761        just throw away rectangles in region 2 that aren't in region 1 */
1762     invReg.extents = *invRect;
1763     invReg.data = (region_data_type_t *)NULL;
1764     if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, TRUE, FALSE, &overlap))
1765         return FALSE;
1766
1767     /*
1768      * Can't alter newReg's extents before we call pixman_op because
1769      * it might be one of the source regions and pixman_op depends
1770      * on the extents of those regions being unaltered. Besides, this
1771      * way there's no checking against rectangles that will be nuked
1772      * due to coalescing, so we have to examine fewer rectangles.
1773      */
1774     pixman_set_extents(newReg);
1775     good(newReg);
1776     return TRUE;
1777 }
1778
1779 /*
1780  *   RectIn(region, rect)
1781  *   This routine takes a pointer to a region and a pointer to a box
1782  *   and determines if the box is outside/inside/partly inside the region.
1783  *
1784  *   The idea is to travel through the list of rectangles trying to cover the
1785  *   passed box with them. Anytime a piece of the rectangle isn't covered
1786  *   by a band of rectangles, partOut is set TRUE. Any time a rectangle in
1787  *   the region covers part of the box, partIn is set TRUE. The process ends
1788  *   when either the box has been completely covered (we reached a band that
1789  *   doesn't overlap the box, partIn is TRUE and partOut is false), the
1790  *   box has been partially covered (partIn == partOut == TRUE -- because of
1791  *   the banding, the first time this is true we know the box is only
1792  *   partially in the region) or is outside the region (we reached a band
1793  *   that doesn't overlap the box at all and partIn is false)
1794  */
1795
1796 pixman_region_overlap_t
1797 PIXMAN_EXPORT PREFIX(_contains_rectangle) (region_type_t *  region,
1798                                  box_type_t *     prect)
1799 {
1800     int x;
1801     int y;
1802     box_type_t *     pbox;
1803     box_type_t *     pboxEnd;
1804     int                 partIn, partOut;
1805     int                 numRects;
1806
1807     good(region);
1808     numRects = PIXREGION_NUM_RECTS(region);
1809     /* useful optimization */
1810     if (!numRects || !EXTENTCHECK(&region->extents, prect))
1811         return(PIXMAN_REGION_OUT);
1812
1813     if (numRects == 1)
1814     {
1815         /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
1816         if (SUBSUMES(&region->extents, prect))
1817             return(PIXMAN_REGION_IN);
1818         else
1819             return(PIXMAN_REGION_PART);
1820     }
1821
1822     partOut = FALSE;
1823     partIn = FALSE;
1824
1825     /* (x,y) starts at upper left of rect, moving to the right and down */
1826     x = prect->x1;
1827     y = prect->y1;
1828
1829     /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
1830     for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
1831          pbox != pboxEnd;
1832          pbox++)
1833     {
1834
1835         if (pbox->y2 <= y)
1836            continue;    /* getting up to speed or skipping remainder of band */
1837
1838         if (pbox->y1 > y)
1839         {
1840            partOut = TRUE;      /* missed part of rectangle above */
1841            if (partIn || (pbox->y1 >= prect->y2))
1842               break;
1843            y = pbox->y1;        /* x guaranteed to be == prect->x1 */
1844         }
1845
1846         if (pbox->x2 <= x)
1847            continue;            /* not far enough over yet */
1848
1849         if (pbox->x1 > x)
1850         {
1851            partOut = TRUE;      /* missed part of rectangle to left */
1852            if (partIn)
1853               break;
1854         }
1855
1856         if (pbox->x1 < prect->x2)
1857         {
1858             partIn = TRUE;      /* definitely overlap */
1859             if (partOut)
1860                break;
1861         }
1862
1863         if (pbox->x2 >= prect->x2)
1864         {
1865            y = pbox->y2;        /* finished with this band */
1866            if (y >= prect->y2)
1867               break;
1868            x = prect->x1;       /* reset x out to left again */
1869         }
1870         else
1871         {
1872             /*
1873              * Because boxes in a band are maximal width, if the first box
1874              * to overlap the rectangle doesn't completely cover it in that
1875              * band, the rectangle must be partially out, since some of it
1876              * will be uncovered in that band. partIn will have been set true
1877              * by now...
1878              */
1879             partOut = TRUE;
1880             break;
1881         }
1882     }
1883
1884     if (partIn)
1885     {
1886         if (y < prect->y2)
1887             return PIXMAN_REGION_PART;
1888         else
1889             return PIXMAN_REGION_IN;
1890     }
1891     else
1892     {
1893         return PIXMAN_REGION_OUT;
1894     }
1895 }
1896
1897 /* PREFIX(_translate) (region, x, y)
1898    translates in place
1899 */
1900
1901 PIXMAN_EXPORT void
1902 PREFIX(_translate) (region_type_t * region, int x, int y)
1903 {
1904     int x1, x2, y1, y2;
1905     int nbox;
1906     box_type_t * pbox;
1907
1908     good(region);
1909     region->extents.x1 = x1 = region->extents.x1 + x;
1910     region->extents.y1 = y1 = region->extents.y1 + y;
1911     region->extents.x2 = x2 = region->extents.x2 + x;
1912     region->extents.y2 = y2 = region->extents.y2 + y;
1913     if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0)
1914     {
1915         if (region->data && (nbox = region->data->numRects))
1916         {
1917             for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
1918             {
1919                 pbox->x1 += x;
1920                 pbox->y1 += y;
1921                 pbox->x2 += x;
1922                 pbox->y2 += y;
1923             }
1924         }
1925         return;
1926     }
1927     if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
1928     {
1929         region->extents.x2 = region->extents.x1;
1930         region->extents.y2 = region->extents.y1;
1931         freeData(region);
1932         region->data = pixman_region_emptyData;
1933         return;
1934     }
1935     if (x1 < SHRT_MIN)
1936         region->extents.x1 = SHRT_MIN;
1937     else if (x2 > SHRT_MAX)
1938         region->extents.x2 = SHRT_MAX;
1939     if (y1 < SHRT_MIN)
1940         region->extents.y1 = SHRT_MIN;
1941     else if (y2 > SHRT_MAX)
1942         region->extents.y2 = SHRT_MAX;
1943     if (region->data && (nbox = region->data->numRects))
1944     {
1945         box_type_t * pboxout;
1946
1947         for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
1948         {
1949             pboxout->x1 = x1 = pbox->x1 + x;
1950             pboxout->y1 = y1 = pbox->y1 + y;
1951             pboxout->x2 = x2 = pbox->x2 + x;
1952             pboxout->y2 = y2 = pbox->y2 + y;
1953             if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|
1954                  (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
1955             {
1956                 region->data->numRects--;
1957                 continue;
1958             }
1959             if (x1 < SHRT_MIN)
1960                 pboxout->x1 = SHRT_MIN;
1961             else if (x2 > SHRT_MAX)
1962                 pboxout->x2 = SHRT_MAX;
1963             if (y1 < SHRT_MIN)
1964                 pboxout->y1 = SHRT_MIN;
1965             else if (y2 > SHRT_MAX)
1966                 pboxout->y2 = SHRT_MAX;
1967             pboxout++;
1968         }
1969         if (pboxout != pbox)
1970         {
1971             if (region->data->numRects == 1)
1972             {
1973                 region->extents = *PIXREGION_BOXPTR(region);
1974                 freeData(region);
1975                 region->data = (region_data_type_t *)NULL;
1976             }
1977             else
1978                 pixman_set_extents(region);
1979         }
1980     }
1981 }
1982
1983 PIXMAN_EXPORT void
1984 PREFIX(_reset) (region_type_t *region, box_type_t *box)
1985 {
1986     good(region);
1987     assert(box->x1<=box->x2);
1988     assert(box->y1<=box->y2);
1989     region->extents = *box;
1990     freeData(region);
1991     region->data = (region_data_type_t *)NULL;
1992 }
1993
1994 /* box is "return" value */
1995 PIXMAN_EXPORT int
1996 PREFIX(_contains_point) (region_type_t * region,
1997                              int x, int y,
1998                              box_type_t * box)
1999 {
2000     box_type_t *pbox, *pboxEnd;
2001     int numRects;
2002
2003     good(region);
2004     numRects = PIXREGION_NUM_RECTS(region);
2005     if (!numRects || !INBOX(&region->extents, x, y))
2006         return(FALSE);
2007     if (numRects == 1)
2008     {
2009         if (box)
2010             *box = region->extents;
2011
2012         return(TRUE);
2013     }
2014     for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
2015          pbox != pboxEnd;
2016          pbox++)
2017     {
2018         if (y >= pbox->y2)
2019            continue;            /* not there yet */
2020         if ((y < pbox->y1) || (x < pbox->x1))
2021            break;               /* missed it */
2022         if (x >= pbox->x2)
2023            continue;            /* not there yet */
2024
2025         if (box)
2026             *box = *pbox;
2027
2028         return(TRUE);
2029     }
2030     return(FALSE);
2031 }
2032
2033 PIXMAN_EXPORT int
2034 PREFIX(_not_empty) (region_type_t * region)
2035 {
2036     good(region);
2037     return(!PIXREGION_NIL(region));
2038 }
2039
2040 PIXMAN_EXPORT box_type_t *
2041 PREFIX(_extents) (region_type_t * region)
2042 {
2043     good(region);
2044     return(&region->extents);
2045 }
2046
2047 /*
2048     Clip a list of scanlines to a region.  The caller has allocated the
2049     space.  FSorted is non-zero if the scanline origins are in ascending
2050     order.
2051     returns the number of new, clipped scanlines.
2052 */
2053
2054 PIXMAN_EXPORT pixman_bool_t
2055 PREFIX(_selfcheck) (reg)
2056     region_type_t * reg;
2057 {
2058     int i, numRects;
2059
2060     if ((reg->extents.x1 > reg->extents.x2) ||
2061         (reg->extents.y1 > reg->extents.y2))
2062         return FALSE;
2063     numRects = PIXREGION_NUM_RECTS(reg);
2064     if (!numRects)
2065         return ((reg->extents.x1 == reg->extents.x2) &&
2066                 (reg->extents.y1 == reg->extents.y2) &&
2067                 (reg->data->size || (reg->data == pixman_region_emptyData)));
2068     else if (numRects == 1)
2069         return (!reg->data);
2070     else
2071     {
2072         box_type_t * pboxP, * pboxN;
2073         box_type_t box;
2074
2075         pboxP = PIXREGION_RECTS(reg);
2076         box = *pboxP;
2077         box.y2 = pboxP[numRects-1].y2;
2078         pboxN = pboxP + 1;
2079         for (i = numRects; --i > 0; pboxP++, pboxN++)
2080         {
2081             if ((pboxN->x1 >= pboxN->x2) ||
2082                 (pboxN->y1 >= pboxN->y2))
2083                 return FALSE;
2084             if (pboxN->x1 < box.x1)
2085                 box.x1 = pboxN->x1;
2086             if (pboxN->x2 > box.x2)
2087                 box.x2 = pboxN->x2;
2088             if ((pboxN->y1 < pboxP->y1) ||
2089                 ((pboxN->y1 == pboxP->y1) &&
2090                  ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
2091                 return FALSE;
2092         }
2093         return ((box.x1 == reg->extents.x1) &&
2094                 (box.x2 == reg->extents.x2) &&
2095                 (box.y1 == reg->extents.y1) &&
2096                 (box.y2 == reg->extents.y2));
2097     }
2098 }
2099
2100 PIXMAN_EXPORT pixman_bool_t
2101 PREFIX(_init_rects) (region_type_t *region,
2102                      box_type_t *boxes, int count)
2103 {
2104     int overlap;
2105
2106     /* if it's 1, then we just want to set the extents, so call
2107      * the existing method. */
2108     if (count == 1) {
2109        PREFIX(_init_rect) (region,
2110                                boxes[0].x1,
2111                                boxes[0].y1,
2112                                boxes[0].x2 - boxes[0].x1,
2113                                boxes[0].y2 - boxes[0].y1);
2114        return TRUE;
2115     }
2116
2117     PREFIX(_init) (region);
2118
2119     /* if it's 0, don't call pixman_rect_alloc -- 0 rectangles is
2120      * a special case, and causing pixman_rect_alloc would cause
2121      * us to leak memory (because the 0-rect case should be the
2122      * static pixman_region_emptyData data).
2123      */
2124     if (count == 0)
2125         return TRUE;
2126
2127     if (!pixman_rect_alloc(region, count))
2128         return FALSE;
2129
2130     /* Copy in the rects */
2131     memcpy (PIXREGION_RECTS(region), boxes, sizeof(box_type_t) * count);
2132     region->data->numRects = count;
2133
2134     /* Validate */
2135     region->extents.x1 = region->extents.x2 = 0;
2136     return validate (region, &overlap);
2137 }