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

📄 miregion.c

📁 远程桌面连接工具
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    else if (!reg1->data && !reg2->data)    {	/* Covers about 80% of cases that aren't trivially rejected */	newReg->extents.x1 = max(reg1->extents.x1, reg2->extents.x1);	newReg->extents.y1 = max(reg1->extents.y1, reg2->extents.y1);	newReg->extents.x2 = min(reg1->extents.x2, reg2->extents.x2);	newReg->extents.y2 = min(reg1->extents.y2, reg2->extents.y2);	xfreeData(newReg);	newReg->data = (RegDataPtr)NULL;    }    else if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))    {	return miRegionCopy(newReg, reg1);    }    else if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))    {	return miRegionCopy(newReg, reg2);    }    else if (reg1 == reg2)    {	return miRegionCopy(newReg, reg1);    }    else    {	/* General purpose intersection */	Bool overlap; /* result ignored */	if (!miRegionOp(newReg, reg1, reg2, miIntersectO, FALSE, FALSE,			&overlap))	    return FALSE;	miSetExtents(newReg);    }    good(newReg);    return(TRUE);}#define MERGERECT(r)						\{								\    if (r->x1 <= x2) {						\	/* Merge with current rectangle */			\	if (r->x1 < x2) *pOverlap = TRUE;				\	if (x2 < r->x2) x2 = r->x2;				\    } else {							\	/* Add current rectangle, start new one */		\	NEWRECT(pReg, pNextRect, x1, y1, x2, y2);		\	x1 = r->x1;						\	x2 = r->x2;						\    }								\    r++;							\}/*====================================================================== *	    Region Union *====================================================================*//*- *----------------------------------------------------------------------- * miUnionO -- *	Handle an overlapping band for the union operation. Picks the *	left-most rectangle each time and merges it into the region. * * Results: *	TRUE if successful. * * Side Effects: *	pReg is overwritten. *	pOverlap is set to TRUE if any boxes overlap. * *----------------------------------------------------------------------- */static BoolmiUnionO (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 BoxPtr     pNextRect;    register int        x1;     /* left and right side of current union */    register int        x2;    assert (y1 < y2);    assert(r1 != r1End && r2 != r2End);    pNextRect = REGION_TOP(pReg);    /* Start off current rectangle */    if (r1->x1 < r2->x1)    {	x1 = r1->x1;	x2 = r1->x2;	r1++;    }    else    {	x1 = r2->x1;	x2 = r2->x2;	r2++;    }    while (r1 != r1End && r2 != r2End)    {	if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);    }    /* Finish off whoever (if any) is left */    if (r1 != r1End)    {	do	{	    MERGERECT(r1);	} while (r1 != r1End);    }    else if (r2 != r2End)    {	do	{	    MERGERECT(r2);	} while (r2 != r2End);    }        /* Add current rectangle */    NEWRECT(pReg, pNextRect, x1, y1, x2, y2);    return TRUE;}Bool miUnion(newReg, reg1, reg2)    RegionPtr		newReg;                  /* destination Region */    register RegionPtr 	reg1;    register RegionPtr	reg2;             /* source regions     */{    Bool overlap; /* result ignored */    /* Return TRUE if some overlap between reg1, reg2 */    good(reg1);    good(reg2);    good(newReg);    /*  checks all the simple cases */    /*     * Region 1 and 2 are the same     */    if (reg1 == reg2)    {	return miRegionCopy(newReg, reg1);    }    /*     * Region 1 is empty     */    if (REGION_NIL(reg1))    {        if (newReg != reg2)	    return miRegionCopy(newReg, reg2);        return TRUE;    }    /*     * Region 2 is empty     */    if (REGION_NIL(reg2))    {        if (newReg != reg1)	    return miRegionCopy(newReg, reg1);        return TRUE;    }    /*     * Region 1 completely subsumes region 2     */    if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))    {        if (newReg != reg1)	    return miRegionCopy(newReg, reg1);        return TRUE;    }    /*     * Region 2 completely subsumes region 1     */    if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))    {        if (newReg != reg2)	    return miRegionCopy(newReg, reg2);        return TRUE;    }    if (!miRegionOp(newReg, reg1, reg2, miUnionO, TRUE, TRUE, &overlap))	return FALSE;    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);    good(newReg);    return TRUE;}/*====================================================================== *	    Batch Rectangle Union *====================================================================*//*- *----------------------------------------------------------------------- * miRegionAppend -- *  *      "Append" the rgn rectangles onto the end of dstrgn, maintaining *      knowledge of YX-banding when it's easy.  Otherwise, dstrgn just *      becomes a non-y-x-banded random collection of rectangles, and not *      yet a true region.  After a sequence of appends, the caller must *      call miRegionValidate to ensure that a valid region is constructed. * * Results: *	TRUE if successful. * * Side Effects: *      dstrgn is modified if rgn has rectangles. * */BoolmiRegionAppend(dstrgn, rgn)    register RegionPtr dstrgn;    register RegionPtr rgn;{    int numRects, dnumRects, size;    BoxPtr new, old;    Bool prepend;    if (!rgn->data && (dstrgn->data == &miEmptyData))    {	dstrgn->extents = rgn->extents;	dstrgn->data = (RegDataPtr)NULL;	return TRUE;    }    numRects = REGION_NUM_RECTS(rgn);    if (!numRects)	return TRUE;    prepend = FALSE;    size = numRects;    dnumRects = REGION_NUM_RECTS(dstrgn);    if (!dnumRects && (size < 200))	size = 200; /* XXX pick numbers out of a hat */    RECTALLOC(dstrgn, size);    old = REGION_RECTS(rgn);    if (!dnumRects)	dstrgn->extents = rgn->extents;    else if (dstrgn->extents.x2 > dstrgn->extents.x1)    {	register BoxPtr first, last;	first = old;	last = REGION_BOXPTR(dstrgn) + (dnumRects - 1);	if ((first->y1 > last->y2) ||	    ((first->y1 == last->y1) && (first->y2 == last->y2) &&	     (first->x1 > last->x2)))	{	    if (rgn->extents.x1 < dstrgn->extents.x1)		dstrgn->extents.x1 = rgn->extents.x1;	    if (rgn->extents.x2 > dstrgn->extents.x2)		dstrgn->extents.x2 = rgn->extents.x2;	    dstrgn->extents.y2 = rgn->extents.y2;	}	else	{	    first = REGION_BOXPTR(dstrgn);	    last = old + (numRects - 1);	    if ((first->y1 > last->y2) ||		((first->y1 == last->y1) && (first->y2 == last->y2) &&		 (first->x1 > last->x2)))	    {		prepend = TRUE;		if (rgn->extents.x1 < dstrgn->extents.x1)		    dstrgn->extents.x1 = rgn->extents.x1;		if (rgn->extents.x2 > dstrgn->extents.x2)		    dstrgn->extents.x2 = rgn->extents.x2;		dstrgn->extents.y1 = rgn->extents.y1;	    }	    else		dstrgn->extents.x2 = dstrgn->extents.x1;	}    }    if (prepend)    {	new = REGION_BOX(dstrgn, numRects);	if (dnumRects == 1)	    *new = *REGION_BOXPTR(dstrgn);	else	    memmove((char *)new,(char *)REGION_BOXPTR(dstrgn), 		  dnumRects * sizeof(BoxRec));	new = REGION_BOXPTR(dstrgn);    }    else	new = REGION_BOXPTR(dstrgn) + dnumRects;    if (numRects == 1)	*new = *old;    else	memmove((char *)new, (char *)old, numRects * sizeof(BoxRec));    dstrgn->data->numRects += numRects;    return TRUE;}   #define ExchangeRects(a, b) \{			    \    BoxRec     t;	    \    t = rects[a];	    \    rects[a] = rects[b];    \    rects[b] = t;	    \}static voidQuickSortRects(rects, numRects)    register BoxRec     rects[];    register int        numRects;{    register int	y1;    register int	x1;    register int        i, j;    register BoxPtr     r;    /* Always called with numRects > 1 */    do    {	if (numRects == 2)	{	    if (rects[0].y1 > rects[1].y1 ||		    (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))		ExchangeRects(0, 1);	    return;	}	/* Choose partition element, stick in location 0 */        ExchangeRects(0, numRects >> 1);	y1 = rects[0].y1;	x1 = rects[0].x1;        /* Partition array */        i = 0;        j = numRects;        do	{	    r = &(rects[i]);	    do	    {		r++;		i++;            } while (i != numRects &&		     (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));	    r = &(rects[j]);	    do	    {		r--;		j--;            } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));            if (i < j)		ExchangeRects(i, j);        } while (i < j);        /* Move partition element back to middle */        ExchangeRects(0, j);	/* Recurse */        if (numRects-j-1 > 1)	    QuickSortRects(&rects[j+1], numRects-j-1);        numRects = j;    } while (numRects > 1);}/*- *----------------------------------------------------------------------- * miRegionValidate -- *  *      Take a ``region'' which is a non-y-x-banded random collection of *      rectangles, and compute a nice region which is the union of all the *      rectangles. * * Results: *	TRUE if successful. * * Side Effects: *      The passed-in ``region'' may be modified. *	pOverlap set to TRUE if any retangles overlapped, else FALSE; * * Strategy: *      Step 1. Sort the rectangles into ascending order with primary key y1 *		and secondary key x1. * *      Step 2. Split the rectangles into the minimum number of proper y-x *		banded regions.  This may require horizontally merging *		rectangles, and vertically coalescing bands.  With any luck, *		this step in an identity tranformation (ala the Box widget), *		or a coalescing into 1 box (ala Menus). * *	Step 3. Merge the separate regions down to a single region by calling *		miUnion.  Maximize the work each miUnion call does by using *		a binary merge. * *----------------------------------------------------------------------- */BoolmiRegionValidate(badreg, pOverlap)    RegionPtr badreg;    Bool *pOverlap;{    /* Descriptor for regions under construction  in Step 2. */    typedef struct {	RegionRec   reg;	int	    prevBand;	int	    curBand;    } RegionInfo;	     int	numRects;   /* Original numRects for badreg	    */	     RegionInfo *ri;	    /* Array of current regions		    */    	     int	numRI;      /* Number of entries used in ri	    */	     int	sizeRI;	    /* Number of entries available in ri    */	     int	i;	    /* Index into rects			    */    register int	j;	    /* Index into ri			    */    register RegionInfo *rit;       /* &ri[j]				    */    register RegionPtr  reg;        /* ri[j].reg			    */    register BoxPtr	box;	    /* Current box in rects		    */    register BoxPtr	riBox;      /* Last box in ri[j].reg		    */    register RegionPtr  hreg;       /* ri[j_half].reg			    */    *pOverlap = FALSE;    if (!badreg->data)    {	good(badreg);	return TRUE;    }    numRects = badreg->data->numRects;    if (!numRects)    {	good(badreg);	return TRUE;    }    if (badreg->extents.x1 < badreg->extents.x2)    {	if ((numRects) == 1)	{	    xfreeData(badreg);	    badreg->data = (RegDataPtr) NULL;	}	else	{	    DOWNSIZE(badreg, numRects);	}	good(badreg);	return TRUE;    }    /* Step 1: Sort the rects array into ascending (y1, x1) order */    QuickSortRects(REGION_BOXPTR(badreg), numRects);    /* Step 2: Scatter the sorted array into the minimum number of regions */    /* Set up the first region to be the first rectangle in badreg */    /* Note that step 2 code will never overflow the ri[0].reg rects array */    Must_have_memory = TRUE; /* XXX */    ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo));    Must_have_memory = FALSE; /* XXX */    sizeRI = 4;    numRI = 1;    ri[0].prevBand = 0;    ri[0].curBand = 0;    ri[0].reg = *badreg;    box = REGION_BOXPTR(&ri[0].reg);    ri[0].reg.extents = *box;    ri[0].reg.data->numRects = 1;    /* Now scatter rectangles into the minimum set of valid regions.  If the       next rectangle to be added to a region would force an existing rectangle       in the region to be split up in order to maintain y-x banding, just       forget it.  Try the next region.  If it doesn't fit cleanly into any       region, make a new one. */

⌨️ 快捷键说明

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