📄 pixman-region.c
字号:
freeData(newReg); newReg->data = (pixman_region16_data_t *)NULL; return TRUE; } /* 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, TRUE, FALSE, &overlap)) return FALSE; /* * 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 TRUE;}/* * 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 TRUE. Any time a rectangle in * the region covers part of the box, partIn is set TRUE. The process ends * when either the box has been completely covered (we reached a band that * doesn't overlap the box, partIn is TRUE and partOut is false), the * box has been partially covered (partIn == partOut == TRUE -- 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) */pixman_region_overlap_tpixman_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(PIXMAN_REGION_OUT); if (numRects == 1) { /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */ if (SUBSUMES(®ion->extents, prect)) return(PIXMAN_REGION_IN); else return(PIXMAN_REGION_PART); } partOut = FALSE; partIn = FALSE; /* (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 TRUE, 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 = TRUE; /* 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 = TRUE; /* missed part of rectangle to left */ if (partIn) break; } if (pbox->x1 < prect->x2) { partIn = TRUE; /* 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 = TRUE; break; } } if (partIn) { if (y < prect->y2) return PIXMAN_REGION_PART; else return PIXMAN_REGION_IN; } else { return PIXMAN_REGION_OUT; }}/* 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_bool_tpixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src){ good(dst); good(src); if (dst->data) return TRUE; if (dst == src) return TRUE; if (!src->data || !src->data->size) { freeData(dst); dst->data = (pixman_region16_data_t *)NULL; return TRUE; } 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 TRUE;}*/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(FALSE); if (numRects == 1) { *box = region->extents; return(TRUE); } 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(TRUE); } return(FALSE);}intpixman_region_not_empty(pixman_region16_t * region){ good(region); return(!PIXREGION_NIL(region));}/* XXX: Do we need this?static intpixman_region16_broken(pixman_region16_t * region){ good(region); return (PIXREGION_NAR(region));}*/voidpixman_region_empty(pixman_region16_t * region){ good(region); freeData(region); region->extents.x2 = region->extents.x1; region->extents.y2 = region->extents.y1; region->data = pixman_region_emptyData;}pixman_box16_t *pixman_region_extents(pixman_region16_t * region){ good(region); return(®ion->extents);}#define ExchangeSpans(a, b) \{ \ pixman_region16_point_t tpt; \ int tw; \ \ tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \}/* ||| I should apply the merge sort code to rectangle sorting above, and see if mapping time can be improved. But right now I've been at work 12 hours, so forget it.*/static void QuickSortSpans( pixman_region16_point_t spans[], int widths[], int numSpans){ int y; int i, j, m; pixman_region16_point_t *r; /* Always called with numSpans > 1 */ /* Sorts only by y, doesn't bother to sort by x */ do { if (numSpans < 9) { /* Do insertion sort */ int yprev; yprev = spans[0].y; i = 1; do { /* while i != numSpans */ y = spans[i].y; if (yprev > y) { /* spans[i] is out of order. Move into proper location. */ pixman_region16_point_t tpt; int tw, k; for (j = 0; y >= spans[j].y; j++) {} tpt = spans[i]; tw = widths[i]; for (k = i; k != j; k--) { spans[k] = spans[k-1]; widths[k] = widths[k-1]; } spans[j] = tpt; widths[j] = tw; y = spans[i].y; } /* if out of order */ yprev = y; i++; } while (i != numSpans); return; } /* Choose partition element, stick in location 0 */ m = numSpans / 2; if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); y = spans[0].y; /* Partition array */ i = 0; j = numSpans; do { r = &(spans[i]); do { r++; i++; } while (i != numSpans && r->y < y); r = &(spans[j]); do { r--; j--; } while (y < r->y); if (i < j) ExchangeSpans(i, j); } while (i < j); /* Move partition element back to middle */ ExchangeSpans(0, j); /* Recurse */ if (numSpans-j-1 > 1) QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); numSpans = j; } while (numSpans > 1);}#define NextBand() \{ \ clipy1 = pboxBandStart->y1; \ clipy2 = pboxBandStart->y2; \ pboxBandEnd = pboxBandStart + 1; \ while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ pboxBandEnd++; \ } \ for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \}/* Clip a list of scanlines to a region. The caller has allocated the space. FSorted is non-zero if the scanline origins are in ascending order. returns the number of new, clipped scanlines.*/#ifdef XXX_DO_WE_NEED_THISstatic intpixman_region16_clip_spans( pixman_region16_t *prgnDst, pixman_region16_point_t *ppt, int *pwidth, int nspans, pixman_region16_point_t *pptNew, int *pwi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -