#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); }