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