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

📄 pixman-region.c

📁 嵌入式图形库
💻 C
📖 第 1 页 / 共 5 页
字号:
pixman_coalesce (    pixman_region16_t *	region,	    	/* Region to coalesce		     */    int	    	  	prevStart,  	/* Index of start of previous band   */    int	    	  	curStart)   	/* Index of start of current band    */{    pixman_box16_t *	pPrevBox;   	/* Current box in previous band	     */    pixman_box16_t *	pCurBox;    	/* Current box in current band       */    int  	numRects;	/* Number rectangles in both bands   */    int	y2;		/* Bottom of current band	     */    /*     * Figure out how many rectangles are in the band.     */    numRects = curStart - prevStart;    assert(numRects == region->data->numRects - curStart);    if (!numRects) return curStart;    /*     * The bands may only be coalesced if the bottom of the previous     * matches the top scanline of the current.     */    pPrevBox = PIXREGION_BOX(region, prevStart);    pCurBox = PIXREGION_BOX(region, curStart);    if (pPrevBox->y2 != pCurBox->y1) return curStart;    /*     * 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.     */    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;    region->data->numRects -= numRects;    do {	pPrevBox--;	pPrevBox->y2 = y2;	numRects--;    } while (numRects);    return prevStart;}/* Quicky macro to avoid trivial reject procedure calls to pixman_coalesce */#define Coalesce(newReg, prevBand, curBand)				\    if (curBand - prevBand == newReg->data->numRects - curBand) {	\	prevBand = pixman_coalesce(newReg, prevBand, curBand);		\    } else {								\	prevBand = curBand;						\    }/*- *----------------------------------------------------------------------- * pixman_region_appendNonO -- *	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: *	region->data->numRects is incremented and the rectangles overwritten *	with the rectangles we're passed. * *----------------------------------------------------------------------- */static inline pixman_bool_tpixman_region_appendNonO (    pixman_region16_t *	region,    pixman_box16_t *	r,    pixman_box16_t *  	  	rEnd,    int  	y1,    int  	y2){    pixman_box16_t *	pNextRect;    int	newRects;    newRects = rEnd - r;    assert(y1 < y2);    assert(newRects != 0);    /* Make sure we have enough space for all rectangles to be added */    RECTALLOC(region, newRects);    pNextRect = PIXREGION_TOP(region);    region->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 *)PIXREGION_TOP(newReg),(char *)r, 			\              newRects * sizeof(pixman_box16_t));				\	newReg->data->numRects += newRects;				\    }									\}/*- *----------------------------------------------------------------------- * pixman_op -- *	Apply an operation to two regions. Called by pixman_region_union, pixman_region_inverse, *	pixman_region_subtract, pixman_region_intersect....  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. * *----------------------------------------------------------------------- */typedef pixman_bool_t (*OverlapProcPtr)(    pixman_region16_t	 *region,    pixman_box16_t *r1,    pixman_box16_t *r1End,    pixman_box16_t *r2,    pixman_box16_t *r2End,    short    	 y1,    short    	 y2,    int		 *pOverlap);static pixman_bool_tpixman_op(    pixman_region16_t *newReg,		    /* Place to store result	     */    pixman_region16_t *       reg1,		    /* First region in operation     */    pixman_region16_t *       reg2,		    /* 2d region in operation        */    OverlapProcPtr  overlapFunc,            /* Function to call for over-					     * lapping bands		     */    int	    appendNon1,		    /* Append non-overlapping bands  */					    /* in region 1 ? */    int	    appendNon2,		    /* Append non-overlapping bands  */					    /* in region 2 ? */    int	    *pOverlap){    pixman_box16_t * r1;			    /* Pointer into first region     */    pixman_box16_t * r2;			    /* Pointer into 2d region	     */    pixman_box16_t *	    r1End;		    /* End of 1st region	     */    pixman_box16_t *	    r2End;		    /* End of 2d region		     */    short	    ybot;		    /* Bottom of intersection	     */    short	    ytop;		    /* Top of intersection	     */    pixman_region16_data_t *	    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		     */    pixman_box16_t * r1BandEnd;		    /* End of current band in r1     */    pixman_box16_t * r2BandEnd;		    /* End of current band in r2     */    short	    top;		    /* Top of non-overlapping band   */    short	    bot;		    /* Bottom of non-overlapping band*/    int    r1y1;		    /* Temps for r1->y1 and r2->y1   */    int    r2y1;    int		    newSize;    int		    numRects;    /*     * Break any region computed from a broken region     */    if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))	return pixman_break (newReg);    /*     * 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 = PIXREGION_RECTS(reg1);    newSize = PIXREGION_NUM_RECTS(reg1);    r1End = r1 + newSize;    numRects = PIXREGION_NUM_RECTS(reg2);    r2 = PIXREGION_RECTS(reg2);    r2End = r2 + numRects;    assert(r1 != r1End);    assert(r2 != r2End);    oldData = (pixman_region16_data_t *)NULL;    if (((newReg == reg1) && (newSize > 1)) ||	((newReg == reg2) && (numRects > 1)))    {	oldData = newReg->data;	newReg->data = pixman_region_emptyData;    }    /* guess at new size */    if (numRects > newSize)	newSize = numRects;    newSize <<= 1;    if (!newReg->data)	newReg->data = pixman_region_emptyData;    else if (newReg->data->size)	newReg->data->numRects = 0;    if (newSize > newReg->data->size) {	if (!pixman_rect_alloc(newReg, newSize)) {	    if (oldData)		free (oldData);	    return FALSE;	}    }    /*     * 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. pixman_coalesce, 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;		    pixman_region_appendNonO(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;		    pixman_region_appendNonO(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;	pixman_region_appendNonO(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;	pixman_region_appendNonO(newReg, r2, r2BandEnd, MAX(r2y1, ybot), r2->y2);	Coalesce(newReg, prevBand, curBand);	/* Append rest of boxes */	AppendRegions(newReg, r2BandEnd, r2End);    }    if (oldData)	free(oldData);    if (!(numRects = newReg->data->numRects))    {	freeData(newReg);	newReg->data = pixman_region_emptyData;    }    else if (numRects == 1)    {	newReg->extents = *PIXREGION_BOXPTR(newReg);	freeData(newReg);	newReg->data = (pixman_region16_data_t *)NULL;    }    else    {	DOWNSIZE(newReg, numRects);    }    return TRUE;}/*- *----------------------------------------------------------------------- * pixman_set_extents -- *	Reset the extents of a region to what they should be. Called by *	pixman_region_subtract and pixman_region_intersect as they can't figure it out along the *	way or do so easily, as pixman_region_union can. * * Results: *	None. * * Side Effects: *	The region's 'extents' structure is overwritten. * *----------------------------------------------------------------------- */static voidpixman_set_extents (pixman_region16_t *region){    pixman_box16_t *box, *boxEnd;    if (!region->data)	return;    if (!region->data->size)    {	region->extents.x2 = region->extents.x1;	region->extents.y2 = region->extents.y1;	return;    }    box = PIXREGION_BOXPTR(region);    boxEnd = PIXREGION_END(region);    /*     * Since box is the first rectangle in the region, it must have the     * smallest y1 and since boxEnd is the last rectangle in the region,     * it must have the largest y2, because of banding. Initialize x1 and     * x2 from  box and boxEnd, resp., as good things to initialize them     * to...     */    region->extents.x1 = box->x1;    region->extents.y1 = box->y1;    region->extents.x2 = boxEnd->x2;    region->extents.y2 = boxEnd->y2;    assert(region->extents.y1 < region->extents.y2);    while (box <= boxEnd) {	if (box->x1 < region->extents.x1)	    region->extents.x1 = box->x1;	if (box->x2 > region->extents.x2)	    region->extents.x2 = box->x2;	box++;    };    assert(region->extents.x1 < region->extents.x2);}/*====================================================================== *	    Region Intersection *====================================================================*//*- *----------------------------------------------------------------------- * pixman_region_intersectO -- *	Handle an overlapping band for pixman_region_intersect. * * Results: *	TRUE if successful. * * Side Effects: *	Rectangles may be added to the region. * *----------------------------------------------------------------------- */

⌨️ 快捷键说明

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