#include "X.h"
#include "Xproto.h"
#include "Xint.h"
#include "dix.h"
#define MIN(a,b) ((a)>(b)?(b):(a))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define EXTENTCHECK(r1, r2) \
( ( ((r1)->x2 < (r2)->x1)) || \
( ((r1)->x1 > (r2)->x2)) || \
( ((r1)->y2 < (r2)->y1)) || \
( ((r1)->y1 > (r2)->y2)) ) \
? 0 : 1
/*
/* update region extents
*/
#define EXTENTS(r,idRect){\
if((r)->x1 < (idRect)->extents.x1)\
(idRect)->extents.x1 = (r)->x1;\
if((r)->y1 < (idRect)->extents.y1)\
(idRect)->extents.y1 = (r)->y1;\
if((r)->x2 > (idRect)->extents.x2)\
(idRect)->extents.x2 = (r)->x2;\
if((r)->y2 > (idRect)->extents.y2)\
(idRect)->extents.y2 = (r)->y2;\
}
/*
* Check to see if there is enough memory in the present region.
*/
#define MEMCHECK(reg, rect, firstrect){\
if ((reg)->numRects >= ((reg)->size - 1)){\
(firstrect) = (BOX *) Xrealloc \
((firstrect), (2 * (sizeof(BOX)) * ((reg)->size)));\
if ((firstrect) == 0)\
return(0);\
(reg)->size *= 2;\
(rect) = &(firstrect)[(reg)->numRects];\
}\
}
/* this routine checks to see if the previous rectangle is the same
* or subsumes the new rectangle to add.
*/
#define CHECK←PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\
((((Reg)->numRects > 0)&&\
((R-1)->y1 == (Ry1)) &&\
((R-1)->y2 == (Ry2)) &&\
((R-1)->x1 <= (Rx1)) &&\
((R-1)->x2 >= (Rx2)))\
? 0 : 1)
/* add a rectangle to the given region */
#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\
if ((rx1 < rx2) && (ry1 < ry2) &&\
(CHECK←PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2)))){\
(r)->x1 = (((rx1) < 0) ? 0 : (rx1));\
(r)->y1 = (((ry1) < 0) ? 0 : (ry1));\
(r)->x2 = (((rx2) < 0) ? 0 : (rx2));\
(r)->y2 = (((ry2) < 0) ? 0 : (ry2));\
(reg)->numRects++;\
(r)++;\
}\
}
/*
* This set of utilities is primarily used for functions needed
* by Union.c. NOT by UnionS.c .
*/
BOX *IndexAddRects();
/*
* combinRegs(newReg, reg1, reg2)
* if one region is above or below the other.
*/
combineRegs(newReg, reg1, reg2)
register REGION *newReg;
REGION *reg1;
REGION *reg2;
{
extern REGION *RegionCreate();
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;
tempReg = RegionCreate(NULL, total);
/* region 1 is below region 2 */
if (reg1->extents.y1 > reg2->extents.y1)
{
RegionCopy(tempReg, reg2);
rects = &tempReg->rects[tempReg->numRects];
total -= tempReg->numRects;
while (total--)
*rects++ = *rects1++;
}
else
{
RegionCopy(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);
RegionCopy(newReg, tempReg);
/*
if (newReg->size)
Xfree(newReg->rects);
*newReg = *tempReg;
Xfree(tempReg);
*/
}
/*
* TopRects(rects, reg1, reg2)
*/
int
TopRects(newReg, rects, reg1, size1, reg2, size2, FirstRect)
register REGION *newReg;
register BOX *rects;
register REGION *reg1;
int size1;
register REGION *reg2;
int size2;
BOX *FirstRect;
{
register BOX *tempRects;
register int num;
num = 0;
/* need to add some rects from region 1 */
if (reg1->extents.y1 < reg2->extents.y1)
{
tempRects = reg1->rects;
while((tempRects->y1 < reg2->extents.y1) &&
(tempRects != reg1->rects+size1))
{
MEMCHECK(newReg, rects, FirstRect);
ADDRECTNOX(newReg,rects, tempRects->x1, tempRects->y1,
tempRects->x2, MIN(tempRects->y2, reg2->extents.y1));
num++;
tempRects++;
}
}
/* need to add some rects from region 2 */
if (reg2->extents.y1 < reg1->extents.y1)
{
tempRects = reg2->rects;
while ((tempRects->y1 < reg1->extents.y1) &&
(tempRects != reg2->rects+size2))
{
MEMCHECK(newReg, rects, FirstRect);
ADDRECTNOX(newReg, rects, tempRects->x1,tempRects->y1,
tempRects->x2, MIN(tempRects->y2, reg1->extents.y1));
tempRects++;
num++;
}
}
return(num);
}
/*
* QuickCheck checks to see if it does not have to go through all the
* the ugly code for the region call. It returns 1 if it did all
* the work for Union, otherwise 0 - still work to be done.
*/
int
QuickCheck(newReg, reg1, reg2)
REGION *newReg, *reg1, *reg2;
{
/* if unioning with itself or no rects to union with */
if ( (reg1 == reg2) || (!(reg1->numRects)) )
{
RegionCopy(newReg, reg2);
return(1);
}
/* if nothing to union */
if (!(reg2->numRects))
{
RegionCopy(newReg, reg1);
return(1);
}
/* could put an extent check to see if add above or below */
if ((reg1->extents.y1 >= reg2->extents.y2) ||
(reg2->extents.y1 >= reg1->extents.y2) )
{
combineRegs(newReg, reg1, reg2);
return(1);
}
return(0);
}