2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 static inline uint32_t get_area(const SkIRect& rect);
12 static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2);
13 static inline uint32_t get_margin(const SkIRect& rect);
14 static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2);
15 static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out);
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
19 SkRTree* SkRTree::Create(int minChildren, int maxChildren, SkScalar aspectRatio,
20 bool sortWhenBulkLoading) {
21 if (minChildren < maxChildren && (maxChildren + 1) / 2 >= minChildren &&
22 minChildren > 0 && maxChildren < static_cast<int>(SK_MaxU16)) {
23 return new SkRTree(minChildren, maxChildren, aspectRatio, sortWhenBulkLoading);
28 SkRTree::SkRTree(int minChildren, int maxChildren, SkScalar aspectRatio,
29 bool sortWhenBulkLoading)
30 : fMinChildren(minChildren)
31 , fMaxChildren(maxChildren)
32 , fNodeSize(sizeof(Node) + sizeof(Branch) * maxChildren)
34 , fNodes(fNodeSize * 256)
35 , fAspectRatio(aspectRatio)
36 , fSortWhenBulkLoading(sortWhenBulkLoading) {
37 SkASSERT(minChildren < maxChildren && minChildren > 0 && maxChildren <
38 static_cast<int>(SK_MaxU16));
39 SkASSERT((maxChildren + 1) / 2 >= minChildren);
47 void SkRTree::insert(void* data, const SkRect& fbounds, bool defer) {
49 if (fbounds.isLargest()) {
52 fbounds.roundOut(&bounds);
56 if (bounds.isEmpty()) {
61 newBranch.fBounds = bounds;
62 newBranch.fChild.data = data;
63 if (this->isEmpty()) {
64 // since a bulk-load into an existing tree is as of yet unimplemented (and arguably not
65 // of vital importance right now), we only batch up inserts if the tree is empty.
67 fDeferredInserts.push(newBranch);
70 fRoot.fChild.subtree = allocateNode(0);
71 fRoot.fChild.subtree->fNumChildren = 0;
75 Branch* newSibling = insert(fRoot.fChild.subtree, &newBranch);
76 fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
79 Node* oldRoot = fRoot.fChild.subtree;
80 Node* newRoot = this->allocateNode(oldRoot->fLevel + 1);
81 newRoot->fNumChildren = 2;
82 *newRoot->child(0) = fRoot;
83 *newRoot->child(1) = *newSibling;
84 fRoot.fChild.subtree = newRoot;
85 fRoot.fBounds = this->computeBounds(fRoot.fChild.subtree);
92 void SkRTree::flushDeferredInserts() {
94 if (this->isEmpty() && fDeferredInserts.count() > 0) {
95 fCount = fDeferredInserts.count();
97 fRoot.fChild.subtree = allocateNode(0);
98 fRoot.fChild.subtree->fNumChildren = 0;
99 this->insert(fRoot.fChild.subtree, &fDeferredInserts[0]);
100 fRoot.fBounds = fDeferredInserts[0].fBounds;
102 fRoot = this->bulkLoad(&fDeferredInserts);
105 // TODO: some algorithm for bulk loading into an already populated tree
106 SkASSERT(0 == fDeferredInserts.count());
108 fDeferredInserts.rewind();
112 void SkRTree::search(const SkRect& fquery, SkTDArray<void*>* results) const {
114 fquery.roundOut(&query);
116 SkASSERT(0 == fDeferredInserts.count()); // If this fails, you should have flushed.
117 if (!this->isEmpty() && SkIRect::IntersectsNoEmptyCheck(fRoot.fBounds, query)) {
118 this->search(fRoot.fChild.subtree, query, results);
123 void SkRTree::clear() {
126 fDeferredInserts.rewind();
131 SkRTree::Node* SkRTree::allocateNode(uint16_t level) {
132 Node* out = static_cast<Node*>(fNodes.allocThrow(fNodeSize));
133 out->fNumChildren = 0;
138 SkRTree::Branch* SkRTree::insert(Node* root, Branch* branch, uint16_t level) {
139 Branch* toInsert = branch;
140 if (root->fLevel != level) {
141 int childIndex = this->chooseSubtree(root, branch);
142 toInsert = this->insert(root->child(childIndex)->fChild.subtree, branch, level);
143 root->child(childIndex)->fBounds = this->computeBounds(
144 root->child(childIndex)->fChild.subtree);
147 if (root->fNumChildren == fMaxChildren) {
148 // handle overflow by splitting. TODO: opportunistic reinsertion
150 // decide on a distribution to divide with
151 Node* newSibling = this->allocateNode(root->fLevel);
152 Branch* toDivide = SkNEW_ARRAY(Branch, fMaxChildren + 1);
153 for (int i = 0; i < fMaxChildren; ++i) {
154 toDivide[i] = *root->child(i);
156 toDivide[fMaxChildren] = *toInsert;
157 int splitIndex = this->distributeChildren(toDivide);
159 // divide up the branches
160 root->fNumChildren = splitIndex;
161 newSibling->fNumChildren = fMaxChildren + 1 - splitIndex;
162 for (int i = 0; i < splitIndex; ++i) {
163 *root->child(i) = toDivide[i];
165 for (int i = splitIndex; i < fMaxChildren + 1; ++i) {
166 *newSibling->child(i - splitIndex) = toDivide[i];
168 SkDELETE_ARRAY(toDivide);
170 // pass the new sibling branch up to the parent
171 branch->fChild.subtree = newSibling;
172 branch->fBounds = this->computeBounds(newSibling);
175 *root->child(root->fNumChildren) = *toInsert;
176 ++root->fNumChildren;
183 int SkRTree::chooseSubtree(Node* root, Branch* branch) {
184 SkASSERT(!root->isLeaf());
185 if (1 < root->fLevel) {
186 // root's child pointers do not point to leaves, so minimize area increase
187 int32_t minAreaIncrease = SK_MaxS32;
188 int32_t minArea = SK_MaxS32;
189 int32_t bestSubtree = -1;
190 for (int i = 0; i < root->fNumChildren; ++i) {
191 const SkIRect& subtreeBounds = root->child(i)->fBounds;
192 int32_t areaIncrease = get_area_increase(subtreeBounds, branch->fBounds);
193 // break ties in favor of subtree with smallest area
194 if (areaIncrease < minAreaIncrease || (areaIncrease == minAreaIncrease &&
195 static_cast<int32_t>(get_area(subtreeBounds)) < minArea)) {
196 minAreaIncrease = areaIncrease;
197 minArea = get_area(subtreeBounds);
201 SkASSERT(-1 != bestSubtree);
203 } else if (1 == root->fLevel) {
204 // root's child pointers do point to leaves, so minimize overlap increase
205 int32_t minOverlapIncrease = SK_MaxS32;
206 int32_t minAreaIncrease = SK_MaxS32;
207 int32_t bestSubtree = -1;
208 for (int32_t i = 0; i < root->fNumChildren; ++i) {
209 const SkIRect& subtreeBounds = root->child(i)->fBounds;
210 SkIRect expandedBounds = subtreeBounds;
211 join_no_empty_check(branch->fBounds, &expandedBounds);
213 for (int32_t j = 0; j < root->fNumChildren; ++j) {
214 if (j == i) continue;
215 // Note: this would be more correct if we subtracted the original pre-expanded
216 // overlap, but computing overlaps is expensive and omitting it doesn't seem to
217 // hurt query performance. See get_overlap_increase()
218 overlap += get_overlap(expandedBounds, root->child(j)->fBounds);
220 // break ties with lowest area increase
221 if (overlap < minOverlapIncrease || (overlap == minOverlapIncrease &&
222 static_cast<int32_t>(get_area_increase(branch->fBounds, subtreeBounds)) <
224 minOverlapIncrease = overlap;
225 minAreaIncrease = get_area_increase(branch->fBounds, subtreeBounds);
236 SkIRect SkRTree::computeBounds(Node* n) {
237 SkIRect r = n->child(0)->fBounds;
238 for (int i = 1; i < n->fNumChildren; ++i) {
239 join_no_empty_check(n->child(i)->fBounds, &r);
244 int SkRTree::distributeChildren(Branch* children) {
245 // We have two sides to sort by on each of two axes:
246 const static SortSide sorts[2][2] = {
247 {&SkIRect::fLeft, &SkIRect::fRight},
248 {&SkIRect::fTop, &SkIRect::fBottom}
251 // We want to choose an axis to split on, then a distribution along that axis; we'll need
252 // three pieces of info: the split axis, the side to sort by on that axis, and the index
253 // to split the sorted array on.
254 int32_t sortSide = -1;
257 int32_t bestS = SK_MaxS32;
259 // Evaluate each axis, we want the min summed margin-value (s) over all distributions
260 for (int i = 0; i < 2; ++i) {
261 int32_t minOverlap = SK_MaxS32;
262 int32_t minArea = SK_MaxS32;
263 int32_t axisBestK = 0;
264 int32_t axisBestSide = 0;
267 // Evaluate each sort
268 for (int j = 0; j < 2; ++j) {
269 SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[i][j]));
271 // Evaluate each split index
272 for (int32_t k = 1; k <= fMaxChildren - 2 * fMinChildren + 2; ++k) {
273 SkIRect r1 = children[0].fBounds;
274 SkIRect r2 = children[fMinChildren + k - 1].fBounds;
275 for (int32_t l = 1; l < fMinChildren - 1 + k; ++l) {
276 join_no_empty_check(children[l].fBounds, &r1);
278 for (int32_t l = fMinChildren + k; l < fMaxChildren + 1; ++l) {
279 join_no_empty_check(children[l].fBounds, &r2);
282 int32_t area = get_area(r1) + get_area(r2);
283 int32_t overlap = get_overlap(r1, r2);
284 s += get_margin(r1) + get_margin(r2);
286 if (overlap < minOverlap || (overlap == minOverlap && area < minArea)) {
287 minOverlap = overlap;
298 sortSide = axisBestSide;
303 // replicate the sort of the winning distribution, (we can skip this if the last
304 // sort ended up being best)
305 if (!(axis == 1 && sortSide == 1)) {
306 SkTQSort(children, children + fMaxChildren, RectLessThan(sorts[axis][sortSide]));
309 return fMinChildren - 1 + k;
312 void SkRTree::search(Node* root, const SkIRect query, SkTDArray<void*>* results) const {
313 for (int i = 0; i < root->fNumChildren; ++i) {
314 if (SkIRect::IntersectsNoEmptyCheck(root->child(i)->fBounds, query)) {
315 if (root->isLeaf()) {
316 results->push(root->child(i)->fChild.data);
318 this->search(root->child(i)->fChild.subtree, query, results);
324 SkRTree::Branch SkRTree::bulkLoad(SkTDArray<Branch>* branches, int level) {
325 if (branches->count() == 1) {
326 // Only one branch: it will be the root
327 Branch out = (*branches)[0];
331 // We sort the whole list by y coordinates, if we are told to do so.
333 // We expect Webkit / Blink to give us a reasonable x,y order.
334 // Avoiding this call resulted in a 17% win for recording with
335 // negligible difference in playback speed.
336 if (fSortWhenBulkLoading) {
337 SkTQSort(branches->begin(), branches->end() - 1, RectLessY());
340 int numBranches = branches->count() / fMaxChildren;
341 int remainder = branches->count() % fMaxChildren;
344 if (0 != remainder) {
346 // If the remainder isn't enough to fill a node, we'll need to add fewer nodes to
347 // some other branches to make up for it
348 if (remainder >= fMinChildren) {
351 remainder = fMinChildren - remainder;
355 int numStrips = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(numBranches) *
356 SkScalarInvert(fAspectRatio)));
357 int numTiles = SkScalarCeilToInt(SkIntToScalar(numBranches) /
358 SkIntToScalar(numStrips));
359 int currentBranch = 0;
361 for (int i = 0; i < numStrips; ++i) {
362 // Once again, if we are told to do so, we sort by x.
363 if (fSortWhenBulkLoading) {
364 int begin = currentBranch;
365 int end = currentBranch + numTiles * fMaxChildren - SkMin32(remainder,
366 (fMaxChildren - fMinChildren) * numTiles);
367 if (end > branches->count()) {
368 end = branches->count();
371 // Now we sort horizontal strips of rectangles by their x coords
372 SkTQSort(branches->begin() + begin, branches->begin() + end - 1, RectLessX());
375 for (int j = 0; j < numTiles && currentBranch < branches->count(); ++j) {
376 int incrementBy = fMaxChildren;
377 if (remainder != 0) {
378 // if need be, omit some nodes to make up for remainder
379 if (remainder <= fMaxChildren - fMinChildren) {
380 incrementBy -= remainder;
383 incrementBy = fMinChildren;
384 remainder -= fMaxChildren - fMinChildren;
387 Node* n = allocateNode(level);
389 *n->child(0) = (*branches)[currentBranch];
391 b.fBounds = (*branches)[currentBranch].fBounds;
392 b.fChild.subtree = n;
394 for (int k = 1; k < incrementBy && currentBranch < branches->count(); ++k) {
395 b.fBounds.join((*branches)[currentBranch].fBounds);
396 *n->child(k) = (*branches)[currentBranch];
400 (*branches)[newBranches] = b;
404 branches->setCount(newBranches);
405 return this->bulkLoad(branches, level + 1);
409 void SkRTree::validate() const {
411 if (this->isEmpty()) {
414 SkASSERT(fCount == this->validateSubtree(fRoot.fChild.subtree, fRoot.fBounds, true));
418 int SkRTree::validateSubtree(Node* root, SkIRect bounds, bool isRoot) const {
419 // make sure the pointer is pointing to a valid place
420 SkASSERT(fNodes.contains(static_cast<void*>(root)));
423 // If the root of this subtree is the overall root, we have looser standards:
424 if (root->isLeaf()) {
425 SkASSERT(root->fNumChildren >= 1 && root->fNumChildren <= fMaxChildren);
427 SkASSERT(root->fNumChildren >= 2 && root->fNumChildren <= fMaxChildren);
430 SkASSERT(root->fNumChildren >= fMinChildren && root->fNumChildren <= fMaxChildren);
433 for (int i = 0; i < root->fNumChildren; ++i) {
434 SkASSERT(bounds.contains(root->child(i)->fBounds));
437 if (root->isLeaf()) {
438 SkASSERT(0 == root->fLevel);
439 return root->fNumChildren;
442 for (int i = 0; i < root->fNumChildren; ++i) {
443 SkASSERT(root->child(i)->fChild.subtree->fLevel == root->fLevel - 1);
444 childCount += this->validateSubtree(root->child(i)->fChild.subtree,
445 root->child(i)->fBounds);
451 void SkRTree::rewindInserts() {
452 SkASSERT(this->isEmpty()); // Currently only supports deferred inserts
453 while (!fDeferredInserts.isEmpty() &&
454 fClient->shouldRewind(fDeferredInserts.top().fChild.data)) {
455 fDeferredInserts.pop();
459 ///////////////////////////////////////////////////////////////////////////////////////////////////
461 static inline uint32_t get_area(const SkIRect& rect) {
462 return rect.width() * rect.height();
465 static inline uint32_t get_overlap(const SkIRect& rect1, const SkIRect& rect2) {
466 // I suspect there's a more efficient way of computing this...
467 return SkMax32(0, SkMin32(rect1.fRight, rect2.fRight) - SkMax32(rect1.fLeft, rect2.fLeft)) *
468 SkMax32(0, SkMin32(rect1.fBottom, rect2.fBottom) - SkMax32(rect1.fTop, rect2.fTop));
471 // Get the margin (aka perimeter)
472 static inline uint32_t get_margin(const SkIRect& rect) {
473 return 2 * (rect.width() + rect.height());
476 static inline uint32_t get_area_increase(const SkIRect& rect1, SkIRect rect2) {
477 join_no_empty_check(rect1, &rect2);
478 return get_area(rect2) - get_area(rect1);
481 // Expand 'out' to include 'joinWith'
482 static inline void join_no_empty_check(const SkIRect& joinWith, SkIRect* out) {
483 // since we check for empty bounds on insert, we know we'll never have empty rects
484 // and we can save the empty check that SkIRect::join requires
485 if (joinWith.fLeft < out->fLeft) { out->fLeft = joinWith.fLeft; }
486 if (joinWith.fTop < out->fTop) { out->fTop = joinWith.fTop; }
487 if (joinWith.fRight > out->fRight) { out->fRight = joinWith.fRight; }
488 if (joinWith.fBottom > out->fBottom) { out->fBottom = joinWith.fBottom; }