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

📄 region.c

📁 realvnc是一个非常流行的远程控制程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    {        miRegionCopy(newReg, reg1);        return TRUE;    }    /*   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 TRUE;    }    return FALSE;}/*   TopRects(rects, reg1, reg2) * N.B. We now assume that reg1 and reg2 intersect.  Therefore we are * NOT checking in the two while loops for stepping off the end of the * region.   */ static intTopRects(newReg, rects, reg1, reg2, FirstRect)    register XRegion newReg;    register BOX *rects;    register XRegion reg1;    register XRegion reg2;     BOX *FirstRect;{    register BOX *tempRects;    /*  need to add some rects from region 1 */    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++;	}    }    /*  need to add some rects from region 2 */    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/*====================================================================== *	    Generic Region Operator *====================================================================*//*- *----------------------------------------------------------------------- * miCoalesce -- *	Attempt to merge the boxes in the current band with those in the *	previous one. Used only by miRegionOp. * * Results: *	The new index for the previous band. * * Side Effects: *	If coalescing takes place: *	    - rectangles in the previous band will have their y2 fields *	      altered. *	    - pReg->numRects will be decreased. * *----------------------------------------------------------------------- *//* static int*/static intmiCoalesce (pReg, prevStart, curStart)    register XRegion	pReg;	    	/* Region to coalesce */    int	    	  	prevStart;  	/* Index of start of previous band */    int	    	  	curStart;   	/* Index of start of current band */{    register BoxPtr	pPrevBox;   	/* Current box in previous band */    register BoxPtr	pCurBox;    	/* Current box in current band */    register BoxPtr	pRegEnd;    	/* End of region */    int	    	  	curNumRects;	/* Number of rectangles in current					 * band */    int	    	  	prevNumRects;	/* Number of rectangles in previous					 * band */    int	    	  	bandY1;	    	/* Y1 coordinate for current band */    pRegEnd = &pReg->rects[pReg->numRects];    pPrevBox = &pReg->rects[prevStart];    prevNumRects = curStart - prevStart;    /*     * Figure out how many rectangles are in the current band. Have to do     * this because multiple bands could have been added in miRegionOp     * at the end when one region has been exhausted.     */    pCurBox = &pReg->rects[curStart];    bandY1 = pCurBox->y1;    for (curNumRects = 0;	 (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);	 curNumRects++)    {	pCurBox++;    }        if (pCurBox != pRegEnd)    {	/*	 * If more than one band was added, we have to find the start	 * of the last band added so the next coalescing job can start	 * at the right place... (given when multiple bands are added,	 * this may be pointless -- see above).	 */	pRegEnd--;	while (pRegEnd[-1].y1 == pRegEnd->y1)	{	    pRegEnd--;	}	curStart = pRegEnd - pReg->rects;	pRegEnd = pReg->rects + pReg->numRects;    }	    if ((curNumRects == prevNumRects) && (curNumRects != 0)) {	pCurBox -= curNumRects;	/*	 * The bands may only be coalesced if the bottom of the previous	 * matches the top scanline of the current.	 */	if (pPrevBox->y2 == pCurBox->y1)	{	    /*	     * Make sure the bands have boxes in the same places. This	     * assumes that boxes have been added in such a way that they	     * cover the most area possible. I.e. two boxes in a band must	     * have some horizontal space between them.	     */	    do	    {		if ((pPrevBox->x1 != pCurBox->x1) ||		    (pPrevBox->x2 != pCurBox->x2))		{		    /*		     * The bands don't line up so they can't be coalesced.		     */		    return (curStart);		}		pPrevBox++;		pCurBox++;		prevNumRects -= 1;	    } while (prevNumRects != 0);	    pReg->numRects -= curNumRects;	    pCurBox -= curNumRects;	    pPrevBox -= curNumRects;	    /*	     * The bands may be merged, so set the bottom y of each box	     * in the previous band to that of the corresponding box in	     * the current band.	     */	    do	    {		pPrevBox->y2 = pCurBox->y2;		pPrevBox++;		pCurBox++;		curNumRects -= 1;	    } while (curNumRects != 0);	    /*	     * If only one band was added to the region, we have to backup	     * curStart to the start of the previous band.	     *	     * If more than one band was added to the region, copy the	     * other bands down. The assumption here is that the other bands	     * came from the same region as the current one and no further	     * coalescing can be done on them since it's all been done	     * already... curStart is already in the right place.	     */	    if (pCurBox == pRegEnd)	    {		curStart = prevStart;	    }	    else	    {		do		{		    *pPrevBox++ = *pCurBox++;		} while (pCurBox != pRegEnd);	    }	    	}    }    return (curStart);}/*- *----------------------------------------------------------------------- * miRegionOp -- *	Apply an operation to two regions. Called by miUnion, miInverse, *	miSubtract, miIntersect... * * Results: *	None. * * Side Effects: *	The new region is overwritten. * * 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 void*/static voidmiRegionOp(newReg, reg1, reg2, overlapFunc,  nonOverlap1Func, nonOverlap2Func)    register XRegion 	newReg;	    	    	/* Place to store result */    XRegion	  	reg1;	    	    	/* First region in operation */    XRegion	  	reg2;	    	    	/* 2d region in operation */    void    	  	(*overlapFunc)();   	/* Function to call for over-						 * lapping bands */    void    	  	(*nonOverlap1Func)();	/* Function to call for non-						 * overlapping bands in region						 * 1 */    void    	  	(*nonOverlap2Func)();	/* Function to call for non-						 * overlapping bands in region						 * 2 */{    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 */    register short  	ybot;	    	    	/* Bottom of intersection */    register short  	ytop;	    	    	/* Top of intersection */    BoxPtr  	  	oldRects;   	    	/* Old rects 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 */        /*     * Initialization:     *	set r1, r2, r1End and r2End appropriately, preserve the important     * parts 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 = reg1->rects;    r2 = reg2->rects;    r1End = r1 + reg1->numRects;    r2End = r2 + reg2->numRects;        oldRects = newReg->rects;        EMPTY_REGION(newReg);    /*     * Allocate a reasonable number of rectangles for the new region. The idea     * is to allocate enough so the individual functions don't need to     * reallocate and copy the array, which is time consuming, yet we don't     * have to worry about using too much memory. I hope to be able to     * nuke the Xrealloc() at the end of this function eventually.     */    newReg->size = max(reg1->numRects,reg2->numRects) * 2;    if (! (newReg->rects = (BoxPtr)	   Xmalloc ((unsigned) (sizeof(BoxRec) * newReg->size)))) {	newReg->size = 0;	return;    }        /*     * Initialize ybot and ytop.     * 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.     */    if (reg1->extents.y1 < reg2->extents.y1)	ybot = reg1->extents.y1;    else	ybot = reg2->extents.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    {	curBand = newReg->numRects;	/*	 * 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.	 */	r1BandEnd = r1;	while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))	{	    r1BandEnd++;	}		r2BandEnd = r2;	while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))	{	    r2BandEnd++;	}		/*	 * 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 (r1->y1 < r2->y1)	{	    top = max(r1->y1,ybot);	    bot = min(r1->y2,r2->y1);	    if ((top != bot) && (nonOverlap1Func != (void (*)())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 != (void (*)())NULL))	    {		(* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot);	    }	    ytop = r1->y1;	}	else	{	    ytop = r1->y1;	}	/*	 * If any rectangles got added to the region, try and coalesce them	 * with rectangles from the previous band. Note we could just do	 * this test in miCoalesce, but some machines incur a not	 * inconsiderable cost for function calls, so...	 */	if (newReg->numRects != curBand)	{	    prevBand = miCoalesce (newReg, prevBand, curBand);	}	/*	 * Now see if we've hit an intersecting band. The two bands only	 * intersect if ybot > ytop	 */	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 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 still has rectangles left.     */    curBand = newReg->numRects;    if (r1 != r1End)    {	if (nonOverlap1Func != (void (*)())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 != (void (*)())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);    }    /*     * A bit of cleanup. To keep regions from growing without bound,     * we shrink the array of rectangles to match the new number of     * rectangles in the region. This never goes to 0, however...     *     * Only do this stuff if the number of rectangles allocated is more than     * twice the number of rectangles in the region (a simple optimization...).     */    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	{	    /*	     * No point in doing the extra work involved in an Xrealloc if	     * the region is empty	     */	    newReg->size = 1;	    Xfree((char *) newReg->rects);	    newReg->rects = (BoxPtr) Xmalloc(sizeof(BoxRec));	}    }    Xfree ((char *) oldRects);    return;}/*====================================================================== *	    Region Union *====================================================================*//*- *----------------------------------------------------------------------- * miUnionNonO -- *	Handle a non-overlapping band for the union operation. Just *	Adds the rectangles into the region. Doesn't have to check for *	subsumption or anything. * * Results: *	None. * * Side Effects: *	pReg->numRects is incremented and the final rectangles overwritten *	with the rectangles we're passed. * *----------------------------------------------------------------------- *//* static void*/static intmiUnionNonO (pReg, r, rEnd, y1, y2)    register XRegion	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++;    }

⌨️ 快捷键说明

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