#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
#include "Xutil.h"
#include <X11/Xregion.h>
#include "poly.h"
#ifdef DEBUG
#include <stdio.h>
#define assert(expr) {if (!(expr)) fprintf(stderr,\
"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); }
#else
#define assert(expr)
#endif
typedef int (*overlapProcp)(
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
short y1,
short y2);
typedef int (*nonOverlapProcp)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2);
static void miRegionOp(
register Region newReg,
Region reg1,
Region reg2,
int (*overlapFunc)(
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
short y1,
short y2),
int (*nonOverlap1Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2),
int (*nonOverlap2Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2));
Region
XCreateRegion(void)
{
Region temp;
if (! (temp = ( Region )Xmalloc( (unsigned) sizeof( REGION ))))
return (Region) NULL;
if (! (temp->rects = ( BOX * )Xmalloc( (unsigned) sizeof( BOX )))) {
Xfree((char *) temp);
return (Region) NULL;
}
temp->numRects = 0;
temp->extents.x1 = 0;
temp->extents.y1 = 0;
temp->extents.x2 = 0;
temp->extents.y2 = 0;
temp->size = 1;
return( temp );
}
int
XClipBox(
Region r,
XRectangle *rect)
{
rect->x = r->extents.x1;
rect->y = r->extents.y1;
rect->width = r->extents.x2 - r->extents.x1;
rect->height = r->extents.y2 - r->extents.y1;
return 1;
}
int
XUnionRectWithRegion(
register XRectangle *rect,
Region source, Region dest)
{
REGION region;
if (!rect->width || !rect->height)
return 0;
region.rects = ®ion.extents;
region.numRects = 1;
region.extents.x1 = rect->x;
region.extents.y1 = rect->y;
region.extents.x2 = rect->x + rect->width;
region.extents.y2 = rect->y + rect->height;
region.size = 1;
return XUnionRegion(®ion, source, dest);
}
static void
miSetExtents (
Region pReg)
{
register BoxPtr pBox,
pBoxEnd,
pExtents;
if (pReg->numRects == 0)
{
pReg->extents.x1 = 0;
pReg->extents.y1 = 0;
pReg->extents.x2 = 0;
pReg->extents.y2 = 0;
return;
}
pExtents = &pReg->extents;
pBox = pReg->rects;
pBoxEnd = &pBox[pReg->numRects - 1];
pExtents->x1 = pBox->x1;
pExtents->y1 = pBox->y1;
pExtents->x2 = pBoxEnd->x2;
pExtents->y2 = pBoxEnd->y2;
assert(pExtents->y1 < pExtents->y2);
while (pBox <= pBoxEnd)
{
if (pBox->x1 < pExtents->x1)
{
pExtents->x1 = pBox->x1;
}
if (pBox->x2 > pExtents->x2)
{
pExtents->x2 = pBox->x2;
}
pBox++;
}
assert(pExtents->x1 < pExtents->x2);
}
int
XSetRegion(
Display *dpy,
GC gc,
register Region r)
{
register int i;
register XRectangle *xr, *pr;
register BOX *pb;
unsigned long total;
LockDisplay (dpy);
total = r->numRects * sizeof (XRectangle);
if ((xr = (XRectangle *) _XAllocTemp(dpy, total))) {
for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) {
pr->x = pb->x1;
pr->y = pb->y1;
pr->width = pb->x2 - pb->x1;
pr->height = pb->y2 - pb->y1;
}
}
if (xr || !r->numRects)
_XSetClipRectangles(dpy, gc, 0, 0, xr, r->numRects, YXBanded);
if (xr)
_XFreeTemp(dpy, (char *)xr, total);
UnlockDisplay(dpy);
SyncHandle();
return 1;
}
int
XDestroyRegion(
Region r)
{
Xfree( (char *) r->rects );
Xfree( (char *) r );
return 1;
}
int
XOffsetRegion(
register Region pRegion,
register int x,
register int y)
{
register int nbox;
register BOX *pbox;
pbox = pRegion->rects;
nbox = pRegion->numRects;
while(nbox--)
{
pbox->x1 += x;
pbox->x2 += x;
pbox->y1 += y;
pbox->y2 += y;
pbox++;
}
pRegion->extents.x1 += x;
pRegion->extents.x2 += x;
pRegion->extents.y1 += y;
pRegion->extents.y2 += y;
return 1;
}
#define ZOpRegion(a,b,c) if (grow) XUnionRegion(a,b,c); \
else XIntersectRegion(a,b,c)
#define ZShiftRegion(a,b) if (xdir) XOffsetRegion(a,b,0); \
else XOffsetRegion(a,0,b)
#define ZCopyRegion(a,b) XUnionRegion(a,a,b)
static void
Compress(
Region r, Region s, Region t,
register unsigned dx,
register int xdir, register int grow)
{
register unsigned shift = 1;
ZCopyRegion(r, s);
while (dx) {
if (dx & shift) {
ZShiftRegion(r, -(int)shift);
ZOpRegion(r, s, r);
dx -= shift;
if (!dx) break;
}
ZCopyRegion(s, t);
ZShiftRegion(s, -(int)shift);
ZOpRegion(s, t, s);
shift <<= 1;
}
}
#undef ZOpRegion
#undef ZShiftRegion
#undef ZCopyRegion
int
XShrinkRegion(
Region r,
int dx, int dy)
{
Region s, t;
int grow;
if (!dx && !dy) return 0;
if ((! (s = XCreateRegion())) || (! (t = XCreateRegion()))) return 0;
if ((grow = (dx < 0))) dx = -dx;
if (dx) Compress(r, s, t, (unsigned) 2*dx, TRUE, grow);
if ((grow = (dy < 0))) dy = -dy;
if (dy) Compress(r, s, t, (unsigned) 2*dy, FALSE, grow);
XOffsetRegion(r, dx, dy);
XDestroyRegion(s);
XDestroyRegion(t);
return 0;
}
#ifdef notdef
static BOX
*IndexRects(
register BOX *rects,
register int numRects,
register int y)
{
while ((numRects--) && (rects->y2 <= y))
rects++;
return(rects);
}
#endif
static int
miIntersectO (
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
short y1,
short y2)
{
register short x1;
register short x2;
register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End))
{
x1 = max(r1->x1,r2->x1);
x2 = min(r1->x2,r2->x2);
if (x1 < x2)
{
assert(y1<y2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pNextRect->x2 = x2;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects <= pReg->size);
}
if (r1->x2 < r2->x2)
{
r1++;
}
else if (r2->x2 < r1->x2)
{
r2++;
}
else
{
r1++;
r2++;
}
}
return 0;
}
int
XIntersectRegion(
Region reg1,
Region reg2,
register Region newReg)
{
if ( (!(reg1->numRects)) || (!(reg2->numRects)) ||
(!EXTENTCHECK(®1->extents, ®2->extents)))
newReg->numRects = 0;
else
miRegionOp (newReg, reg1, reg2,
miIntersectO, NULL, NULL);
miSetExtents(newReg);
return 1;
}
static void
miRegionCopy(
register Region dstrgn,
register Region rgn)
{
if (dstrgn != rgn)
{
if (dstrgn->size < rgn->numRects)
{
if (dstrgn->rects)
{
BOX *prevRects = dstrgn->rects;
if (! (dstrgn->rects = (BOX *)
Xrealloc((char *) dstrgn->rects,
(unsigned) rgn->numRects * (sizeof(BOX))))) {
Xfree(prevRects);
return;
}
}
dstrgn->size = rgn->numRects;
}
dstrgn->numRects = rgn->numRects;
dstrgn->extents.x1 = rgn->extents.x1;
dstrgn->extents.y1 = rgn->extents.y1;
dstrgn->extents.x2 = rgn->extents.x2;
dstrgn->extents.y2 = rgn->extents.y2;
memcpy((char *) dstrgn->rects, (char *) rgn->rects,
(int) (rgn->numRects * sizeof(BOX)));
}
}
#ifdef notdef
static void
combineRegs(
register Region newReg,
Region reg1,
Region reg2)
{
register Region tempReg;
register BOX *rects;
register BOX *rects1;
register BOX *rects2;
register int total;
rects1 = reg1->rects;
rects2 = reg2->rects;
total = reg1->numRects + reg2->numRects;
if (! (tempReg = XCreateRegion()))
return;
tempReg->size = total;
if (reg1->extents.y1 > reg2->extents.y1)
{
miRegionCopy(tempReg, reg2);
rects = &tempReg->rects[tempReg->numRects];
total -= tempReg->numRects;
while (total--)
*rects++ = *rects1++;
}
else
{
miRegionCopy(tempReg, reg1);
rects = &tempReg->rects[tempReg->numRects];
total -= tempReg->numRects;
while (total--)
*rects++ = *rects2++;
}
tempReg->extents = reg1->extents;
tempReg->numRects = reg1->numRects + reg2->numRects;
EXTENTS(®2->extents, tempReg);
miRegionCopy(newReg, tempReg);
Xfree((char *)tempReg);
}
static int
QuickCheck(Region newReg, Region reg1, Region reg2)
{
if ( (reg1 == reg2) || (!(reg1->numRects)) )
{
miRegionCopy(newReg, reg2);
return TRUE;
}
if (!(reg2->numRects))
{
miRegionCopy(newReg, reg1);
return TRUE;
}
if ((reg1->extents.y1 >= reg2->extents.y2) ||
(reg2->extents.y1 >= reg1->extents.y2) )
{
combineRegs(newReg, reg1, reg2);
return TRUE;
}
return FALSE;
}
static int
TopRects(
register Region newReg,
register BOX *rects,
register Region reg1,
register Region reg2,
BOX *FirstRect)
{
register BOX *tempRects;
if (reg1->extents.y1 < reg2->extents.y1)
{
tempRects = reg1->rects;
while(tempRects->y1 < reg2->extents.y1)
{
MEMCHECK(newReg, rects, FirstRect);
ADDRECTNOX(newReg,rects, tempRects->x1, tempRects->y1,
tempRects->x2, MIN(tempRects->y2, reg2->extents.y1));
tempRects++;
}
}
if (reg2->extents.y1 < reg1->extents.y1)
{
tempRects = reg2->rects;
while (tempRects->y1 < reg1->extents.y1)
{
MEMCHECK(newReg, rects, FirstRect);
ADDRECTNOX(newReg, rects, tempRects->x1,tempRects->y1,
tempRects->x2, MIN(tempRects->y2, reg1->extents.y1));
tempRects++;
}
}
return 1;
}
#endif
static int
miCoalesce(
register Region pReg,
int prevStart,
int curStart)
{
register BoxPtr pPrevBox;
register BoxPtr pCurBox;
register BoxPtr pRegEnd;
int curNumRects;
int prevNumRects;
int bandY1;
pRegEnd = &pReg->rects[pReg->numRects];
pPrevBox = &pReg->rects[prevStart];
prevNumRects = curStart - prevStart;
pCurBox = &pReg->rects[curStart];
bandY1 = pCurBox->y1;
for (curNumRects = 0;
(pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
curNumRects++)
{
pCurBox++;
}
if (pCurBox != pRegEnd)
{
pRegEnd--;
while (pRegEnd[-1].y1 == pRegEnd->y1)
{
pRegEnd--;
}
curStart = pRegEnd - pReg->rects;
pRegEnd = pReg->rects + pReg->numRects;
}
if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
pCurBox -= curNumRects;
if (pPrevBox->y2 == pCurBox->y1)
{
do
{
if ((pPrevBox->x1 != pCurBox->x1) ||
(pPrevBox->x2 != pCurBox->x2))
{
return (curStart);
}
pPrevBox++;
pCurBox++;
prevNumRects -= 1;
} while (prevNumRects != 0);
pReg->numRects -= curNumRects;
pCurBox -= curNumRects;
pPrevBox -= curNumRects;
do
{
pPrevBox->y2 = pCurBox->y2;
pPrevBox++;
pCurBox++;
curNumRects -= 1;
} while (curNumRects != 0);
if (pCurBox == pRegEnd)
{
curStart = prevStart;
}
else
{
do
{
*pPrevBox++ = *pCurBox++;
} while (pCurBox != pRegEnd);
}
}
}
return (curStart);
}
static void
miRegionOp(
register Region newReg,
Region reg1,
Region reg2,
int (*overlapFunc)(
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
short y1,
short y2),
int (*nonOverlap1Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2),
int (*nonOverlap2Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2))
{
register BoxPtr r1;
register BoxPtr r2;
BoxPtr r1End;
BoxPtr r2End;
register short ybot;
register short ytop;
BoxPtr oldRects;
int prevBand;
int curBand;
register BoxPtr r1BandEnd;
register BoxPtr r2BandEnd;
short top;
short bot;
r1 = reg1->rects;
r2 = reg2->rects;
r1End = r1 + reg1->numRects;
r2End = r2 + reg2->numRects;
oldRects = newReg->rects;
EMPTY_REGION(newReg);
newReg->size = max(reg1->numRects,reg2->numRects) * 2;
if (! (newReg->rects = (BoxPtr)
Xmalloc ((unsigned) (sizeof(BoxRec) * newReg->size)))) {
newReg->size = 0;
return;
}
if (reg1->extents.y1 < reg2->extents.y1)
ybot = reg1->extents.y1;
else
ybot = reg2->extents.y1;
prevBand = 0;
do
{
curBand = newReg->numRects;
r1BandEnd = r1;
while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))
{
r1BandEnd++;
}
r2BandEnd = r2;
while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))
{
r2BandEnd++;
}
if (r1->y1 < r2->y1)
{
top = max(r1->y1,ybot);
bot = min(r1->y2,r2->y1);
if ((top != bot) && (nonOverlap1Func != NULL))
{
(* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot);
}
ytop = r2->y1;
}
else if (r2->y1 < r1->y1)
{
top = max(r2->y1,ybot);
bot = min(r2->y2,r1->y1);
if ((top != bot) && (nonOverlap2Func != NULL))
{
(* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot);
}
ytop = r1->y1;
}
else
{
ytop = r1->y1;
}
if (newReg->numRects != curBand)
{
prevBand = miCoalesce (newReg, prevBand, curBand);
}
ybot = min(r1->y2, r2->y2);
curBand = newReg->numRects;
if (ybot > ytop)
{
(* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
}
if (newReg->numRects != curBand)
{
prevBand = miCoalesce (newReg, prevBand, curBand);
}
if (r1->y2 == ybot)
{
r1 = r1BandEnd;
}
if (r2->y2 == ybot)
{
r2 = r2BandEnd;
}
} while ((r1 != r1End) && (r2 != r2End));
curBand = newReg->numRects;
if (r1 != r1End)
{
if (nonOverlap1Func != NULL)
{
do
{
r1BandEnd = r1;
while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1))
{
r1BandEnd++;
}
(* nonOverlap1Func) (newReg, r1, r1BandEnd,
max(r1->y1,ybot), r1->y2);
r1 = r1BandEnd;
} while (r1 != r1End);
}
}
else if ((r2 != r2End) && (nonOverlap2Func != NULL))
{
do
{
r2BandEnd = r2;
while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1))
{
r2BandEnd++;
}
(* nonOverlap2Func) (newReg, r2, r2BandEnd,
max(r2->y1,ybot), r2->y2);
r2 = r2BandEnd;
} while (r2 != r2End);
}
if (newReg->numRects != curBand)
{
(void) miCoalesce (newReg, prevBand, curBand);
}
if (newReg->numRects < (newReg->size >> 1))
{
if (REGION_NOT_EMPTY(newReg))
{
BoxPtr prev_rects = newReg->rects;
newReg->size = newReg->numRects;
newReg->rects = (BoxPtr) Xrealloc ((char *) newReg->rects,
(unsigned) (sizeof(BoxRec) * newReg->size));
if (! newReg->rects)
newReg->rects = prev_rects;
}
else
{
newReg->size = 1;
Xfree((char *) newReg->rects);
newReg->rects = (BoxPtr) Xmalloc(sizeof(BoxRec));
}
}
Xfree ((char *) oldRects);
return;
}
static int
miUnionNonO (
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2)
{
register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
assert(y1 < y2);
while (r != rEnd)
{
assert(r->x1 < r->x2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = r->x1;
pNextRect->y1 = y1;
pNextRect->x2 = r->x2;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects<=pReg->size);
r++;
}
return 0;
}
static int
miUnionO (
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
register short y1,
register short y2)
{
register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
#define MERGERECT(r) \
if ((pReg->numRects != 0) && \
(pNextRect[-1].y1 == y1) && \
(pNextRect[-1].y2 == y2) && \
(pNextRect[-1].x2 >= r->x1)) \
{ \
if (pNextRect[-1].x2 < r->x2) \
{ \
pNextRect[-1].x2 = r->x2; \
assert(pNextRect[-1].x1<pNextRect[-1].x2); \
} \
} \
else \
{ \
MEMCHECK(pReg, pNextRect, pReg->rects); \
pNextRect->y1 = y1; \
pNextRect->y2 = y2; \
pNextRect->x1 = r->x1; \
pNextRect->x2 = r->x2; \
pReg->numRects += 1; \
pNextRect += 1; \
} \
assert(pReg->numRects<=pReg->size);\
r++;
assert (y1<y2);
while ((r1 != r1End) && (r2 != r2End))
{
if (r1->x1 < r2->x1)
{
MERGERECT(r1);
}
else
{
MERGERECT(r2);
}
}
if (r1 != r1End)
{
do
{
MERGERECT(r1);
} while (r1 != r1End);
}
else while (r2 != r2End)
{
MERGERECT(r2);
}
return 0;
}
int
XUnionRegion(
Region reg1,
Region reg2,
Region newReg)
{
if ( (reg1 == reg2) || (!(reg1->numRects)) )
{
if (newReg != reg2)
miRegionCopy(newReg, reg2);
return 1;
}
if (!(reg2->numRects))
{
if (newReg != reg1)
miRegionCopy(newReg, reg1);
return 1;
}
if ((reg1->numRects == 1) &&
(reg1->extents.x1 <= reg2->extents.x1) &&
(reg1->extents.y1 <= reg2->extents.y1) &&
(reg1->extents.x2 >= reg2->extents.x2) &&
(reg1->extents.y2 >= reg2->extents.y2))
{
if (newReg != reg1)
miRegionCopy(newReg, reg1);
return 1;
}
if ((reg2->numRects == 1) &&
(reg2->extents.x1 <= reg1->extents.x1) &&
(reg2->extents.y1 <= reg1->extents.y1) &&
(reg2->extents.x2 >= reg1->extents.x2) &&
(reg2->extents.y2 >= reg1->extents.y2))
{
if (newReg != reg2)
miRegionCopy(newReg, reg2);
return 1;
}
miRegionOp (newReg, reg1, reg2, miUnionO,
miUnionNonO, miUnionNonO);
newReg->extents.x1 = min(reg1->extents.x1, reg2->extents.x1);
newReg->extents.y1 = min(reg1->extents.y1, reg2->extents.y1);
newReg->extents.x2 = max(reg1->extents.x2, reg2->extents.x2);
newReg->extents.y2 = max(reg1->extents.y2, reg2->extents.y2);
return 1;
}
static int
miSubtractNonO1 (
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register short y1,
register short y2)
{
register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
assert(y1<y2);
while (r != rEnd)
{
assert(r->x1<r->x2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = r->x1;
pNextRect->y1 = y1;
pNextRect->x2 = r->x2;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects <= pReg->size);
r++;
}
return 0;
}
static int
miSubtractO (
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
register short y1,
register short y2)
{
register BoxPtr pNextRect;
register int x1;
x1 = r1->x1;
assert(y1<y2);
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End))
{
if (r2->x2 <= x1)
{
r2++;
}
else if (r2->x1 <= x1)
{
x1 = r2->x2;
if (x1 >= r1->x2)
{
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
else
{
r2++;
}
}
else if (r2->x1 < r1->x2)
{
assert(x1<r2->x1);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pNextRect->x2 = r2->x1;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects<=pReg->size);
x1 = r2->x2;
if (x1 >= r1->x2)
{
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
else
{
r2++;
}
}
else
{
if (r1->x2 > x1)
{
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pNextRect->x2 = r1->x2;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects<=pReg->size);
}
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
}
while (r1 != r1End)
{
assert(x1<r1->x2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pNextRect->x2 = r1->x2;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
assert(pReg->numRects<=pReg->size);
r1++;
if (r1 != r1End)
{
x1 = r1->x1;
}
}
return 0;
}
int
XSubtractRegion(
Region regM,
Region regS,
register Region regD)
{
if ( (!(regM->numRects)) || (!(regS->numRects)) ||
(!EXTENTCHECK(®M->extents, ®S->extents)) )
{
miRegionCopy(regD, regM);
return 1;
}
miRegionOp (regD, regM, regS, miSubtractO,
miSubtractNonO1, NULL);
miSetExtents (regD);
return 1;
}
int
XXorRegion(Region sra, Region srb, Region dr)
{
Region tra, trb;
if ((! (tra = XCreateRegion())) || (! (trb = XCreateRegion())))
return 0;
(void) XSubtractRegion(sra,srb,tra);
(void) XSubtractRegion(srb,sra,trb);
(void) XUnionRegion(tra,trb,dr);
XDestroyRegion(tra);
XDestroyRegion(trb);
return 0;
}
int
XEmptyRegion(
Region r)
{
if( r->numRects == 0 ) return TRUE;
else return FALSE;
}
int
XEqualRegion(Region r1, Region r2)
{
int i;
if( r1->numRects != r2->numRects ) return FALSE;
else if( r1->numRects == 0 ) return TRUE;
else if ( r1->extents.x1 != r2->extents.x1 ) return FALSE;
else if ( r1->extents.x2 != r2->extents.x2 ) return FALSE;
else if ( r1->extents.y1 != r2->extents.y1 ) return FALSE;
else if ( r1->extents.y2 != r2->extents.y2 ) return FALSE;
else for( i=0; i < r1->numRects; i++ ) {
if ( r1->rects[i].x1 != r2->rects[i].x1 ) return FALSE;
else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return FALSE;
else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return FALSE;
else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return FALSE;
}
return TRUE;
}
int
XPointInRegion(
Region pRegion,
int x, int y)
{
int i;
if (pRegion->numRects == 0)
return FALSE;
if (!INBOX(pRegion->extents, x, y))
return FALSE;
for (i=0; i<pRegion->numRects; i++)
{
if (INBOX (pRegion->rects[i], x, y))
return TRUE;
}
return FALSE;
}
int
XRectInRegion(
register Region region,
int rx, int ry,
unsigned int rwidth, unsigned int rheight)
{
register BoxPtr pbox;
register BoxPtr pboxEnd;
Box rect;
register BoxPtr prect = ▭
int partIn, partOut;
prect->x1 = rx;
prect->y1 = ry;
prect->x2 = rwidth + rx;
prect->y2 = rheight + ry;
if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect))
return(RectangleOut);
partOut = FALSE;
partIn = FALSE;
for (pbox = region->rects, pboxEnd = pbox + region->numRects;
pbox < pboxEnd;
pbox++)
{
if (pbox->y2 <= ry)
continue;
if (pbox->y1 > ry)
{
partOut = TRUE;
if (partIn || (pbox->y1 >= prect->y2))
break;
ry = pbox->y1;
}
if (pbox->x2 <= rx)
continue;
if (pbox->x1 > rx)
{
partOut = TRUE;
if (partIn)
break;
}
if (pbox->x1 < prect->x2)
{
partIn = TRUE;
if (partOut)
break;
}
if (pbox->x2 >= prect->x2)
{
ry = pbox->y2;
if (ry >= prect->y2)
break;
rx = prect->x1;
} else
{
break;
}
}
return(partIn ? ((ry < prect->y2) ? RectanglePart : RectangleIn) :
RectangleOut);
}