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; }
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; }
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 TBOOL region_subrect(struct RectPool *pool, struct Region *region, RECTINT s[]) { struct RectList r1; struct TNode *next, *node; TBOOL success = TTRUE; region_initrectlist(&r1); 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) { region_freerects(pool, ®ion->rg_Rects); region_relinkrects(®ion->rg_Rects, &r1); } else region_freerects(pool, &r1); return success; }
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; }
TLIBAPI void region_destroy(struct RectPool *pool, struct Region *region) { region_freerects(pool, ®ion->rg_Rects); TExecFree(pool->p_ExecBase, region); }
TLIBAPI void region_free(struct RectPool *pool, struct Region *region) { region_freerects(pool, ®ion->rg_Rects); }