⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miregion.c

📁 远程桌面连接工具
💻 C
📖 第 1 页 / 共 5 页
字号:
     * cover the most area possible. I.e. two boxes in a band must     * have some horizontal space between them.     */    y2 = pCurBox->y2;    do {	if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {	    return (curStart);	}	pPrevBox++;	pCurBox++;	numRects--;    } while (numRects);    /*     * The bands may be merged, so set the bottom y of each box     * in the previous band to the bottom y of the current band.     */    numRects = curStart - prevStart;    pReg->data->numRects -= numRects;    do {	pPrevBox--;	pPrevBox->y2 = y2;	numRects--;    } while (numRects);    return prevStart;}/* Quicky macro to avoid trivial reject procedure calls to miCoalesce */#define Coalesce(newReg, prevBand, curBand)				\    if (curBand - prevBand == newReg->data->numRects - curBand) {	\	prevBand = miCoalesce(newReg, prevBand, curBand);		\    } else {								\	prevBand = curBand;						\    }/*- *----------------------------------------------------------------------- * miAppendNonO -- *	Handle a non-overlapping band for the union and subtract operations. *      Just adds the (top/bottom-clipped) rectangles into the region. *      Doesn't have to check for subsumption or anything. * * Results: *	None. * * Side Effects: *	pReg->data->numRects is incremented and the rectangles overwritten *	with the rectangles we're passed. * *----------------------------------------------------------------------- */INLINE static BoolmiAppendNonO (pReg, r, rEnd, y1, y2)    register RegionPtr	pReg;    register BoxPtr	r;    BoxPtr  	  	rEnd;    register int  	y1;    register int  	y2;{    register BoxPtr	pNextRect;    register int	newRects;    newRects = rEnd - r;    assert(y1 < y2);    assert(newRects != 0);    /* Make sure we have enough space for all rectangles to be added */    RECTALLOC(pReg, newRects);    pNextRect = REGION_TOP(pReg);    pReg->data->numRects += newRects;    do {	assert(r->x1 < r->x2);	ADDRECT(pNextRect, r->x1, y1, r->x2, y2);	r++;    } while (r != rEnd);    return TRUE;}#define FindBand(r, rBandEnd, rEnd, ry1)		    \{							    \    ry1 = r->y1;					    \    rBandEnd = r+1;					    \    while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) {   \	rBandEnd++;					    \    }							    \}#define	AppendRegions(newReg, r, rEnd)					\{									\    int newRects;							\    if (newRects = rEnd - r) {						\	RECTALLOC(newReg, newRects);					\	memmove((char *)REGION_TOP(newReg),(char *)r, 			\              newRects * sizeof(BoxRec));				\	newReg->data->numRects += newRects;				\    }									\}/*- *----------------------------------------------------------------------- * miRegionOp -- *	Apply an operation to two regions. Called by miUnion, miInverse, *	miSubtract, miIntersect....  Both regions MUST have at least one *      rectangle, and cannot be the same object. * * Results: *	TRUE if successful. * * Side Effects: *	The new region is overwritten. *	pOverlap set to TRUE if overlapFunc ever returns TRUE. * * Notes: *	The idea behind this function is to view the two regions as sets. *	Together they cover a rectangle of area that this function divides *	into horizontal bands where points are covered only by one region *	or by both. For the first case, the nonOverlapFunc is called with *	each the band and the band's upper and lower extents. For the *	second, the overlapFunc is called to process the entire band. It *	is responsible for clipping the rectangles in the band, though *	this function provides the boundaries. *	At the end of each band, the new region is coalesced, if possible, *	to reduce the number of rectangles in the region. * *----------------------------------------------------------------------- */static BoolmiRegionOp(newReg, reg1, reg2, overlapFunc, appendNon1, appendNon2, pOverlap)    RegionPtr       newReg;		    /* Place to store result	     */    RegionPtr       reg1;		    /* First region in operation     */    RegionPtr       reg2;		    /* 2d region in operation        */    Bool	    (*overlapFunc)();       /* Function to call for over-					     * lapping bands		     */    Bool	    appendNon1;		    /* Append non-overlapping bands  */					    /* in region 1 ? */    Bool	    appendNon2;		    /* Append non-overlapping bands  */					    /* in region 2 ? */    Bool	    *pOverlap;{    register BoxPtr r1;			    /* Pointer into first region     */    register BoxPtr r2;			    /* Pointer into 2d region	     */    BoxPtr	    r1End;		    /* End of 1st region	     */    BoxPtr	    r2End;		    /* End of 2d region		     */    short	    ybot;		    /* Bottom of intersection	     */    short	    ytop;		    /* Top of intersection	     */    RegDataPtr	    oldData;		    /* Old data for newReg	     */    int		    prevBand;		    /* Index of start of					     * previous band in newReg       */    int		    curBand;		    /* Index of start of current					     * band in newReg		     */    register BoxPtr r1BandEnd;		    /* End of current band in r1     */    register BoxPtr r2BandEnd;		    /* End of current band in r2     */    short	    top;		    /* Top of non-overlapping band   */    short	    bot;		    /* Bottom of non-overlapping band*/    register int    r1y1;		    /* Temps for r1->y1 and r2->y1   */    register int    r2y1;    int		    newSize;    int		    numRects;    /*     * Initialization:     *	set r1, r2, r1End and r2End appropriately, save the rectangles     * of the destination region until the end in case it's one of     * the two source regions, then mark the "new" region empty, allocating     * another array of rectangles for it to use.     */    r1 = REGION_RECTS(reg1);    newSize = REGION_NUM_RECTS(reg1);    r1End = r1 + newSize;    numRects = REGION_NUM_RECTS(reg2);    r2 = REGION_RECTS(reg2);    r2End = r2 + numRects;    assert(r1 != r1End);    assert(r2 != r2End);    oldData = (RegDataPtr)NULL;    if (((newReg == reg1) && (newSize > 1)) ||	((newReg == reg2) && (numRects > 1)))    {	oldData = newReg->data;	newReg->data = &miEmptyData;    }    /* guess at new size */    if (numRects > newSize)	newSize = numRects;    newSize <<= 1;    if (!newReg->data)	newReg->data = &miEmptyData;    else if (newReg->data->size)	newReg->data->numRects = 0;    if (newSize > newReg->data->size)	miRectAlloc(newReg, newSize);    /*     * Initialize ybot.     * In the upcoming loop, ybot and ytop serve different functions depending     * on whether the band being handled is an overlapping or non-overlapping     * band.     * 	In the case of a non-overlapping band (only one of the regions     * has points in the band), ybot is the bottom of the most recent     * intersection and thus clips the top of the rectangles in that band.     * ytop is the top of the next intersection between the two regions and     * serves to clip the bottom of the rectangles in the current band.     *	For an overlapping band (where the two regions intersect), ytop clips     * the top of the rectangles of both regions and ybot clips the bottoms.     */    ybot = min(r1->y1, r2->y1);        /*     * prevBand serves to mark the start of the previous band so rectangles     * can be coalesced into larger rectangles. qv. miCoalesce, above.     * In the beginning, there is no previous band, so prevBand == curBand     * (curBand is set later on, of course, but the first band will always     * start at index 0). prevBand and curBand must be indices because of     * the possible expansion, and resultant moving, of the new region's     * array of rectangles.     */    prevBand = 0;        do {	/*	 * This algorithm proceeds one source-band (as opposed to a	 * destination band, which is determined by where the two regions	 * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the	 * rectangle after the last one in the current band for their	 * respective regions.	 */	assert(r1 != r1End);	assert(r2 != r2End);    	FindBand(r1, r1BandEnd, r1End, r1y1);	FindBand(r2, r2BandEnd, r2End, r2y1);	/*	 * First handle the band that doesn't intersect, if any.	 *	 * Note that attention is restricted to one band in the	 * non-intersecting region at once, so if a region has n	 * bands between the current position and the next place it overlaps	 * the other, this entire loop will be passed through n times.	 */	if (r1y1 < r2y1) {	    if (appendNon1) {		top = max(r1y1, ybot);		bot = min(r1->y2, r2y1);		if (top != bot)	{		    curBand = newReg->data->numRects;		    miAppendNonO(newReg, r1, r1BandEnd, top, bot);		    Coalesce(newReg, prevBand, curBand);		}	    }	    ytop = r2y1;	} else if (r2y1 < r1y1) {	    if (appendNon2) {		top = max(r2y1, ybot);		bot = min(r2->y2, r1y1);		if (top != bot) {		    curBand = newReg->data->numRects;		    miAppendNonO(newReg, r2, r2BandEnd, top, bot);		    Coalesce(newReg, prevBand, curBand);		}	    }	    ytop = r1y1;	} else {	    ytop = r1y1;	}	/*	 * Now see if we've hit an intersecting band. The two bands only	 * intersect if ybot > ytop	 */	ybot = min(r1->y2, r2->y2);	if (ybot > ytop) {	    curBand = newReg->data->numRects;	    (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,			    pOverlap);	    Coalesce(newReg, prevBand, curBand);	}	/*	 * If we've finished with a band (y2 == ybot) we skip forward	 * in the region to the next band.	 */	if (r1->y2 == ybot) r1 = r1BandEnd;	if (r2->y2 == ybot) r2 = r2BandEnd;    } while (r1 != r1End && r2 != r2End);    /*     * Deal with whichever region (if any) still has rectangles left.     *     * We only need to worry about banding and coalescing for the very first     * band left.  After that, we can just group all remaining boxes,     * regardless of how many bands, into one final append to the list.     */    if ((r1 != r1End) && appendNon1) {	/* Do first nonOverlap1Func call, which may be able to coalesce */	FindBand(r1, r1BandEnd, r1End, r1y1);	curBand = newReg->data->numRects;	miAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2);	Coalesce(newReg, prevBand, curBand);	/* Just append the rest of the boxes  */	AppendRegions(newReg, r1BandEnd, r1End);    } else if ((r2 != r2End) && appendNon2) {	/* Do first nonOverlap2Func call, which may be able to coalesce */	FindBand(r2, r2BandEnd, r2End, r2y1);	curBand = newReg->data->numRects;	miAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2);	Coalesce(newReg, prevBand, curBand);	/* Append rest of boxes */	AppendRegions(newReg, r2BandEnd, r2End);    }    if (oldData)	xfree(oldData);    if (!(numRects = newReg->data->numRects))    {	xfreeData(newReg);	newReg->data = &miEmptyData;    }    else if (numRects == 1)    {	newReg->extents = *REGION_BOXPTR(newReg);	xfreeData(newReg);	newReg->data = (RegDataPtr)NULL;    }    else    {	DOWNSIZE(newReg, numRects);    }    return TRUE;}/*- *----------------------------------------------------------------------- * miSetExtents -- *	Reset the extents of a region to what they should be. Called by *	miSubtract and miIntersect as they can't figure it out along the *	way or do so easily, as miUnion can. * * Results: *	None. * * Side Effects: *	The region's 'extents' structure is overwritten. * *----------------------------------------------------------------------- */voidmiSetExtents (pReg)    register RegionPtr pReg;{    register BoxPtr pBox, pBoxEnd;    if (!pReg->data)	return;    if (!pReg->data->size)    {	pReg->extents.x2 = pReg->extents.x1;	pReg->extents.y2 = pReg->extents.y1;	return;    }    pBox = REGION_BOXPTR(pReg);    pBoxEnd = REGION_END(pReg);    /*     * Since pBox is the first rectangle in the region, it must have the     * smallest y1 and since pBoxEnd is the last rectangle in the region,     * it must have the largest y2, because of banding. Initialize x1 and     * x2 from  pBox and pBoxEnd, resp., as good things to initialize them     * to...     */    pReg->extents.x1 = pBox->x1;    pReg->extents.y1 = pBox->y1;    pReg->extents.x2 = pBoxEnd->x2;    pReg->extents.y2 = pBoxEnd->y2;    assert(pReg->extents.y1 < pReg->extents.y2);    while (pBox <= pBoxEnd) {	if (pBox->x1 < pReg->extents.x1)	    pReg->extents.x1 = pBox->x1;	if (pBox->x2 > pReg->extents.x2)	    pReg->extents.x2 = pBox->x2;	pBox++;    };    assert(pReg->extents.x1 < pReg->extents.x2);}/*====================================================================== *	    Region Intersection *====================================================================*//*- *----------------------------------------------------------------------- * miIntersectO -- *	Handle an overlapping band for miIntersect. * * Results: *	TRUE if successful. * * Side Effects: *	Rectangles may be added to the region. * *----------------------------------------------------------------------- *//*ARGSUSED*/static BoolmiIntersectO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap)    register RegionPtr	pReg;    register BoxPtr	r1;    BoxPtr  	  	r1End;    register BoxPtr	r2;    BoxPtr  	  	r2End;    short    	  	y1;    short    	  	y2;    Bool		*pOverlap;{    register int  	x1;    register int  	x2;    register BoxPtr	pNextRect;    pNextRect = REGION_TOP(pReg);    assert(y1 < y2);    assert(r1 != r1End && r2 != r2End);    do {	x1 = max(r1->x1, r2->x1);	x2 = min(r1->x2, r2->x2);	/*	 * If there's any overlap between the two rectangles, add that	 * overlap to the new region.	 */	if (x1 < x2)	    NEWRECT(pReg, pNextRect, x1, y1, x2, y2);	/*	 * Advance the pointer(s) with the leftmost right side, since the next	 * rectangle on that list may still overlap the other region's	 * current rectangle.	 */	if (r1->x2 == x2) {	    r1++;	}	if (r2->x2 == x2) {	    r2++;	}    } while ((r1 != r1End) && (r2 != r2End));    return TRUE;}BoolmiIntersect(newReg, reg1, reg2)    register RegionPtr 	newReg;     /* destination Region */    register RegionPtr 	reg1;    register RegionPtr	reg2;       /* source regions     */{    good(reg1);    good(reg2);    good(newReg);   /* check for trivial reject */    if (REGION_NIL(reg1)  || REGION_NIL(reg2) ||	!EXTENTCHECK(&reg1->extents, &reg2->extents))    {	/* Covers about 20% of all cases */	xfreeData(newReg);	newReg->extents.x2 = newReg->extents.x1;	newReg->extents.y2 = newReg->extents.y1;	newReg->data = &miEmptyData;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -