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