Beispiel #1
0
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;
}
Beispiel #2
0
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;
    }
}
Beispiel #3
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);
}
Beispiel #4
0
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);
}