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