2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkQuadTree.h"
12 static const int kSplitThreshold = 8;
21 kTopLeft_Bit = 1 << kTopLeft,
22 kTopRight_Bit = 1 << kTopRight,
23 kBottomLeft_Bit = 1 << kBottomLeft,
24 kBottomRight_Bit = 1 << kBottomRight,
27 kMaskLeft = kTopLeft_Bit | kBottomLeft_Bit,
28 kMaskRight = kTopRight_Bit | kBottomRight_Bit,
29 kMaskTop = kTopLeft_Bit | kTopRight_Bit,
30 kMaskBottom = kBottomLeft_Bit | kBottomRight_Bit,
33 static U8CPU child_intersect(const SkIRect& query, const SkIPoint& split) {
35 U8CPU intersect = 0xf;
36 if (query.fRight < split.fX) {
37 intersect &= ~kMaskRight;
38 } else if(query.fLeft >= split.fX) {
39 intersect &= ~kMaskLeft;
41 if (query.fBottom < split.fY) {
42 intersect &= ~kMaskBottom;
43 } else if(query.fTop >= split.fY) {
44 intersect &= ~kMaskTop;
49 SkQuadTree::SkQuadTree(const SkIRect& bounds)
51 SkASSERT((bounds.width() * bounds.height()) > 0);
55 SkQuadTree::~SkQuadTree() {
58 void SkQuadTree::insert(Node* node, Entry* entry) {
59 // does it belong in a child?
60 if (NULL != node->fChildren[0]) {
61 switch(child_intersect(entry->fBounds, node->fSplitPoint)) {
63 this->insert(node->fChildren[kTopLeft], entry);
66 this->insert(node->fChildren[kTopRight], entry);
69 this->insert(node->fChildren[kBottomLeft], entry);
71 case kBottomRight_Bit:
72 this->insert(node->fChildren[kBottomRight], entry);
75 node->fEntries.push(entry);
79 // No children yet, add to this node
80 node->fEntries.push(entry);
82 if (node->fEntries.getCount() > kSplitThreshold) {
87 void SkQuadTree::split(Node* node) {
88 // Build all the children
89 node->fSplitPoint = SkIPoint::Make(node->fBounds.centerX(),
90 node->fBounds.centerY());
91 for(int index=0; index<kChildCount; ++index) {
92 node->fChildren[index] = fNodePool.acquire();
94 node->fChildren[0]->fBounds = SkIRect::MakeLTRB(
95 node->fBounds.fLeft, node->fBounds.fTop,
96 node->fSplitPoint.fX, node->fSplitPoint.fY);
97 node->fChildren[1]->fBounds = SkIRect::MakeLTRB(
98 node->fSplitPoint.fX, node->fBounds.fTop,
99 node->fBounds.fRight, node->fSplitPoint.fY);
100 node->fChildren[2]->fBounds = SkIRect::MakeLTRB(
101 node->fBounds.fLeft, node->fSplitPoint.fY,
102 node->fSplitPoint.fX, node->fBounds.fBottom);
103 node->fChildren[3]->fBounds = SkIRect::MakeLTRB(
104 node->fSplitPoint.fX, node->fSplitPoint.fY,
105 node->fBounds.fRight, node->fBounds.fBottom);
106 // reinsert all the entries of this node to allow child trickle
107 SkTInternalSList<Entry> entries;
108 entries.pushAll(&node->fEntries);
109 while(!entries.isEmpty()) {
110 this->insert(node, entries.pop());
114 void SkQuadTree::search(Node* node, const SkIRect& query,
115 SkTDArray<void*>* results) const {
116 for (Entry* entry = node->fEntries.head(); NULL != entry;
117 entry = entry->getSListNext()) {
118 if (SkIRect::IntersectsNoEmptyCheck(entry->fBounds, query)) {
119 results->push(entry->fData);
122 if (NULL == node->fChildren[0]) {
125 U8CPU intersect = child_intersect(query, node->fSplitPoint);
126 for(int index=0; index<kChildCount; ++index) {
127 if (intersect & (1 << index)) {
128 this->search(node->fChildren[index], query, results);
133 void SkQuadTree::clear(Node* node) {
134 // first clear the entries of this node
135 fEntryPool.releaseAll(&node->fEntries);
136 // recurse into and clear all child nodes
137 for(int index=0; index<kChildCount; ++index) {
138 Node* child = node->fChildren[index];
139 node->fChildren[index] = NULL;
142 fNodePool.release(child);
147 int SkQuadTree::getDepth(Node* node) const {
150 for(int index=0; index<kChildCount; ++index) {
151 maxDepth = SkMax32(maxDepth, getDepth(node->fChildren[index]));
157 void SkQuadTree::insert(void* data, const SkIRect& bounds, bool) {
158 if (bounds.isEmpty()) {
162 Entry* entry = fEntryPool.acquire();
164 entry->fBounds = bounds;
166 fDeferred.push(entry);
168 this->insert(fRoot, entry);
172 void SkQuadTree::search(const SkIRect& query, SkTDArray<void*>* results) {
173 SkASSERT(NULL != fRoot);
174 SkASSERT(NULL != results);
175 if (SkIRect::Intersects(fRootBounds, query)) {
176 this->search(fRoot, query, results);
180 void SkQuadTree::clear() {
183 fNodePool.release(fRoot);
188 int SkQuadTree::getDepth() const {
189 return this->getDepth(fRoot);
192 void SkQuadTree::rewindInserts() {
194 // Currently only supports deferred inserts
195 SkASSERT(NULL == fRoot);
196 SkTInternalSList<Entry> entries;
197 entries.pushAll(&fDeferred);
198 while(!entries.isEmpty()) {
199 Entry* entry = entries.pop();
200 if (fClient->shouldRewind(entry->fData)) {
202 fEntryPool.release(entry);
204 fDeferred.push(entry);
209 void SkQuadTree::flushDeferredInserts() {
211 fRoot = fNodePool.acquire();
212 fRoot->fBounds = fRootBounds;
214 while(!fDeferred.isEmpty()) {
215 this->insert(fRoot, fDeferred.pop());