SkIRect SkRTree::computeBounds(Node* n) { SkIRect r = n->child(0)->fBounds; for (int i = 1; i < n->fNumChildren; ++i) { join_no_empty_check(n->child(i)->fBounds, &r); } return r; }
int SkRTree::chooseSubtree(Node* root, Branch* branch) { SkASSERT(!root->isLeaf()); if (1 < root->fLevel) { // root's child pointers do not point to leaves, so minimize area increase int32_t minAreaIncrease = SK_MaxS32; int32_t minArea = SK_MaxS32; int32_t bestSubtree = -1; for (int i = 0; i < root->fNumChildren; ++i) { const SkIRect& subtreeBounds = root->child(i)->fBounds; int32_t areaIncrease = get_area_increase(subtreeBounds, branch->fBounds); // break ties in favor of subtree with smallest area if (areaIncrease < minAreaIncrease || (areaIncrease == minAreaIncrease && static_cast<int32_t>(get_area(subtreeBounds)) < minArea)) { minAreaIncrease = areaIncrease; minArea = get_area(subtreeBounds); bestSubtree = i; } } SkASSERT(-1 != bestSubtree); return bestSubtree; } else if (1 == root->fLevel) { // root's child pointers do point to leaves, so minimize overlap increase int32_t minOverlapIncrease = SK_MaxS32; int32_t minAreaIncrease = SK_MaxS32; int32_t bestSubtree = -1; for (int32_t i = 0; i < root->fNumChildren; ++i) { const SkIRect& subtreeBounds = root->child(i)->fBounds; SkIRect expandedBounds = subtreeBounds; join_no_empty_check(branch->fBounds, &expandedBounds); int32_t overlap = 0; for (int32_t j = 0; j < root->fNumChildren; ++j) { if (j == i) continue; // Note: this would be more correct if we subtracted the original pre-expanded // overlap, but computing overlaps is expensive and omitting it doesn't seem to // hurt query performance. See get_overlap_increase() overlap += get_overlap(expandedBounds, root->child(j)->fBounds); } // break ties with lowest area increase if (overlap < minOverlapIncrease || (overlap == minOverlapIncrease && static_cast<int32_t>(get_area_increase(branch->fBounds, subtreeBounds)) < minAreaIncrease)) { minOverlapIncrease = overlap; minAreaIncrease = get_area_increase(branch->fBounds, subtreeBounds); bestSubtree = i; } } return bestSubtree; } else { SkASSERT(false); return 0; } }
static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2) { join_no_empty_check(rect1, &rect2); return get_area(rect2) - get_area(rect1); }
int SkRTree::distributeChildren(Branch* children) { // We have two sides to sort by on each of two axes: const static SortSide sorts[2][2] = { {&SkIRect::fLeft, &SkIRect::fRight}, {&SkIRect::fTop, &SkIRect::fBottom} }; // We want to choose an axis to split on, then a distribution along that axis; we'll need // three pieces of info: the split axis, the side to sort by on that axis, and the index // to split the sorted array on. int32_t sortSide = -1; int32_t k = -1; int32_t axis = -1; int32_t bestS = SK_MaxS32; // Evaluate each axis, we want the min summed margin-value (s) over all distributions for (int i = 0; i < 2; ++i) { int32_t minOverlap = SK_MaxS32; int32_t minArea = SK_MaxS32; int32_t axisBestK = 0; int32_t axisBestSide = 0; int32_t s = 0; // Evaluate each sort for (int j = 0; j < 2; ++j) { SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[i][j])); // Evaluate each split index for (int32_t k = 1; k <= fMaxChildren - 2 * fMinChildren + 2; ++k) { SkIRect r1 = children[0].fBounds; SkIRect r2 = children[fMinChildren + k - 1].fBounds; for (int32_t l = 1; l < fMinChildren - 1 + k; ++l) { join_no_empty_check(children[l].fBounds, &r1); } for (int32_t l = fMinChildren + k; l < fMaxChildren + 1; ++l) { join_no_empty_check(children[l].fBounds, &r2); } int32_t area = get_area(r1) + get_area(r2); int32_t overlap = get_overlap(r1, r2); s += get_margin(r1) + get_margin(r2); if (overlap < minOverlap || (overlap == minOverlap && area < minArea)) { minOverlap = overlap; minArea = area; axisBestSide = j; axisBestK = k; } } } if (s < bestS) { bestS = s; axis = i; sortSide = axisBestSide; k = axisBestK; } } // replicate the sort of the winning distribution, (we can skip this if the last // sort ended up being best) if (!(axis == 1 && sortSide == 1)) { SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[axis][sortSide])); } return fMinChildren - 1 + k; }
static inline uint32_t get_overlap_increase(const SkIRect& rect1, const SkIRect& rect2, SkIRect expandBy) { join_no_empty_check(rect1, &expandBy); return get_overlap(expandBy, rect2) - get_overlap(rect1, rect2); }