1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkQuadTree.h" 9 #include "SkTSort.h" 10 #include <stdio.h> 11 12 static const int kSplitThreshold = 8; 13 14 enum { 15 kTopLeft, 16 kTopRight, 17 kBottomLeft, 18 kBottomRight, 19 }; 20 enum { 21 kTopLeft_Bit = 1 << kTopLeft, 22 kTopRight_Bit = 1 << kTopRight, 23 kBottomLeft_Bit = 1 << kBottomLeft, 24 kBottomRight_Bit = 1 << kBottomRight, 25 }; 26 enum { 27 kMaskLeft = kTopLeft_Bit | kBottomLeft_Bit, 28 kMaskRight = kTopRight_Bit | kBottomRight_Bit, 29 kMaskTop = kTopLeft_Bit | kTopRight_Bit, 30 kMaskBottom = kBottomLeft_Bit | kBottomRight_Bit, 31 }; 32 33 static U8CPU child_intersect(const SkIRect& query, const SkIPoint& split) { 34 // fast quadrant test 35 U8CPU intersect = 0xf; 36 if (query.fRight < split.fX) { 37 intersect &= ~kMaskRight; 38 } else if(query.fLeft >= split.fX) { 39 intersect &= ~kMaskLeft; 40 } 41 if (query.fBottom < split.fY) { 42 intersect &= ~kMaskBottom; 43 } else if(query.fTop >= split.fY) { 44 intersect &= ~kMaskTop; 45 } 46 return intersect; 47 } 48 49 SkQuadTree::SkQuadTree(const SkIRect& bounds) : fRoot(NULL) { 50 SkASSERT((bounds.width() * bounds.height()) > 0); 51 fRootBounds = bounds; 52 } 53 54 SkQuadTree::~SkQuadTree() { 55 } 56 57 void SkQuadTree::insert(Node* node, Entry* entry) { 58 // does it belong in a child? 59 if (NULL != node->fChildren[0]) { 60 switch(child_intersect(entry->fBounds, node->fSplitPoint)) { 61 case kTopLeft_Bit: 62 this->insert(node->fChildren[kTopLeft], entry); 63 return; 64 case kTopRight_Bit: 65 this->insert(node->fChildren[kTopRight], entry); 66 return; 67 case kBottomLeft_Bit: 68 this->insert(node->fChildren[kBottomLeft], entry); 69 return; 70 case kBottomRight_Bit: 71 this->insert(node->fChildren[kBottomRight], entry); 72 return; 73 default: 74 node->fEntries.push(entry); 75 return; 76 } 77 } 78 // No children yet, add to this node 79 node->fEntries.push(entry); 80 // should I split? 81 if (node->fEntries.getCount() > kSplitThreshold) { 82 this->split(node); 83 } 84 } 85 86 void SkQuadTree::split(Node* node) { 87 // Build all the children 88 node->fSplitPoint = SkIPoint::Make(node->fBounds.centerX(), 89 node->fBounds.centerY()); 90 for(int index=0; index<kChildCount; ++index) { 91 node->fChildren[index] = fNodePool.acquire(); 92 } 93 node->fChildren[0]->fBounds = SkIRect::MakeLTRB( 94 node->fBounds.fLeft, node->fBounds.fTop, 95 node->fSplitPoint.fX, node->fSplitPoint.fY); 96 node->fChildren[1]->fBounds = SkIRect::MakeLTRB( 97 node->fSplitPoint.fX, node->fBounds.fTop, 98 node->fBounds.fRight, node->fSplitPoint.fY); 99 node->fChildren[2]->fBounds = SkIRect::MakeLTRB( 100 node->fBounds.fLeft, node->fSplitPoint.fY, 101 node->fSplitPoint.fX, node->fBounds.fBottom); 102 node->fChildren[3]->fBounds = SkIRect::MakeLTRB( 103 node->fSplitPoint.fX, node->fSplitPoint.fY, 104 node->fBounds.fRight, node->fBounds.fBottom); 105 // reinsert all the entries of this node to allow child trickle 106 SkTInternalSList<Entry> entries; 107 entries.pushAll(&node->fEntries); 108 while(!entries.isEmpty()) { 109 this->insert(node, entries.pop()); 110 } 111 } 112 113 void SkQuadTree::search(Node* node, const SkIRect& query, 114 SkTDArray<void*>* results) const { 115 for (Entry* entry = node->fEntries.head(); NULL != entry; 116 entry = entry->getSListNext()) { 117 if (SkIRect::IntersectsNoEmptyCheck(entry->fBounds, query)) { 118 results->push(entry->fData); 119 } 120 } 121 if (NULL == node->fChildren[0]) { 122 return; 123 } 124 U8CPU intersect = child_intersect(query, node->fSplitPoint); 125 for(int index=0; index<kChildCount; ++index) { 126 if (intersect & (1 << index)) { 127 this->search(node->fChildren[index], query, results); 128 } 129 } 130 } 131 132 void SkQuadTree::clear(Node* node) { 133 // first clear the entries of this node 134 fEntryPool.releaseAll(&node->fEntries); 135 // recurse into and clear all child nodes 136 for(int index=0; index<kChildCount; ++index) { 137 Node* child = node->fChildren[index]; 138 node->fChildren[index] = NULL; 139 if (NULL != child) { 140 this->clear(child); 141 fNodePool.release(child); 142 } 143 } 144 } 145 146 int SkQuadTree::getDepth(Node* node) const { 147 int maxDepth = 0; 148 if (NULL != node) { 149 for(int index=0; index<kChildCount; ++index) { 150 maxDepth = SkMax32(maxDepth, getDepth(node->fChildren[index])); 151 } 152 } 153 return maxDepth + 1; 154 } 155 156 void SkQuadTree::insert(void* data, const SkIRect& bounds, bool) { 157 if (bounds.isEmpty()) { 158 SkASSERT(false); 159 return; 160 } 161 Entry* entry = fEntryPool.acquire(); 162 entry->fData = data; 163 entry->fBounds = bounds; 164 if (NULL == fRoot) { 165 fDeferred.push(entry); 166 } else { 167 this->insert(fRoot, entry); 168 } 169 } 170 171 void SkQuadTree::search(const SkIRect& query, SkTDArray<void*>* results) { 172 SkASSERT(NULL != fRoot); 173 SkASSERT(NULL != results); 174 if (SkIRect::Intersects(fRootBounds, query)) { 175 this->search(fRoot, query, results); 176 } 177 } 178 179 void SkQuadTree::clear() { 180 this->flushDeferredInserts(); 181 if (NULL != fRoot) { 182 this->clear(fRoot); 183 fNodePool.release(fRoot); 184 fRoot = NULL; 185 } 186 SkASSERT(fEntryPool.allocated() == fEntryPool.available()); 187 SkASSERT(fNodePool.allocated() == fNodePool.available()); 188 } 189 190 int SkQuadTree::getDepth() const { 191 return this->getDepth(fRoot); 192 } 193 194 void SkQuadTree::rewindInserts() { 195 SkASSERT(fClient); 196 // Currently only supports deferred inserts 197 SkASSERT(NULL == fRoot); 198 SkTInternalSList<Entry> entries; 199 entries.pushAll(&fDeferred); 200 while(!entries.isEmpty()) { 201 Entry* entry = entries.pop(); 202 if (fClient->shouldRewind(entry->fData)) { 203 entry->fData = NULL; 204 fEntryPool.release(entry); 205 } else { 206 fDeferred.push(entry); 207 } 208 } 209 } 210 211 void SkQuadTree::flushDeferredInserts() { 212 if (NULL == fRoot) { 213 fRoot = fNodePool.acquire(); 214 fRoot->fBounds = fRootBounds; 215 } 216 while(!fDeferred.isEmpty()) { 217 this->insert(fRoot, fDeferred.pop()); 218 } 219 } 220