1 /***********************************************************
3 Copyright 1987, 1988, 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1987, 1988, 1989 by
26 Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
54 #include "pixman-private.h"
57 typedef struct pixman_region16_point {
59 } pixman_region16_point_t;
61 #define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
63 #define PIXREGION_NAR(reg) ((reg)->data == pixman_brokendata)
64 #define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
65 #define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
66 #define PIXREGION_RECTS(reg) ((reg)->data ? (pixman_box16_t *)((reg)->data + 1) \
68 #define PIXREGION_BOXPTR(reg) ((pixman_box16_t *)((reg)->data + 1))
69 #define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
70 #define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
71 #define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
75 #ifdef DEBUG_PIXREGION
76 #define assert(expr) {if (!(expr)) \
77 FatalError("Assertion failed file %s, line %d: expr\n", \
78 __FILE__, __LINE__); }
83 #define good(reg) assert(pixman_region_selfcheck(reg))
86 #define MIN(a,b) ((a) < (b) ? (a) : (b))
88 #define MAX(a,b) ((a) > (b) ? (a) : (b))
90 static const pixman_box16_t _pixman_region_emptyBox = {0, 0, 0, 0};
91 static const pixman_region16_data_t _pixman_region_emptyData = {0, 0};
92 static const pixman_region16_data_t _pixman_brokendata = {0, 0};
94 static pixman_box16_t *pixman_region_emptyBox = (pixman_box16_t *)&_pixman_region_emptyBox;
95 static pixman_region16_data_t *pixman_region_emptyData = (pixman_region16_data_t *)&_pixman_region_emptyData;
96 static pixman_region16_data_t *pixman_brokendata = (pixman_region16_data_t *)&_pixman_brokendata;
98 /* This function exists only to make it possible to preserve the X ABI - it should
99 * go away at first opportunity.
101 * The problem is that the X ABI exports the three structs and has used
102 * them through macros. So the X server calls this function with
103 * the addresses of those structs which makes the existing code continue to
107 pixman_region_set_static_pointers (pixman_box16_t *empty_box,
108 pixman_region16_data_t *empty_data,
109 pixman_region16_data_t *broken_data)
111 pixman_region_emptyBox = empty_box;
112 pixman_region_emptyData = empty_data;
113 pixman_brokendata = broken_data;
117 pixman_break (pixman_region16_t *pReg);
120 * The functions in this file implement the Region abstraction used extensively
121 * throughout the X11 sample server. A Region is simply a set of disjoint
122 * (non-overlapping) rectangles, plus an "extent" rectangle which is the
123 * smallest single rectangle that contains all the non-overlapping rectangles.
125 * A Region is implemented as a "y-x-banded" array of rectangles. This array
126 * imposes two degrees of order. First, all rectangles are sorted by top side
127 * y coordinate first (y1), and then by left side x coordinate (x1).
129 * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
130 * band has the same top y coordinate (y1), and each has the same bottom y
131 * coordinate (y2). Thus all rectangles in a band differ only in their left
132 * and right side (x1 and x2). Bands are implicit in the array of rectangles:
133 * there is no separate list of band start pointers.
135 * The y-x band representation does not minimize rectangles. In particular,
136 * if a rectangle vertically crosses a band (the rectangle has scanlines in
137 * the y1 to y2 area spanned by the band), then the rectangle may be broken
138 * down into two or more smaller rectangles stacked one atop the other.
140 * ----------- -----------
142 * | | -------- ----------- --------
143 * | | | | in y-x banded | | | | band 1
144 * | | | | form is | | | |
145 * ----------- | | ----------- --------
149 * An added constraint on the rectangles is that they must cover as much
150 * horizontal area as possible: no two rectangles within a band are allowed
153 * Whenever possible, bands will be merged together to cover a greater vertical
154 * distance (and thus reduce the number of rectangles). Two bands can be merged
155 * only if the bottom of one touches the top of the other and they have
156 * rectangles in the same places (of the same width, of course).
158 * Adam de Boor wrote most of the original region code. Joel McCormack
159 * substantially modified or rewrote most of the core arithmetic routines, and
160 * added pixman_region_validate in order to support several speed improvements to
161 * pixman_region_validateTree. Bob Scheifler changed the representation to be more
162 * compact when empty or a single rectangle, and did a bunch of gratuitous
163 * reformatting. Carl Worth did further gratuitous reformatting while re-merging
164 * the server and client region code into libpixregion.
167 /* true iff two Boxes overlap */
168 #define EXTENTCHECK(r1,r2) \
169 (!( ((r1)->x2 <= (r2)->x1) || \
170 ((r1)->x1 >= (r2)->x2) || \
171 ((r1)->y2 <= (r2)->y1) || \
172 ((r1)->y1 >= (r2)->y2) ) )
174 /* true iff (x,y) is in Box */
175 #define INBOX(r,x,y) \
181 /* true iff Box r1 contains Box r2 */
182 #define SUBSUMES(r1,r2) \
183 ( ((r1)->x1 <= (r2)->x1) && \
184 ((r1)->x2 >= (r2)->x2) && \
185 ((r1)->y1 <= (r2)->y1) && \
186 ((r1)->y2 >= (r2)->y2) )
189 PIXREGION_SZOF(size_t n)
191 size_t size = n * sizeof(pixman_box16_t);
192 if (n > UINT32_MAX / sizeof(pixman_box16_t))
195 if (sizeof(pixman_region16_data_t) > UINT32_MAX - size)
198 return size + sizeof(pixman_region16_data_t);
204 size_t sz = PIXREGION_SZOF(n);
211 #define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
213 #define RECTALLOC_BAIL(pReg,n,bail) \
214 if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
215 if (!pixman_rect_alloc(pReg, n)) { goto bail; }
217 #define RECTALLOC(pReg,n) \
218 if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
219 if (!pixman_rect_alloc(pReg, n)) { return FALSE; }
221 #define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
223 pNextRect->x1 = nx1; \
224 pNextRect->y1 = ny1; \
225 pNextRect->x2 = nx2; \
226 pNextRect->y2 = ny2; \
230 #define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
232 if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
234 if (!pixman_rect_alloc(pReg, 1)) \
236 pNextRect = PIXREGION_TOP(pReg); \
238 ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
239 pReg->data->numRects++; \
240 assert(pReg->data->numRects<=pReg->data->size); \
243 #define DOWNSIZE(reg,numRects) \
244 if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
246 pixman_region16_data_t * NewData; \
247 size_t data_size = PIXREGION_SZOF(numRects); \
251 NewData = (pixman_region16_data_t *)realloc((reg)->data, data_size); \
254 NewData->size = (numRects); \
255 (reg)->data = NewData; \
260 pixman_region_equal(reg1, reg2)
261 pixman_region16_t * reg1;
262 pixman_region16_t * reg2;
265 pixman_box16_t *rects1;
266 pixman_box16_t *rects2;
268 if (reg1->extents.x1 != reg2->extents.x1) return FALSE;
269 if (reg1->extents.x2 != reg2->extents.x2) return FALSE;
270 if (reg1->extents.y1 != reg2->extents.y1) return FALSE;
271 if (reg1->extents.y2 != reg2->extents.y2) return FALSE;
272 if (PIXREGION_NUM_RECTS(reg1) != PIXREGION_NUM_RECTS(reg2)) return FALSE;
274 rects1 = PIXREGION_RECTS(reg1);
275 rects2 = PIXREGION_RECTS(reg2);
276 for (i = 0; i != PIXREGION_NUM_RECTS(reg1); i++) {
277 if (rects1[i].x1 != rects2[i].x1) return FALSE;
278 if (rects1[i].x2 != rects2[i].x2) return FALSE;
279 if (rects1[i].y1 != rects2[i].y1) return FALSE;
280 if (rects1[i].y2 != rects2[i].y2) return FALSE;
286 pixman_region16_print(rgn)
287 pixman_region16_t * rgn;
291 pixman_box16_t * rects;
293 num = PIXREGION_NUM_RECTS(rgn);
294 size = PIXREGION_SIZE(rgn);
295 rects = PIXREGION_RECTS(rgn);
296 fprintf(stderr, "num: %d size: %d\n", num, size);
297 fprintf(stderr, "extents: %d %d %d %d\n",
298 rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
299 for (i = 0; i < num; i++)
300 fprintf(stderr, "%d %d %d %d \n",
301 rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
302 fprintf(stderr, "\n");
308 pixman_region_init (pixman_region16_t *region)
310 region->extents = *pixman_region_emptyBox;
311 region->data = pixman_region_emptyData;
315 pixman_region_init_rect (pixman_region16_t *region,
316 int x, int y, unsigned int width, unsigned int height)
318 region->extents.x1 = x;
319 region->extents.y1 = y;
320 region->extents.x2 = x + width;
321 region->extents.y2 = y + height;
326 pixman_region_init_with_extents (pixman_region16_t *region, pixman_box16_t *extents)
328 region->extents = *extents;
333 pixman_region_fini (pixman_region16_t *region)
340 pixman_region_n_rects (pixman_region16_t *region)
342 return PIXREGION_NUM_RECTS (region);
346 pixman_region_rects (pixman_region16_t *region)
348 return PIXREGION_RECTS (region);
352 pixman_region_rectangles (pixman_region16_t *region,
356 *n_rects = PIXREGION_NUM_RECTS (region);
358 return PIXREGION_RECTS (region);
362 pixman_break (pixman_region16_t *region)
365 region->extents = *pixman_region_emptyBox;
366 region->data = pixman_brokendata;
371 pixman_rect_alloc (pixman_region16_t * region, int n)
373 pixman_region16_data_t *data;
378 region->data = allocData(n);
380 return pixman_break (region);
381 region->data->numRects = 1;
382 *PIXREGION_BOXPTR(region) = region->extents;
384 else if (!region->data->size)
386 region->data = allocData(n);
388 return pixman_break (region);
389 region->data->numRects = 0;
396 n = region->data->numRects;
397 if (n > 500) /* XXX pick numbers out of a hat */
400 n += region->data->numRects;
401 data_size = PIXREGION_SZOF(n);
405 data = (pixman_region16_data_t *)realloc(region->data, PIXREGION_SZOF(n));
407 return pixman_break (region);
410 region->data->size = n;
415 pixman_region_copy (pixman_region16_t *dst, pixman_region16_t *src)
421 dst->extents = src->extents;
422 if (!src->data || !src->data->size)
425 dst->data = src->data;
428 if (!dst->data || (dst->data->size < src->data->numRects))
431 dst->data = allocData(src->data->numRects);
433 return pixman_break (dst);
434 dst->data->size = src->data->numRects;
436 dst->data->numRects = src->data->numRects;
437 memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src),
438 dst->data->numRects * sizeof(pixman_box16_t));
442 /*======================================================================
443 * Generic Region Operator
444 *====================================================================*/
447 *-----------------------------------------------------------------------
449 * Attempt to merge the boxes in the current band with those in the
450 * previous one. We are guaranteed that the current band extends to
451 * the end of the rects array. Used only by pixman_op.
454 * The new index for the previous band.
457 * If coalescing takes place:
458 * - rectangles in the previous band will have their y2 fields
460 * - region->data->numRects will be decreased.
462 *-----------------------------------------------------------------------
466 pixman_region16_t * region, /* Region to coalesce */
467 int prevStart, /* Index of start of previous band */
468 int curStart) /* Index of start of current band */
470 pixman_box16_t * pPrevBox; /* Current box in previous band */
471 pixman_box16_t * pCurBox; /* Current box in current band */
472 int numRects; /* Number rectangles in both bands */
473 int y2; /* Bottom of current band */
475 * Figure out how many rectangles are in the band.
477 numRects = curStart - prevStart;
478 assert(numRects == region->data->numRects - curStart);
480 if (!numRects) return curStart;
483 * The bands may only be coalesced if the bottom of the previous
484 * matches the top scanline of the current.
486 pPrevBox = PIXREGION_BOX(region, prevStart);
487 pCurBox = PIXREGION_BOX(region, curStart);
488 if (pPrevBox->y2 != pCurBox->y1) return curStart;
491 * Make sure the bands have boxes in the same places. This
492 * assumes that boxes have been added in such a way that they
493 * cover the most area possible. I.e. two boxes in a band must
494 * have some horizontal space between them.
499 if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
508 * The bands may be merged, so set the bottom y of each box
509 * in the previous band to the bottom y of the current band.
511 numRects = curStart - prevStart;
512 region->data->numRects -= numRects;
521 /* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */
523 #define Coalesce(newReg, prevBand, curBand) \
524 if (curBand - prevBand == newReg->data->numRects - curBand) { \
525 prevBand = pixman_coalesce(newReg, prevBand, curBand); \
527 prevBand = curBand; \
531 *-----------------------------------------------------------------------
532 * pixman_region_appendNonO --
533 * Handle a non-overlapping band for the union and subtract operations.
534 * Just adds the (top/bottom-clipped) rectangles into the region.
535 * Doesn't have to check for subsumption or anything.
541 * region->data->numRects is incremented and the rectangles overwritten
542 * with the rectangles we're passed.
544 *-----------------------------------------------------------------------
547 static inline pixman_bool_t
548 pixman_region_appendNonO (
549 pixman_region16_t * region,
551 pixman_box16_t * rEnd,
555 pixman_box16_t * pNextRect;
561 assert(newRects != 0);
563 /* Make sure we have enough space for all rectangles to be added */
564 RECTALLOC(region, newRects);
565 pNextRect = PIXREGION_TOP(region);
566 region->data->numRects += newRects;
568 assert(r->x1 < r->x2);
569 ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
576 #define FindBand(r, rBandEnd, rEnd, ry1) \
580 while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
585 #define AppendRegions(newReg, r, rEnd) \
588 if ((newRects = rEnd - r)) { \
589 RECTALLOC(newReg, newRects); \
590 memmove((char *)PIXREGION_TOP(newReg),(char *)r, \
591 newRects * sizeof(pixman_box16_t)); \
592 newReg->data->numRects += newRects; \
597 *-----------------------------------------------------------------------
599 * Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse,
600 * pixman_region_subtract, pixman_region_intersect.... Both regions MUST have at least one
601 * rectangle, and cannot be the same object.
604 * TRUE if successful.
607 * The new region is overwritten.
608 * pOverlap set to TRUE if overlapFunc ever returns TRUE.
611 * The idea behind this function is to view the two regions as sets.
612 * Together they cover a rectangle of area that this function divides
613 * into horizontal bands where points are covered only by one region
614 * or by both. For the first case, the nonOverlapFunc is called with
615 * each the band and the band's upper and lower extents. For the
616 * second, the overlapFunc is called to process the entire band. It
617 * is responsible for clipping the rectangles in the band, though
618 * this function provides the boundaries.
619 * At the end of each band, the new region is coalesced, if possible,
620 * to reduce the number of rectangles in the region.
622 *-----------------------------------------------------------------------
625 typedef pixman_bool_t (*OverlapProcPtr)(
626 pixman_region16_t *region,
628 pixman_box16_t *r1End,
630 pixman_box16_t *r2End,
637 pixman_region16_t *newReg, /* Place to store result */
638 pixman_region16_t * reg1, /* First region in operation */
639 pixman_region16_t * reg2, /* 2d region in operation */
640 OverlapProcPtr overlapFunc, /* Function to call for over-
642 int appendNon1, /* Append non-overlapping bands */
644 int appendNon2, /* Append non-overlapping bands */
648 pixman_box16_t * r1; /* Pointer into first region */
649 pixman_box16_t * r2; /* Pointer into 2d region */
650 pixman_box16_t * r1End; /* End of 1st region */
651 pixman_box16_t * r2End; /* End of 2d region */
652 short ybot; /* Bottom of intersection */
653 short ytop; /* Top of intersection */
654 pixman_region16_data_t * oldData; /* Old data for newReg */
655 int prevBand; /* Index of start of
656 * previous band in newReg */
657 int curBand; /* Index of start of current
659 pixman_box16_t * r1BandEnd; /* End of current band in r1 */
660 pixman_box16_t * r2BandEnd; /* End of current band in r2 */
661 short top; /* Top of non-overlapping band */
662 short bot; /* Bottom of non-overlapping band*/
663 int r1y1; /* Temps for r1->y1 and r2->y1 */
669 * Break any region computed from a broken region
671 if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))
672 return pixman_break (newReg);
676 * set r1, r2, r1End and r2End appropriately, save the rectangles
677 * of the destination region until the end in case it's one of
678 * the two source regions, then mark the "new" region empty, allocating
679 * another array of rectangles for it to use.
682 r1 = PIXREGION_RECTS(reg1);
683 newSize = PIXREGION_NUM_RECTS(reg1);
684 r1End = r1 + newSize;
685 numRects = PIXREGION_NUM_RECTS(reg2);
686 r2 = PIXREGION_RECTS(reg2);
687 r2End = r2 + numRects;
691 oldData = (pixman_region16_data_t *)NULL;
692 if (((newReg == reg1) && (newSize > 1)) ||
693 ((newReg == reg2) && (numRects > 1)))
695 oldData = newReg->data;
696 newReg->data = pixman_region_emptyData;
698 /* guess at new size */
699 if (numRects > newSize)
703 newReg->data = pixman_region_emptyData;
704 else if (newReg->data->size)
705 newReg->data->numRects = 0;
706 if (newSize > newReg->data->size) {
707 if (!pixman_rect_alloc(newReg, newSize)) {
716 * In the upcoming loop, ybot and ytop serve different functions depending
717 * on whether the band being handled is an overlapping or non-overlapping
719 * In the case of a non-overlapping band (only one of the regions
720 * has points in the band), ybot is the bottom of the most recent
721 * intersection and thus clips the top of the rectangles in that band.
722 * ytop is the top of the next intersection between the two regions and
723 * serves to clip the bottom of the rectangles in the current band.
724 * For an overlapping band (where the two regions intersect), ytop clips
725 * the top of the rectangles of both regions and ybot clips the bottoms.
728 ybot = MIN(r1->y1, r2->y1);
731 * prevBand serves to mark the start of the previous band so rectangles
732 * can be coalesced into larger rectangles. qv. pixman_coalesce, above.
733 * In the beginning, there is no previous band, so prevBand == curBand
734 * (curBand is set later on, of course, but the first band will always
735 * start at index 0). prevBand and curBand must be indices because of
736 * the possible expansion, and resultant moving, of the new region's
737 * array of rectangles.
743 * This algorithm proceeds one source-band (as opposed to a
744 * destination band, which is determined by where the two regions
745 * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
746 * rectangle after the last one in the current band for their
747 * respective regions.
752 FindBand(r1, r1BandEnd, r1End, r1y1);
753 FindBand(r2, r2BandEnd, r2End, r2y1);
756 * First handle the band that doesn't intersect, if any.
758 * Note that attention is restricted to one band in the
759 * non-intersecting region at once, so if a region has n
760 * bands between the current position and the next place it overlaps
761 * the other, this entire loop will be passed through n times.
765 top = MAX(r1y1, ybot);
766 bot = MIN(r1->y2, r2y1);
768 curBand = newReg->data->numRects;
769 pixman_region_appendNonO(newReg, r1, r1BandEnd, top, bot);
770 Coalesce(newReg, prevBand, curBand);
774 } else if (r2y1 < r1y1) {
776 top = MAX(r2y1, ybot);
777 bot = MIN(r2->y2, r1y1);
779 curBand = newReg->data->numRects;
780 pixman_region_appendNonO(newReg, r2, r2BandEnd, top, bot);
781 Coalesce(newReg, prevBand, curBand);
790 * Now see if we've hit an intersecting band. The two bands only
791 * intersect if ybot > ytop
793 ybot = MIN(r1->y2, r2->y2);
795 curBand = newReg->data->numRects;
796 (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
798 Coalesce(newReg, prevBand, curBand);
802 * If we've finished with a band (y2 == ybot) we skip forward
803 * in the region to the next band.
805 if (r1->y2 == ybot) r1 = r1BandEnd;
806 if (r2->y2 == ybot) r2 = r2BandEnd;
808 } while (r1 != r1End && r2 != r2End);
811 * Deal with whichever region (if any) still has rectangles left.
813 * We only need to worry about banding and coalescing for the very first
814 * band left. After that, we can just group all remaining boxes,
815 * regardless of how many bands, into one final append to the list.
818 if ((r1 != r1End) && appendNon1) {
819 /* Do first nonOverlap1Func call, which may be able to coalesce */
820 FindBand(r1, r1BandEnd, r1End, r1y1);
821 curBand = newReg->data->numRects;
822 pixman_region_appendNonO(newReg, r1, r1BandEnd, MAX(r1y1, ybot), r1->y2);
823 Coalesce(newReg, prevBand, curBand);
824 /* Just append the rest of the boxes */
825 AppendRegions(newReg, r1BandEnd, r1End);
827 } else if ((r2 != r2End) && appendNon2) {
828 /* Do first nonOverlap2Func call, which may be able to coalesce */
829 FindBand(r2, r2BandEnd, r2End, r2y1);
830 curBand = newReg->data->numRects;
831 pixman_region_appendNonO(newReg, r2, r2BandEnd, MAX(r2y1, ybot), r2->y2);
832 Coalesce(newReg, prevBand, curBand);
833 /* Append rest of boxes */
834 AppendRegions(newReg, r2BandEnd, r2End);
840 if (!(numRects = newReg->data->numRects))
843 newReg->data = pixman_region_emptyData;
845 else if (numRects == 1)
847 newReg->extents = *PIXREGION_BOXPTR(newReg);
849 newReg->data = (pixman_region16_data_t *)NULL;
853 DOWNSIZE(newReg, numRects);
860 *-----------------------------------------------------------------------
861 * pixman_set_extents --
862 * Reset the extents of a region to what they should be. Called by
863 * pixman_region_subtract and pixman_region_intersect as they can't figure it out along the
864 * way or do so easily, as pixman_region_union can.
870 * The region's 'extents' structure is overwritten.
872 *-----------------------------------------------------------------------
875 pixman_set_extents (pixman_region16_t *region)
877 pixman_box16_t *box, *boxEnd;
881 if (!region->data->size)
883 region->extents.x2 = region->extents.x1;
884 region->extents.y2 = region->extents.y1;
888 box = PIXREGION_BOXPTR(region);
889 boxEnd = PIXREGION_END(region);
892 * Since box is the first rectangle in the region, it must have the
893 * smallest y1 and since boxEnd is the last rectangle in the region,
894 * it must have the largest y2, because of banding. Initialize x1 and
895 * x2 from box and boxEnd, resp., as good things to initialize them
898 region->extents.x1 = box->x1;
899 region->extents.y1 = box->y1;
900 region->extents.x2 = boxEnd->x2;
901 region->extents.y2 = boxEnd->y2;
903 assert(region->extents.y1 < region->extents.y2);
904 while (box <= boxEnd) {
905 if (box->x1 < region->extents.x1)
906 region->extents.x1 = box->x1;
907 if (box->x2 > region->extents.x2)
908 region->extents.x2 = box->x2;
912 assert(region->extents.x1 < region->extents.x2);
915 /*======================================================================
916 * Region Intersection
917 *====================================================================*/
919 *-----------------------------------------------------------------------
920 * pixman_region_intersectO --
921 * Handle an overlapping band for pixman_region_intersect.
924 * TRUE if successful.
927 * Rectangles may be added to the region.
929 *-----------------------------------------------------------------------
933 pixman_region_intersectO (pixman_region16_t *region,
935 pixman_box16_t *r1End,
937 pixman_box16_t *r2End,
944 pixman_box16_t * pNextRect;
946 pNextRect = PIXREGION_TOP(region);
949 assert(r1 != r1End && r2 != r2End);
952 x1 = MAX(r1->x1, r2->x1);
953 x2 = MIN(r1->x2, r2->x2);
956 * If there's any overlap between the two rectangles, add that
957 * overlap to the new region.
960 NEWRECT(region, pNextRect, x1, y1, x2, y2);
963 * Advance the pointer(s) with the leftmost right side, since the next
964 * rectangle on that list may still overlap the other region's
973 } while ((r1 != r1End) && (r2 != r2End));
979 pixman_region_intersect (pixman_region16_t * newReg,
980 pixman_region16_t * reg1,
981 pixman_region16_t * reg2)
986 /* check for trivial reject */
987 if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) ||
988 !EXTENTCHECK(®1->extents, ®2->extents))
990 /* Covers about 20% of all cases */
992 newReg->extents.x2 = newReg->extents.x1;
993 newReg->extents.y2 = newReg->extents.y1;
994 if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2))
996 newReg->data = pixman_brokendata;
1000 newReg->data = pixman_region_emptyData;
1002 else if (!reg1->data && !reg2->data)
1004 /* Covers about 80% of cases that aren't trivially rejected */
1005 newReg->extents.x1 = MAX(reg1->extents.x1, reg2->extents.x1);
1006 newReg->extents.y1 = MAX(reg1->extents.y1, reg2->extents.y1);
1007 newReg->extents.x2 = MIN(reg1->extents.x2, reg2->extents.x2);
1008 newReg->extents.y2 = MIN(reg1->extents.y2, reg2->extents.y2);
1010 newReg->data = (pixman_region16_data_t *)NULL;
1012 else if (!reg2->data && SUBSUMES(®2->extents, ®1->extents))
1014 return pixman_region_copy(newReg, reg1);
1016 else if (!reg1->data && SUBSUMES(®1->extents, ®2->extents))
1018 return pixman_region_copy(newReg, reg2);
1020 else if (reg1 == reg2)
1022 return pixman_region_copy(newReg, reg1);
1026 /* General purpose intersection */
1027 int overlap; /* result ignored */
1028 if (!pixman_op(newReg, reg1, reg2, pixman_region_intersectO, FALSE, FALSE,
1031 pixman_set_extents(newReg);
1038 #define MERGERECT(r) \
1040 if (r->x1 <= x2) { \
1041 /* Merge with current rectangle */ \
1042 if (r->x1 < x2) *pOverlap = TRUE; \
1043 if (x2 < r->x2) x2 = r->x2; \
1045 /* Add current rectangle, start new one */ \
1046 NEWRECT(region, pNextRect, x1, y1, x2, y2); \
1053 /*======================================================================
1055 *====================================================================*/
1058 *-----------------------------------------------------------------------
1059 * pixman_region_unionO --
1060 * Handle an overlapping band for the union operation. Picks the
1061 * left-most rectangle each time and merges it into the region.
1064 * TRUE if successful.
1067 * region is overwritten.
1068 * pOverlap is set to TRUE if any boxes overlap.
1070 *-----------------------------------------------------------------------
1072 static pixman_bool_t
1073 pixman_region_unionO (
1074 pixman_region16_t *region,
1076 pixman_box16_t *r1End,
1078 pixman_box16_t *r2End,
1083 pixman_box16_t * pNextRect;
1084 int x1; /* left and right side of current union */
1088 assert(r1 != r1End && r2 != r2End);
1090 pNextRect = PIXREGION_TOP(region);
1092 /* Start off current rectangle */
1093 if (r1->x1 < r2->x1)
1105 while (r1 != r1End && r2 != r2End)
1107 if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
1110 /* Finish off whoever (if any) is left */
1116 } while (r1 != r1End);
1118 else if (r2 != r2End)
1123 } while (r2 != r2End);
1126 /* Add current rectangle */
1127 NEWRECT(region, pNextRect, x1, y1, x2, y2);
1132 /* Convenience function for performing union of region with a
1136 pixman_region_union_rect (pixman_region16_t *dest,
1137 pixman_region16_t *source,
1139 unsigned int width, unsigned int height)
1141 pixman_region16_t region;
1143 if (!width || !height)
1144 return pixman_region_copy (dest, source);
1146 region.extents.x1 = x;
1147 region.extents.y1 = y;
1148 region.extents.x2 = x + width;
1149 region.extents.y2 = y + height;
1151 return pixman_region_union (dest, source, ®ion);
1155 pixman_region_union (pixman_region16_t *newReg,
1156 pixman_region16_t *reg1,
1157 pixman_region16_t *reg2)
1159 int overlap; /* result ignored */
1161 /* Return TRUE if some overlap
1162 * between reg1, reg2
1167 /* checks all the simple cases */
1170 * Region 1 and 2 are the same
1174 return pixman_region_copy(newReg, reg1);
1180 if (PIXREGION_NIL(reg1))
1182 if (PIXREGION_NAR(reg1))
1183 return pixman_break (newReg);
1185 return pixman_region_copy(newReg, reg2);
1192 if (PIXREGION_NIL(reg2))
1194 if (PIXREGION_NAR(reg2))
1195 return pixman_break (newReg);
1197 return pixman_region_copy(newReg, reg1);
1202 * Region 1 completely subsumes region 2
1204 if (!reg1->data && SUBSUMES(®1->extents, ®2->extents))
1207 return pixman_region_copy(newReg, reg1);
1212 * Region 2 completely subsumes region 1
1214 if (!reg2->data && SUBSUMES(®2->extents, ®1->extents))
1217 return pixman_region_copy(newReg, reg2);
1221 if (!pixman_op(newReg, reg1, reg2, pixman_region_unionO, TRUE, TRUE, &overlap))
1224 newReg->extents.x1 = MIN(reg1->extents.x1, reg2->extents.x1);
1225 newReg->extents.y1 = MIN(reg1->extents.y1, reg2->extents.y1);
1226 newReg->extents.x2 = MAX(reg1->extents.x2, reg2->extents.x2);
1227 newReg->extents.y2 = MAX(reg1->extents.y2, reg2->extents.y2);
1232 /*======================================================================
1233 * Batch Rectangle Union
1234 *====================================================================*/
1237 *-----------------------------------------------------------------------
1238 * pixman_region_append --
1240 * "Append" the rgn rectangles onto the end of dstrgn, maintaining
1241 * knowledge of YX-banding when it's easy. Otherwise, dstrgn just
1242 * becomes a non-y-x-banded random collection of rectangles, and not
1243 * yet a true region. After a sequence of appends, the caller must
1244 * call pixman_region_validate to ensure that a valid region is
1248 * TRUE if successful.
1251 * dstrgn is modified if rgn has rectangles.
1255 pixman_region_append (pixman_region16_t * dstrgn,
1256 pixman_region16_t * rgn)
1258 int numRects, dnumRects, size;
1259 pixman_box16_t *new, *old;
1262 if (PIXREGION_NAR(rgn))
1263 return pixman_break (dstrgn);
1265 if (!rgn->data && (dstrgn->data == pixman_region_emptyData))
1267 dstrgn->extents = rgn->extents;
1268 dstrgn->data = (pixman_region16_data_t *)NULL;
1272 numRects = PIXREGION_NUM_RECTS(rgn);
1277 dnumRects = PIXREGION_NUM_RECTS(dstrgn);
1278 if (!dnumRects && (size < 200))
1279 size = 200; /* XXX pick numbers out of a hat */
1280 RECTALLOC(dstrgn, size);
1281 old = PIXREGION_RECTS(rgn);
1283 dstrgn->extents = rgn->extents;
1284 else if (dstrgn->extents.x2 > dstrgn->extents.x1)
1286 pixman_box16_t *first, *last;
1289 last = PIXREGION_BOXPTR(dstrgn) + (dnumRects - 1);
1290 if ((first->y1 > last->y2) ||
1291 ((first->y1 == last->y1) && (first->y2 == last->y2) &&
1292 (first->x1 > last->x2)))
1294 if (rgn->extents.x1 < dstrgn->extents.x1)
1295 dstrgn->extents.x1 = rgn->extents.x1;
1296 if (rgn->extents.x2 > dstrgn->extents.x2)
1297 dstrgn->extents.x2 = rgn->extents.x2;
1298 dstrgn->extents.y2 = rgn->extents.y2;
1302 first = PIXREGION_BOXPTR(dstrgn);
1303 last = old + (numRects - 1);
1304 if ((first->y1 > last->y2) ||
1305 ((first->y1 == last->y1) && (first->y2 == last->y2) &&
1306 (first->x1 > last->x2)))
1309 if (rgn->extents.x1 < dstrgn->extents.x1)
1310 dstrgn->extents.x1 = rgn->extents.x1;
1311 if (rgn->extents.x2 > dstrgn->extents.x2)
1312 dstrgn->extents.x2 = rgn->extents.x2;
1313 dstrgn->extents.y1 = rgn->extents.y1;
1316 dstrgn->extents.x2 = dstrgn->extents.x1;
1321 new = PIXREGION_BOX(dstrgn, numRects);
1323 *new = *PIXREGION_BOXPTR(dstrgn);
1325 memmove((char *)new,(char *)PIXREGION_BOXPTR(dstrgn),
1326 dnumRects * sizeof(pixman_box16_t));
1327 new = PIXREGION_BOXPTR(dstrgn);
1330 new = PIXREGION_BOXPTR(dstrgn) + dnumRects;
1334 memmove((char *)new, (char *)old, numRects * sizeof(pixman_box16_t));
1335 dstrgn->data->numRects += numRects;
1339 #define ExchangeRects(a, b) \
1343 rects[a] = rects[b]; \
1349 pixman_box16_t rects[],
1357 /* Always called with numRects > 1 */
1363 if (rects[0].y1 > rects[1].y1 ||
1364 (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
1365 ExchangeRects(0, 1);
1369 /* Choose partition element, stick in location 0 */
1370 ExchangeRects(0, numRects >> 1);
1374 /* Partition array */
1384 } while (i != numRects &&
1385 (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
1391 } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
1393 ExchangeRects(i, j);
1396 /* Move partition element back to middle */
1397 ExchangeRects(0, j);
1400 if (numRects-j-1 > 1)
1401 QuickSortRects(&rects[j+1], numRects-j-1);
1403 } while (numRects > 1);
1407 *-----------------------------------------------------------------------
1408 * pixman_region_validate --
1410 * Take a ``region'' which is a non-y-x-banded random collection of
1411 * rectangles, and compute a nice region which is the union of all the
1415 * TRUE if successful.
1418 * The passed-in ``region'' may be modified.
1419 * pOverlap set to TRUE if any retangles overlapped,
1423 * Step 1. Sort the rectangles into ascending order with primary key y1
1424 * and secondary key x1.
1426 * Step 2. Split the rectangles into the minimum number of proper y-x
1427 * banded regions. This may require horizontally merging
1428 * rectangles, and vertically coalescing bands. With any luck,
1429 * this step in an identity transformation (ala the Box widget),
1430 * or a coalescing into 1 box (ala Menus).
1432 * Step 3. Merge the separate regions down to a single region by calling
1433 * pixman_region_union. Maximize the work each pixman_region_union call does by using
1436 *-----------------------------------------------------------------------
1440 pixman_region_validate(pixman_region16_t * badreg,
1443 /* Descriptor for regions under construction in Step 2. */
1445 pixman_region16_t reg;
1450 int numRects; /* Original numRects for badreg */
1451 RegionInfo *ri; /* Array of current regions */
1452 int numRI; /* Number of entries used in ri */
1453 int sizeRI; /* Number of entries available in ri */
1454 int i; /* Index into rects */
1455 int j; /* Index into ri */
1456 RegionInfo *rit; /* &ri[j] */
1457 pixman_region16_t * reg; /* ri[j].reg */
1458 pixman_box16_t * box; /* Current box in rects */
1459 pixman_box16_t * riBox; /* Last box in ri[j].reg */
1460 pixman_region16_t * hreg; /* ri[j_half].reg */
1461 pixman_bool_t ret = TRUE;
1469 numRects = badreg->data->numRects;
1472 if (PIXREGION_NAR(badreg))
1477 if (badreg->extents.x1 < badreg->extents.x2)
1479 if ((numRects) == 1)
1482 badreg->data = (pixman_region16_data_t *) NULL;
1486 DOWNSIZE(badreg, numRects);
1492 /* Step 1: Sort the rects array into ascending (y1, x1) order */
1493 QuickSortRects(PIXREGION_BOXPTR(badreg), numRects);
1495 /* Step 2: Scatter the sorted array into the minimum number of regions */
1497 /* Set up the first region to be the first rectangle in badreg */
1498 /* Note that step 2 code will never overflow the ri[0].reg rects array */
1499 ri = (RegionInfo *) pixman_malloc_ab (4, sizeof(RegionInfo));
1501 return pixman_break (badreg);
1506 ri[0].reg = *badreg;
1507 box = PIXREGION_BOXPTR(&ri[0].reg);
1508 ri[0].reg.extents = *box;
1509 ri[0].reg.data->numRects = 1;
1511 /* Now scatter rectangles into the minimum set of valid regions. If the
1512 next rectangle to be added to a region would force an existing rectangle
1513 in the region to be split up in order to maintain y-x banding, just
1514 forget it. Try the next region. If it doesn't fit cleanly into any
1515 region, make a new one. */
1517 for (i = numRects; --i > 0;)
1520 /* Look for a region to append box to */
1521 for (j = numRI, rit = ri; --j >= 0; rit++)
1524 riBox = PIXREGION_END(reg);
1526 if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
1528 /* box is in same band as riBox. Merge or append it */
1529 if (box->x1 <= riBox->x2)
1531 /* Merge it with riBox */
1532 if (box->x1 < riBox->x2) *pOverlap = TRUE;
1533 if (box->x2 > riBox->x2) riBox->x2 = box->x2;
1537 RECTALLOC_BAIL(reg, 1, bail);
1538 *PIXREGION_TOP(reg) = *box;
1539 reg->data->numRects++;
1541 goto NextRect; /* So sue me */
1543 else if (box->y1 >= riBox->y2)
1545 /* Put box into new band */
1546 if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
1547 if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
1548 Coalesce(reg, rit->prevBand, rit->curBand);
1549 rit->curBand = reg->data->numRects;
1550 RECTALLOC_BAIL(reg, 1, bail);
1551 *PIXREGION_TOP(reg) = *box;
1552 reg->data->numRects++;
1555 /* Well, this region was inappropriate. Try the next one. */
1558 /* Uh-oh. No regions were appropriate. Create a new one. */
1559 if (sizeRI == numRI)
1563 /* Oops, allocate space for new region information */
1566 data_size = sizeRI * sizeof(RegionInfo);
1567 if (data_size / sizeRI != sizeof(RegionInfo))
1569 rit = (RegionInfo *) realloc(ri, data_size);
1578 rit->reg.extents = *box;
1579 rit->reg.data = (pixman_region16_data_t *)NULL;
1580 if (!pixman_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
1585 /* Make a final pass over each region in order to Coalesce and set
1586 extents.x2 and extents.y2 */
1588 for (j = numRI, rit = ri; --j >= 0; rit++)
1591 riBox = PIXREGION_END(reg);
1592 reg->extents.y2 = riBox->y2;
1593 if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
1594 Coalesce(reg, rit->prevBand, rit->curBand);
1595 if (reg->data->numRects == 1) /* keep unions happy below */
1598 reg->data = (pixman_region16_data_t *)NULL;
1602 /* Step 3: Union all regions into a single region */
1606 for (j = numRI & 1; j < (half + (numRI & 1)); j++)
1609 hreg = &ri[j+half].reg;
1610 if (!pixman_op(reg, reg, hreg, pixman_region_unionO, TRUE, TRUE, pOverlap))
1612 if (hreg->extents.x1 < reg->extents.x1)
1613 reg->extents.x1 = hreg->extents.x1;
1614 if (hreg->extents.y1 < reg->extents.y1)
1615 reg->extents.y1 = hreg->extents.y1;
1616 if (hreg->extents.x2 > reg->extents.x2)
1617 reg->extents.x2 = hreg->extents.x2;
1618 if (hreg->extents.y2 > reg->extents.y2)
1619 reg->extents.y2 = hreg->extents.y2;
1624 *badreg = ri[0].reg;
1629 for (i = 0; i < numRI; i++)
1630 freeData(&ri[i].reg);
1632 return pixman_break (badreg);
1635 /*======================================================================
1636 * Region Subtraction
1637 *====================================================================*/
1640 *-----------------------------------------------------------------------
1641 * pixman_region_subtractO --
1642 * Overlapping band subtraction. x1 is the left-most point not yet
1646 * TRUE if successful.
1649 * region may have rectangles added to it.
1651 *-----------------------------------------------------------------------
1654 static pixman_bool_t
1655 pixman_region_subtractO (
1656 pixman_region16_t * region,
1657 pixman_box16_t * r1,
1658 pixman_box16_t * r1End,
1659 pixman_box16_t * r2,
1660 pixman_box16_t * r2End,
1665 pixman_box16_t * pNextRect;
1671 assert(r1 != r1End && r2 != r2End);
1673 pNextRect = PIXREGION_TOP(region);
1680 * Subtrahend entirely to left of minuend: go to next subtrahend.
1684 else if (r2->x1 <= x1)
1687 * Subtrahend preceeds minuend: nuke left edge of minuend.
1693 * Minuend completely covered: advance to next minuend and
1694 * reset left fence to edge of new minuend.
1703 * Subtrahend now used up since it doesn't extend beyond
1709 else if (r2->x1 < r1->x2)
1712 * Left part of subtrahend covers part of minuend: add uncovered
1713 * part of minuend to region and skip to next subtrahend.
1716 NEWRECT(region, pNextRect, x1, y1, r2->x1, y2);
1722 * Minuend used up: advance to new...
1731 * Subtrahend used up
1739 * Minuend used up: add any remaining piece before advancing.
1742 NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
1747 } while ((r1 != r1End) && (r2 != r2End));
1750 * Add remaining minuend rectangles to region.
1755 NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
1764 *-----------------------------------------------------------------------
1765 * pixman_region_subtract --
1766 * Subtract regS from regM and leave the result in regD.
1767 * S stands for subtrahend, M for minuend and D for difference.
1770 * TRUE if successful.
1773 * regD is overwritten.
1775 *-----------------------------------------------------------------------
1778 pixman_region_subtract(pixman_region16_t * regD,
1779 pixman_region16_t * regM,
1780 pixman_region16_t * regS)
1782 int overlap; /* result ignored */
1787 /* check for trivial rejects */
1788 if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) ||
1789 !EXTENTCHECK(®M->extents, ®S->extents))
1791 if (PIXREGION_NAR (regS))
1792 return pixman_break (regD);
1793 return pixman_region_copy(regD, regM);
1795 else if (regM == regS)
1798 regD->extents.x2 = regD->extents.x1;
1799 regD->extents.y2 = regD->extents.y1;
1800 regD->data = pixman_region_emptyData;
1804 /* Add those rectangles in region 1 that aren't in region 2,
1805 do yucky substraction for overlaps, and
1806 just throw away rectangles in region 2 that aren't in region 1 */
1807 if (!pixman_op(regD, regM, regS, pixman_region_subtractO, TRUE, FALSE, &overlap))
1811 * Can't alter RegD's extents before we call pixman_op because
1812 * it might be one of the source regions and pixman_op depends
1813 * on the extents of those regions being unaltered. Besides, this
1814 * way there's no checking against rectangles that will be nuked
1815 * due to coalescing, so we have to examine fewer rectangles.
1817 pixman_set_extents(regD);
1822 /*======================================================================
1824 *====================================================================*/
1827 *-----------------------------------------------------------------------
1828 * pixman_region_inverse --
1829 * Take a region and a box and return a region that is everything
1830 * in the box but not in the region. The careful reader will note
1831 * that this is the same as subtracting the region from the box...
1837 * newReg is overwritten.
1839 *-----------------------------------------------------------------------
1842 pixman_region_inverse(pixman_region16_t * newReg, /* Destination region */
1843 pixman_region16_t * reg1, /* Region to invert */
1844 pixman_box16_t * invRect) /* Bounding box for inversion */
1846 pixman_region16_t invReg; /* Quick and dirty region made from the
1848 int overlap; /* result ignored */
1852 /* check for trivial rejects */
1853 if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents))
1855 if (PIXREGION_NAR(reg1))
1856 return pixman_break (newReg);
1857 newReg->extents = *invRect;
1859 newReg->data = (pixman_region16_data_t *)NULL;
1863 /* Add those rectangles in region 1 that aren't in region 2,
1864 do yucky substraction for overlaps, and
1865 just throw away rectangles in region 2 that aren't in region 1 */
1866 invReg.extents = *invRect;
1867 invReg.data = (pixman_region16_data_t *)NULL;
1868 if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, TRUE, FALSE, &overlap))
1872 * Can't alter newReg's extents before we call pixman_op because
1873 * it might be one of the source regions and pixman_op depends
1874 * on the extents of those regions being unaltered. Besides, this
1875 * way there's no checking against rectangles that will be nuked
1876 * due to coalescing, so we have to examine fewer rectangles.
1878 pixman_set_extents(newReg);
1884 * RectIn(region, rect)
1885 * This routine takes a pointer to a region and a pointer to a box
1886 * and determines if the box is outside/inside/partly inside the region.
1888 * The idea is to travel through the list of rectangles trying to cover the
1889 * passed box with them. Anytime a piece of the rectangle isn't covered
1890 * by a band of rectangles, partOut is set TRUE. Any time a rectangle in
1891 * the region covers part of the box, partIn is set TRUE. The process ends
1892 * when either the box has been completely covered (we reached a band that
1893 * doesn't overlap the box, partIn is TRUE and partOut is false), the
1894 * box has been partially covered (partIn == partOut == TRUE -- because of
1895 * the banding, the first time this is true we know the box is only
1896 * partially in the region) or is outside the region (we reached a band
1897 * that doesn't overlap the box at all and partIn is false)
1900 pixman_region_overlap_t
1901 pixman_region_contains_rectangle(pixman_region16_t * region,
1902 pixman_box16_t * prect)
1906 pixman_box16_t * pbox;
1907 pixman_box16_t * pboxEnd;
1908 int partIn, partOut;
1912 numRects = PIXREGION_NUM_RECTS(region);
1913 /* useful optimization */
1914 if (!numRects || !EXTENTCHECK(®ion->extents, prect))
1915 return(PIXMAN_REGION_OUT);
1919 /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */
1920 if (SUBSUMES(®ion->extents, prect))
1921 return(PIXMAN_REGION_IN);
1923 return(PIXMAN_REGION_PART);
1929 /* (x,y) starts at upper left of rect, moving to the right and down */
1933 /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
1934 for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
1940 continue; /* getting up to speed or skipping remainder of band */
1944 partOut = TRUE; /* missed part of rectangle above */
1945 if (partIn || (pbox->y1 >= prect->y2))
1947 y = pbox->y1; /* x guaranteed to be == prect->x1 */
1951 continue; /* not far enough over yet */
1955 partOut = TRUE; /* missed part of rectangle to left */
1960 if (pbox->x1 < prect->x2)
1962 partIn = TRUE; /* definitely overlap */
1967 if (pbox->x2 >= prect->x2)
1969 y = pbox->y2; /* finished with this band */
1972 x = prect->x1; /* reset x out to left again */
1977 * Because boxes in a band are maximal width, if the first box
1978 * to overlap the rectangle doesn't completely cover it in that
1979 * band, the rectangle must be partially out, since some of it
1980 * will be uncovered in that band. partIn will have been set true
1991 return PIXMAN_REGION_PART;
1993 return PIXMAN_REGION_IN;
1997 return PIXMAN_REGION_OUT;
2001 /* pixman_region_translate (region, x, y)
2006 pixman_region_translate (pixman_region16_t * region, int x, int y)
2010 pixman_box16_t * pbox;
2013 region->extents.x1 = x1 = region->extents.x1 + x;
2014 region->extents.y1 = y1 = region->extents.y1 + y;
2015 region->extents.x2 = x2 = region->extents.x2 + x;
2016 region->extents.y2 = y2 = region->extents.y2 + y;
2017 if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0)
2019 if (region->data && (nbox = region->data->numRects))
2021 for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
2031 if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
2033 region->extents.x2 = region->extents.x1;
2034 region->extents.y2 = region->extents.y1;
2036 region->data = pixman_region_emptyData;
2040 region->extents.x1 = SHRT_MIN;
2041 else if (x2 > SHRT_MAX)
2042 region->extents.x2 = SHRT_MAX;
2044 region->extents.y1 = SHRT_MIN;
2045 else if (y2 > SHRT_MAX)
2046 region->extents.y2 = SHRT_MAX;
2047 if (region->data && (nbox = region->data->numRects))
2049 pixman_box16_t * pboxout;
2051 for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
2053 pboxout->x1 = x1 = pbox->x1 + x;
2054 pboxout->y1 = y1 = pbox->y1 + y;
2055 pboxout->x2 = x2 = pbox->x2 + x;
2056 pboxout->y2 = y2 = pbox->y2 + y;
2057 if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|
2058 (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0)
2060 region->data->numRects--;
2064 pboxout->x1 = SHRT_MIN;
2065 else if (x2 > SHRT_MAX)
2066 pboxout->x2 = SHRT_MAX;
2068 pboxout->y1 = SHRT_MIN;
2069 else if (y2 > SHRT_MAX)
2070 pboxout->y2 = SHRT_MAX;
2073 if (pboxout != pbox)
2075 if (region->data->numRects == 1)
2077 region->extents = *PIXREGION_BOXPTR(region);
2079 region->data = (pixman_region16_data_t *)NULL;
2082 pixman_set_extents(region);
2087 /* XXX: Do we need this?
2088 static pixman_bool_t
2089 pixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src)
2097 if (!src->data || !src->data->size)
2100 dst->data = (pixman_region16_data_t *)NULL;
2103 if (!dst->data || (dst->data->size < src->data->numRects))
2106 dst->data = allocData(src->data->numRects);
2108 return pixman_break (dst);
2110 dst->data->size = src->data->size;
2111 dst->data->numRects = src->data->numRects;
2117 pixman_region_reset(pixman_region16_t *region, pixman_box16_t *box)
2120 assert(box->x1<=box->x2);
2121 assert(box->y1<=box->y2);
2122 region->extents = *box;
2124 region->data = (pixman_region16_data_t *)NULL;
2127 /* box is "return" value */
2129 pixman_region_contains_point(pixman_region16_t * region,
2131 pixman_box16_t * box)
2133 pixman_box16_t *pbox, *pboxEnd;
2137 numRects = PIXREGION_NUM_RECTS(region);
2138 if (!numRects || !INBOX(®ion->extents, x, y))
2142 *box = region->extents;
2145 for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
2150 continue; /* not there yet */
2151 if ((y < pbox->y1) || (x < pbox->x1))
2152 break; /* missed it */
2154 continue; /* not there yet */
2162 pixman_region_not_empty(pixman_region16_t * region)
2165 return(!PIXREGION_NIL(region));
2168 /* XXX: Do we need this?
2170 pixman_region16_broken(pixman_region16_t * region)
2173 return (PIXREGION_NAR(region));
2178 pixman_region_empty(pixman_region16_t * region)
2182 region->extents.x2 = region->extents.x1;
2183 region->extents.y2 = region->extents.y1;
2184 region->data = pixman_region_emptyData;
2188 pixman_region_extents(pixman_region16_t * region)
2191 return(®ion->extents);
2194 #define ExchangeSpans(a, b) \
2196 pixman_region16_point_t tpt; \
2199 tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
2200 tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
2203 /* ||| I should apply the merge sort code to rectangle sorting above, and see
2204 if mapping time can be improved. But right now I've been at work 12 hours,
2208 static void QuickSortSpans(
2209 pixman_region16_point_t spans[],
2215 pixman_region16_point_t *r;
2217 /* Always called with numSpans > 1 */
2218 /* Sorts only by y, doesn't bother to sort by x */
2224 /* Do insertion sort */
2230 { /* while i != numSpans */
2234 /* spans[i] is out of order. Move into proper location. */
2235 pixman_region16_point_t tpt;
2238 for (j = 0; y >= spans[j].y; j++) {}
2241 for (k = i; k != j; k--)
2243 spans[k] = spans[k-1];
2244 widths[k] = widths[k-1];
2249 } /* if out of order */
2252 } while (i != numSpans);
2256 /* Choose partition element, stick in location 0 */
2258 if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
2259 if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
2260 if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
2263 /* Partition array */
2273 } while (i != numSpans && r->y < y);
2281 ExchangeSpans(i, j);
2284 /* Move partition element back to middle */
2285 ExchangeSpans(0, j);
2288 if (numSpans-j-1 > 1)
2289 QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
2291 } while (numSpans > 1);
2294 #define NextBand() \
2296 clipy1 = pboxBandStart->y1; \
2297 clipy2 = pboxBandStart->y2; \
2298 pboxBandEnd = pboxBandStart + 1; \
2299 while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \
2302 for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
2306 Clip a list of scanlines to a region. The caller has allocated the
2307 space. FSorted is non-zero if the scanline origins are in ascending
2309 returns the number of new, clipped scanlines.
2312 #ifdef XXX_DO_WE_NEED_THIS
2314 pixman_region16_clip_spans(
2315 pixman_region16_t *prgnDst,
2316 pixman_region16_point_t *ppt,
2319 pixman_region16_point_t *pptNew,
2323 pixman_region16_point_t *pptLast;
2324 int *pwidthNewStart; /* the vengeance of Xerox! */
2329 pptLast = ppt + nspans;
2330 pwidthNewStart = pwidthNew;
2334 /* Do special fast code with clip boundaries in registers(?) */
2335 /* It doesn't pay much to make use of fSorted in this case,
2336 so we lump everything together. */
2338 int clipx1, clipx2, clipy1, clipy2;
2340 clipx1 = prgnDst->extents.x1;
2341 clipy1 = prgnDst->extents.y1;
2342 clipx2 = prgnDst->extents.x2;
2343 clipy2 = prgnDst->extents.y2;
2345 for (; ppt != pptLast; ppt++, pwidth++)
2349 if (clipy1 <= y && y < clipy2)
2352 if (x1 < clipx1) x1 = clipx1;
2353 if (x2 > clipx2) x2 = clipx2;
2356 /* part of span in clip rectangle */
2359 *pwidthNew = x2 - x1;
2367 else if ((numRects = prgnDst->data->numRects))
2369 /* Have to clip against many boxes */
2370 pixman_box16_t *pboxBandStart, *pboxBandEnd;
2371 pixman_box16_t *pbox;
2372 pixman_box16_t *pboxLast;
2375 /* In this case, taking advantage of sorted spans gains more than
2376 the sorting costs. */
2377 if ((! fSorted) && (nspans > 1))
2378 QuickSortSpans(ppt, pwidth, nspans);
2380 pboxBandStart = PIXREGION_BOXPTR(prgnDst);
2381 pboxLast = pboxBandStart + numRects;
2385 for (; ppt != pptLast; )
2390 /* span is in the current band */
2391 pbox = pboxBandStart;
2395 { /* For each box in band */
2400 if (newx1 < pbox->x1) newx1 = pbox->x1;
2401 if (newx2 > pbox->x2) newx2 = pbox->x2;
2404 /* Part of span in clip rectangle */
2407 *pwidthNew = newx2 - newx1;
2412 } while (pbox != pboxBandEnd);
2418 /* Move to next band, adjust ppt as needed */
2419 pboxBandStart = pboxBandEnd;
2420 if (pboxBandStart == pboxLast)
2421 break; /* We're completely done */
2426 return (pwidthNew - pwidthNewStart);
2429 /* find the band in a region with the most rectangles */
2431 pixman_region16_find_max_band(pixman_region16_t * prgn)
2434 pixman_box16_t * pbox;
2440 nbox = PIXREGION_NUM_RECTS(prgn);
2441 pbox = PIXREGION_RECTS(prgn);
2445 yThisBand = pbox->y1;
2447 while((nbox > 0) && (pbox->y1 == yThisBand))
2453 if (nThisBand > nMaxBand)
2454 nMaxBand = nThisBand;
2458 #endif /* XXX_DO_WE_NEED_THIS */
2462 pixman_region_selfcheck (reg)
2463 pixman_region16_t * reg;
2467 if ((reg->extents.x1 > reg->extents.x2) ||
2468 (reg->extents.y1 > reg->extents.y2))
2470 numRects = PIXREGION_NUM_RECTS(reg);
2472 return ((reg->extents.x1 == reg->extents.x2) &&
2473 (reg->extents.y1 == reg->extents.y2) &&
2474 (reg->data->size || (reg->data == pixman_region_emptyData)));
2475 else if (numRects == 1)
2476 return (!reg->data);
2479 pixman_box16_t * pboxP, * pboxN;
2482 pboxP = PIXREGION_RECTS(reg);
2484 box.y2 = pboxP[numRects-1].y2;
2486 for (i = numRects; --i > 0; pboxP++, pboxN++)
2488 if ((pboxN->x1 >= pboxN->x2) ||
2489 (pboxN->y1 >= pboxN->y2))
2491 if (pboxN->x1 < box.x1)
2493 if (pboxN->x2 > box.x2)
2495 if ((pboxN->y1 < pboxP->y1) ||
2496 ((pboxN->y1 == pboxP->y1) &&
2497 ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
2500 return ((box.x1 == reg->extents.x1) &&
2501 (box.x2 == reg->extents.x2) &&
2502 (box.y1 == reg->extents.y1) &&
2503 (box.y2 == reg->extents.y2));
2508 pixman_region_init_rects (pixman_region16_t *region,
2509 pixman_box16_t *boxes, int count)
2514 pixman_region_init_rect(region,
2517 boxes[0].x2 - boxes[0].x1,
2518 boxes[0].y2 - boxes[0].y1);
2522 pixman_region_init(region);
2523 if (!pixman_rect_alloc(region, count))
2526 /* Copy in the rects */
2527 memcpy (PIXREGION_RECTS(region), boxes, sizeof(pixman_box16_t) * count);
2528 region->data->numRects = count;
2531 region->extents.x1 = region->extents.x2 = 0;
2532 return pixman_region_validate (region, &overlap);