📄 pixregion.c
字号:
* minuend */ r2++; } } else if (r2->x1 < r1->x2) { /* * Left part of subtrahend covers part of minuend: add uncovered * part of minuend to region and skip to next subtrahend. */ assert(x1<r2->x1); NEWRECT(region, pNextRect, x1, y1, r2->x1, y2); x1 = r2->x2; if (x1 >= r1->x2) { /* * Minuend used up: advance to new... */ r1++; if (r1 != r1End) x1 = r1->x1; } else { /* * Subtrahend used up */ r2++; } } else { /* * Minuend used up: add any remaining piece before advancing. */ if (r1->x2 > x1) NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); r1++; if (r1 != r1End) x1 = r1->x1; } } while ((r1 != r1End) && (r2 != r2End)); /* * Add remaining minuend rectangles to region. */ while (r1 != r1End) { assert(x1<r1->x2); NEWRECT(region, pNextRect, x1, y1, r1->x2, y2); r1++; if (r1 != r1End) x1 = r1->x1; } return PIXMAN_REGION_STATUS_SUCCESS;}/*- *----------------------------------------------------------------------- * pixman_region_subtract -- * Subtract regS from regM and leave the result in regD. * S stands for subtrahend, M for minuend and D for difference. * * Results: * PIXMAN_REGION_STATUS_SUCCESS if successful. * * Side Effects: * regD is overwritten. * *----------------------------------------------------------------------- */pixman_region_status_tpixman_region_subtract(pixman_region16_t * regD, pixman_region16_t * regM, pixman_region16_t * regS){ int overlap; /* result ignored */ good(regM); good(regS); good(regD); /* check for trivial rejects */ if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) || !EXTENTCHECK(®M->extents, ®S->extents)) { if (PIXREGION_NAR (regS)) return pixman_break (regD); return pixman_region_copy(regD, regM); } else if (regM == regS) { freeData(regD); regD->extents.x2 = regD->extents.x1; regD->extents.y2 = regD->extents.y1; regD->data = &pixman_region_emptyData; return PIXMAN_REGION_STATUS_SUCCESS; } /* Add those rectangles in region 1 that aren't in region 2, do yucky substraction for overlaps, and just throw away rectangles in region 2 that aren't in region 1 */ if (!pixman_op(regD, regM, regS, pixman_region_subtractO, PIXMAN_REGION_STATUS_SUCCESS, PIXMAN_REGION_STATUS_FAILURE, &overlap)) return PIXMAN_REGION_STATUS_FAILURE; /* * Can't alter RegD's extents before we call pixman_op because * it might be one of the source regions and pixman_op depends * on the extents of those regions being unaltered. Besides, this * way there's no checking against rectangles that will be nuked * due to coalescing, so we have to examine fewer rectangles. */ pixman_set_extents(regD); good(regD); return PIXMAN_REGION_STATUS_SUCCESS;}/*====================================================================== * Region Inversion *====================================================================*//*- *----------------------------------------------------------------------- * pixman_region_inverse -- * Take a region and a box and return a region that is everything * in the box but not in the region. The careful reader will note * that this is the same as subtracting the region from the box... * * Results: * PIXMAN_REGION_STATUS_SUCCESS. * * Side Effects: * newReg is overwritten. * *----------------------------------------------------------------------- */pixman_region_status_tpixman_region_inverse(pixman_region16_t * newReg, /* Destination region */ pixman_region16_t * reg1, /* Region to invert */ pixman_box16_t * invRect) /* Bounding box for inversion */{ pixman_region16_t invReg; /* Quick and dirty region made from the * bounding box */ int overlap; /* result ignored */ good(reg1); good(newReg); /* check for trivial rejects */ if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents)) { if (PIXREGION_NAR(reg1)) return pixman_break (newReg); newReg->extents = *invRect; freeData(newReg); newReg->data = (pixman_region16_data_t *)NULL; return PIXMAN_REGION_STATUS_SUCCESS; } /* Add those rectangles in region 1 that aren't in region 2, do yucky substraction for overlaps, and just throw away rectangles in region 2 that aren't in region 1 */ invReg.extents = *invRect; invReg.data = (pixman_region16_data_t *)NULL; if (!pixman_op(newReg, &invReg, reg1, pixman_region_subtractO, PIXMAN_REGION_STATUS_SUCCESS, PIXMAN_REGION_STATUS_FAILURE, &overlap)) return PIXMAN_REGION_STATUS_FAILURE; /* * Can't alter newReg's extents before we call pixman_op because * it might be one of the source regions and pixman_op depends * on the extents of those regions being unaltered. Besides, this * way there's no checking against rectangles that will be nuked * due to coalescing, so we have to examine fewer rectangles. */ pixman_set_extents(newReg); good(newReg); return PIXMAN_REGION_STATUS_SUCCESS;}/* * RectIn(region, rect) * This routine takes a pointer to a region and a pointer to a box * and determines if the box is outside/inside/partly inside the region. * * The idea is to travel through the list of rectangles trying to cover the * passed box with them. Anytime a piece of the rectangle isn't covered * by a band of rectangles, partOut is set PIXMAN_REGION_STATUS_SUCCESS. Any time a rectangle in * the region covers part of the box, partIn is set PIXMAN_REGION_STATUS_SUCCESS. The process ends * when either the box has been completely covered (we reached a band that * doesn't overlap the box, partIn is PIXMAN_REGION_STATUS_SUCCESS and partOut is false), the * box has been partially covered (partIn == partOut == PIXMAN_REGION_STATUS_SUCCESS -- because of * the banding, the first time this is true we know the box is only * partially in the region) or is outside the region (we reached a band * that doesn't overlap the box at all and partIn is false) */intpixman_region_contains_rectangle(pixman_region16_t * region, pixman_box16_t * prect){ int x; int y; pixman_box16_t * pbox; pixman_box16_t * pboxEnd; int partIn, partOut; int numRects; good(region); numRects = PIXREGION_NUM_RECTS(region); /* useful optimization */ if (!numRects || !EXTENTCHECK(®ion->extents, prect)) return(rgnOUT); if (numRects == 1) { /* We know that it must be rgnIN or rgnPART */ if (SUBSUMES(®ion->extents, prect)) return(rgnIN); else return(rgnPART); } partOut = PIXMAN_REGION_STATUS_FAILURE; partIn = PIXMAN_REGION_STATUS_FAILURE; /* (x,y) starts at upper left of rect, moving to the right and down */ x = prect->x1; y = prect->y1; /* can stop when both partOut and partIn are PIXMAN_REGION_STATUS_SUCCESS, or we reach prect->y2 */ for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; pbox != pboxEnd; pbox++) { if (pbox->y2 <= y) continue; /* getting up to speed or skipping remainder of band */ if (pbox->y1 > y) { partOut = PIXMAN_REGION_STATUS_SUCCESS; /* missed part of rectangle above */ if (partIn || (pbox->y1 >= prect->y2)) break; y = pbox->y1; /* x guaranteed to be == prect->x1 */ } if (pbox->x2 <= x) continue; /* not far enough over yet */ if (pbox->x1 > x) { partOut = PIXMAN_REGION_STATUS_SUCCESS; /* missed part of rectangle to left */ if (partIn) break; } if (pbox->x1 < prect->x2) { partIn = PIXMAN_REGION_STATUS_SUCCESS; /* definitely overlap */ if (partOut) break; } if (pbox->x2 >= prect->x2) { y = pbox->y2; /* finished with this band */ if (y >= prect->y2) break; x = prect->x1; /* reset x out to left again */ } else { /* * Because boxes in a band are maximal width, if the first box * to overlap the rectangle doesn't completely cover it in that * band, the rectangle must be partially out, since some of it * will be uncovered in that band. partIn will have been set true * by now... */ partOut = PIXMAN_REGION_STATUS_SUCCESS; break; } } return(partIn ? ((y < prect->y2) ? rgnPART : rgnIN) : rgnOUT);}/* pixman_region_translate (region, x, y) translates in place*/voidpixman_region_translate (pixman_region16_t * region, int x, int y){ int x1, x2, y1, y2; int nbox; pixman_box16_t * pbox; good(region); region->extents.x1 = x1 = region->extents.x1 + x; region->extents.y1 = y1 = region->extents.y1 + y; region->extents.x2 = x2 = region->extents.x2 + x; region->extents.y2 = y2 = region->extents.y2 + y; if (((x1 - SHRT_MIN)|(y1 - SHRT_MIN)|(SHRT_MAX - x2)|(SHRT_MAX - y2)) >= 0) { if (region->data && (nbox = region->data->numRects)) { for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) { pbox->x1 += x; pbox->y1 += y; pbox->x2 += x; pbox->y2 += y; } } return; } if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)|(SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) { region->extents.x2 = region->extents.x1; region->extents.y2 = region->extents.y1; freeData(region); region->data = &pixman_region_emptyData; return; } if (x1 < SHRT_MIN) region->extents.x1 = SHRT_MIN; else if (x2 > SHRT_MAX) region->extents.x2 = SHRT_MAX; if (y1 < SHRT_MIN) region->extents.y1 = SHRT_MIN; else if (y2 > SHRT_MAX) region->extents.y2 = SHRT_MAX; if (region->data && (nbox = region->data->numRects)) { pixman_box16_t * pboxout; for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++) { pboxout->x1 = x1 = pbox->x1 + x; pboxout->y1 = y1 = pbox->y1 + y; pboxout->x2 = x2 = pbox->x2 + x; pboxout->y2 = y2 = pbox->y2 + y; if (((x2 - SHRT_MIN)|(y2 - SHRT_MIN)| (SHRT_MAX - x1)|(SHRT_MAX - y1)) <= 0) { region->data->numRects--; continue; } if (x1 < SHRT_MIN) pboxout->x1 = SHRT_MIN; else if (x2 > SHRT_MAX) pboxout->x2 = SHRT_MAX; if (y1 < SHRT_MIN) pboxout->y1 = SHRT_MIN; else if (y2 > SHRT_MAX) pboxout->y2 = SHRT_MAX; pboxout++; } if (pboxout != pbox) { if (region->data->numRects == 1) { region->extents = *PIXREGION_BOXPTR(region); freeData(region); region->data = (pixman_region16_data_t *)NULL; } else pixman_set_extents(region); } }}/* XXX: Do we need this?static pixman_region_status_tpixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src){ good(dst); good(src); if (dst->data) return PIXMAN_REGION_STATUS_SUCCESS; if (dst == src) return PIXMAN_REGION_STATUS_SUCCESS; if (!src->data || !src->data->size) { freeData(dst); dst->data = (pixman_region16_data_t *)NULL; return PIXMAN_REGION_STATUS_SUCCESS; } if (!dst->data || (dst->data->size < src->data->numRects)) { freeData(dst); dst->data = allocData(src->data->numRects); if (!dst->data) return pixman_break (dst); } dst->data->size = src->data->size; dst->data->numRects = src->data->numRects; return PIXMAN_REGION_STATUS_SUCCESS;}*/voidpixman_region_reset(pixman_region16_t *region, pixman_box16_t *box){ good(region); assert(box->x1<=box->x2); assert(box->y1<=box->y2); region->extents = *box; freeData(region); region->data = (pixman_region16_data_t *)NULL;}/* box is "return" value */intpixman_region_contains_point(pixman_region16_t * region, int x, int y, pixman_box16_t * box){ pixman_box16_t *pbox, *pboxEnd; int numRects; good(region); numRects = PIXREGION_NUM_RECTS(region); if (!numRects || !INBOX(®ion->extents, x, y)) return(PIXMAN_REGION_STATUS_FAILURE); if (numRects == 1) { *box = region->extents; return(PIXMAN_REGION_STATUS_SUCCESS); } for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects; pbox != pboxEnd; pbox++) { if (y >= pbox->y2) continue; /* not there yet */ if ((y < pbox->y1) || (x < pbox->x1)) break; /* missed it */ if (x >= pbox->x2) continue; /* not there yet */ *box = *pbox; return(PIX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -