TLIBAPI TBOOL region_orrectlist(struct RectPool *pool, struct RectList *list, TINT s[4], TBOOL opportunistic) { if (list->rl_NumNodes > 0) { TINT x0 = s[0]; TINT y0 = s[1]; TINT x1 = s[2]; TINT y1 = s[3]; TUINT64 area = 0; struct TNode *next, *node = list->rl_List.tlh_Head; for (; (next = node->tln_Succ); node = next) { struct RectNode *rn = (struct RectNode *) node; TINT *r = rn->rn_Rect; if (s[0] >= r[0] && s[1] >= r[1] && s[2] <= r[2] && s[3] <= r[3]) return TTRUE; if (!opportunistic) continue; area += (r[2] - r[0] + 1) * (r[3] - r[1] + 1); x0 = TMIN(x0, r[0]); y0 = TMIN(y0, r[1]); x1 = TMAX(x1, r[2]); y1 = TMAX(y1, r[3]); } if (opportunistic) { TUINT64 area2 = (x1 - x0 + 1) * (y1 - y0 + 1); if (area2 < OPPORTUNISTIC_MERGE_THRESHOLD || (area * 256 / area2) > OPPORTUNISTIC_MERGE_RATIO) { /* merge list into a single rectangle */ TDBPRINTF(TDB_TRACE,("merge %d rects\n", list->rl_NumNodes + 1)); region_freerects(pool, list); assert(list->rl_NumNodes == 0); return region_insertrect(pool, list, x0, y0, x1, y1); } } } struct RectList temp; region_initrectlist(&temp); if (region_cutrectlist(pool, list, &temp, s)) { if (region_insertrect(pool, &temp, s[0], s[1], s[2], s[3])) { region_freerects(pool, list); region_relinkrects(list, &temp); return TTRUE; } } region_freerects(pool, &temp); return TFALSE; }
TLIBAPI TBOOL region_xorrect(struct RectPool *pool, struct Region *region, RECTINT s[]) { struct TNode *next, *node; TBOOL success; struct RectList r1, r2; region_initrectlist(&r1); region_initrectlist(&r2); success = region_insertrect(pool, &r2, s[0], s[1], s[2], s[3]); node = region->rg_Rects.rl_List.tlh_Head; for (; success && (next = node->tln_Succ); node = next) { struct TNode *next2, *node2; struct RectNode *rn = (struct RectNode *) node; struct RectList temp; region_initrectlist(&temp); success = region_cutrect(pool, &temp, rn->rn_Rect, s); node2 = temp.rl_List.tlh_Head; for (; success && (next2 = node2->tln_Succ); node2 = next2) { struct RectNode *rn2 = (struct RectNode *) node2; success = region_insertrect(pool, &r1, rn2->rn_Rect[0], rn2->rn_Rect[1], rn2->rn_Rect[2], rn2->rn_Rect[3]); } region_freerects(pool, &temp); if (success) { success = region_cutrectlist(pool, &r2, &temp, rn->rn_Rect); region_freerects(pool, &r2); region_relinkrects(&r2, &temp); } } if (success) { region_freerects(pool, ®ion->rg_Rects); region_relinkrects(®ion->rg_Rects, &r1); region_orregion(region, &r2, TFALSE); region_freerects(pool, &r2); } else { region_freerects(pool, &r1); region_freerects(pool, &r2); } return success; }
static TBOOL region_andrect_internal(struct RectList *temp, struct Region *region, TINT s[], TINT dx, TINT dy) { struct RectPool *pool = region->rg_Pool; struct TNode *next, *node = region->rg_Rects.rl_List.tlh_Head; TBOOL success = TTRUE; TINT s0 = s[0] + dx; TINT s1 = s[1] + dy; TINT s2 = s[2] + dx; TINT s3 = s[3] + dy; for (; success && (next = node->tln_Succ); node = next) { struct RectNode *dr = (struct RectNode *) node; TINT x0 = dr->rn_Rect[0]; TINT y0 = dr->rn_Rect[1]; TINT x1 = dr->rn_Rect[2]; TINT y1 = dr->rn_Rect[3]; if (OVERLAP(x0, y0, x1, y1, s0, s1, s2, s3)) { success = region_insertrect(pool, temp, TMAX(x0, s0), TMAX(y0, s1), TMIN(x1, s2), TMIN(y1, s3)); } } if (!success) region_freerects(pool, temp); return success; }
static TBOOL region_cutrectlist(struct RectPool *pool, struct RectList *inlist, struct RectList *outlist, const RECTINT s[4]) { TBOOL success = TTRUE; struct TNode *next, *node = inlist->rl_List.tlh_Head; for (; success && (next = node->tln_Succ); node = next) { struct RectNode *rn = (struct RectNode *) node; struct RectList temp; region_initrectlist(&temp); success = region_cutrect(pool, &temp, rn->rn_Rect, s); if (success) { struct TNode *next2, *node2 = temp.rl_List.tlh_Head; for (; success && (next2 = node2->tln_Succ); node2 = next2) { struct RectNode *rn2 = (struct RectNode *) node2; success = region_insertrect(pool, outlist, rn2->rn_Rect[0], rn2->rn_Rect[1], rn2->rn_Rect[2], rn2->rn_Rect[3]); /* note that if unsuccessful, outlist is unusable as well */ } } region_freerects(pool, &temp); } return success; }
static TBOOL region_cutrect(struct RectPool *pool, struct RectList *list, const RECTINT d[4], const RECTINT s[4]) { TINT d0 = d[0]; TINT d1 = d[1]; TINT d2 = d[2]; TINT d3 = d[3]; if (!OVERLAPRECT(d, s)) return region_insertrect(pool, list, d[0], d[1], d[2], d[3]); for (;;) { if (d0 < s[0]) { if (!region_insertrect(pool, list, d0, d1, s[0] - 1, d3)) break; d0 = s[0]; } if (d1 < s[1]) { if (!region_insertrect(pool, list, d0, d1, d2, s[1] - 1)) break; d1 = s[1]; } if (d2 > s[2]) { if (!region_insertrect(pool, list, s[2] + 1, d1, d2, d3)) break; d2 = s[2]; } if (d3 > s[3]) { if (!region_insertrect(pool, list, d0, s[3] + 1, d2, d3)) break; } return TTRUE; } return TFALSE; }
TLIBAPI TBOOL region_init(struct RectPool *pool, struct Region *region, TINT *s) { region->rg_Pool = pool; region_initrectlist(®ion->rg_Rects); if (s && !region_insertrect(pool, ®ion->rg_Rects, s[0], s[1], s[2], s[3])) return TFALSE; return TTRUE; }
TLIBAPI struct Region *region_new(struct RectPool *pool, TINT *s) { struct TExecBase *TExecBase = pool->p_ExecBase; struct Region *region = TAlloc(TNULL, sizeof(struct Region)); if (region) { region->rg_Pool = pool; region_initrectlist(®ion->rg_Rects); if (s && !region_insertrect(pool, ®ion->rg_Rects, s[0], s[1], s[2], s[3])) { TFree(region); region = TNULL; } } return region; }