Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: src/core/SkQuadTree.cpp

Issue 500373005: Remove SkQuadTree. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkQuadTree.h ('k') | tests/BBoxHierarchyTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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) const {
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 }
OLDNEW
« no previous file with comments | « src/core/SkQuadTree.h ('k') | tests/BBoxHierarchyTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698