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_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; }
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_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 TBOOL region_andrect(struct RectPool *pool, struct Region *region, TINT s[], TINT dx, TINT dy) { struct RectList temp; region_initrectlist(&temp); if (region_andrect_internal(&temp, region, s, dx, dy)) { region_freerects(pool, ®ion->rg_Rects); region_relinkrects(®ion->rg_Rects, &temp); return TTRUE; } return TFALSE; }
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; }
TLIBAPI TBOOL region_andregion(struct RectPool *pool, struct Region *dregion, struct Region *sregion) { struct TNode *next, *node = sregion->rg_Rects.rl_List.tlh_Head; TBOOL success = TTRUE; struct RectList temp; region_initrectlist(&temp); for (; success && (next = node->tln_Succ); node = next) { struct RectNode *sr = (struct RectNode *) node; success = region_andrect_internal(&temp, dregion, sr->rn_Rect, 0, 0); } if (success) { region_freerects(pool, &dregion->rg_Rects); region_relinkrects(&dregion->rg_Rects, &temp); } /* note: if unsucessful, dregion is of no use anymore */ return success; }
static void region_relinkrects(struct RectList *d, struct RectList *s) { region_relinklist(&d->rl_List, &s->rl_List); d->rl_NumNodes += s->rl_NumNodes; region_initrectlist(s); }
TLIBAPI void region_initpool(struct RectPool *pool, TAPTR TExecBase) { region_initrectlist(&pool->p_Rects); pool->p_ExecBase = TExecBase; }