OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkQuadTree_DEFINED | 8 #ifndef SkQuadTree_DEFINED |
9 #define SkQuadTree_DEFINED | 9 #define SkQuadTree_DEFINED |
10 | 10 |
11 #include "SkRect.h" | 11 #include "SkRect.h" |
12 #include "SkTDArray.h" | 12 #include "SkTDArray.h" |
13 #include "SkBBoxHierarchy.h" | 13 #include "SkBBoxHierarchy.h" |
14 | 14 |
robertphillips
2014/03/05 13:08:53
Might be worth mirroring SkTInternalList.h
iancottrell
2014/03/07 15:06:34
Done.
| |
15 /** | 15 /** |
16 * An QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles | 16 * An implementation of an intrusive singly linked list. |
17 * The type T must have a field fNext that is visible to the list. | |
18 * The list does not maintain ownership of any of its elements, or ever delete | |
19 * them. | |
20 * The fNext must be null on any object handed to push, and will be NULL when | |
21 * returned from pop. It is free to use while the object is not in the a list. | |
22 */ | |
23 template<typename T> class SkSList { | |
24 public: | |
25 SkSList() : fHead(NULL), fCount(0) {} | |
26 | |
27 /** | |
28 * Push an item onto the head of the list. | |
29 * This method is *not* thread safe. | |
30 */ | |
31 void push(T* entry) { | |
32 SkASSERT(entry->fNext == NULL); | |
33 entry->fNext = fHead; | |
34 fHead = entry; | |
35 ++fCount; | |
36 } | |
37 | |
38 /** | |
39 * Takes all the items from another list. | |
reed1
2014/03/05 14:33:01
Are they added to the head or the tail of this lis
iancottrell
2014/03/07 15:06:34
Done.
| |
40 */ | |
41 void takeAll(SkSList<T>& other) { | |
reed1
2014/03/05 14:33:01
typically in Skia if the argument is changed, we p
iancottrell
2014/03/07 15:06:34
Done.
| |
42 if (isEmpty()) { | |
43 swap(other); | |
44 return; | |
45 } | |
46 while(!other.isEmpty()) { | |
47 push(other.pop()); | |
48 } | |
49 } | |
50 | |
51 /** | |
52 * Pop an item from the head of the list. | |
53 * Returns NULL if the list is empty. | |
54 * This method is *not* thread safe. | |
55 */ | |
56 T* pop() { | |
57 if (fHead == NULL) { | |
58 return NULL; | |
59 } | |
60 T* result = fHead; | |
61 fHead = result->fNext; | |
62 result->fNext = NULL; | |
63 --fCount; | |
64 return result; | |
65 } | |
66 | |
67 T* head() { | |
68 return fHead; | |
69 } | |
70 | |
71 /** | |
72 * Returns true if the list has no elements. | |
73 */ | |
74 bool isEmpty() { | |
reed1
2014/03/05 14:33:01
const
iancottrell
2014/03/07 15:06:34
Done.
| |
75 return fHead == NULL; | |
reed1
2014/03/05 14:33:01
tiny nit: Skia tries to be paranoid, and writes th
iancottrell
2014/03/07 15:06:34
Done.
| |
76 } | |
77 | |
78 /** | |
79 * Swaps the contents of this list with another one. | |
80 */ | |
81 void swap(SkSList<T>& other) { | |
82 SkTSwap(fHead, other.fHead); | |
83 SkTSwap(fCount, other.fCount); | |
84 } | |
85 | |
86 /** | |
87 * Returns the count of elements in the list. | |
88 */ | |
89 int getCount() { | |
reed1
2014/03/05 14:33:01
const
iancottrell
2014/03/07 15:06:34
Done.
| |
90 return fCount; | |
91 } | |
92 private: | |
93 T* fHead; | |
94 int fCount; | |
95 }; | |
96 | |
97 | |
98 /** | |
99 * An implementation of a self growing free list of objects. | |
100 * Constructors and destructors will be called on the objects. | |
101 * All memory will be reclaimed when the free list is destroyed, so the free | |
102 * list must survive longer than you are using any item taken from it. | |
103 */ | |
104 template<typename T, int growth = 4096/sizeof(T)> class SkFreeList : public SkSL ist<T> { | |
105 public: | |
106 SkFreeList() {} | |
107 ~SkFreeList() { | |
108 while(!fBlocks.isEmpty()) { SkDELETE(fBlocks.pop()); } | |
109 } | |
110 /** | |
111 * Get an item from the free list. | |
112 * If the free list has no items, it will grow. | |
113 * The free list will never shrink, it will use the maximum memory it has | |
114 * ever reached until destroyed. | |
115 * The returned item is only valid as long as the free list has not been | |
116 * destroyed, at that point all memory allocated by grow will have been | |
117 * reclaimed. | |
118 * This method is *not* thread safe. | |
119 */ | |
120 T* pop() { | |
121 if (this->isEmpty()) { grow(); } | |
122 return SkSList<T>::pop(); | |
123 } | |
124 private: | |
125 /** | |
126 * The type for a new block of entries for the list. | |
127 */ | |
128 struct Block { | |
129 Block() : fNext(0) {} | |
130 Block* fNext; | |
131 T entries[growth]; | |
132 }; | |
133 SkSList<Block> fBlocks; | |
134 | |
135 void grow() { | |
136 Block* block = SkNEW(Block); | |
137 fBlocks.push(block); | |
138 for(int index = 0; index < growth; ++index) { | |
139 push(&block->entries[index]); | |
140 } | |
141 } | |
142 | |
143 }; | |
144 | |
145 /** | |
146 * A QuadTree implementation. In short, it is a tree containing a hierarchy of b ounding rectangles | |
17 * in which each internal node has exactly four children. | 147 * in which each internal node has exactly four children. |
18 * | 148 * |
19 * For more details see: | 149 * For more details see: |
20 * | 150 * |
21 * http://en.wikipedia.org/wiki/Quadtree | 151 * http://en.wikipedia.org/wiki/Quadtree |
22 */ | 152 */ |
23 class SkQuadTree : public SkBBoxHierarchy { | 153 class SkQuadTree : public SkBBoxHierarchy { |
24 public: | 154 public: |
25 SK_DECLARE_INST_COUNT(SkQuadTree) | 155 SK_DECLARE_INST_COUNT(SkQuadTree) |
26 | 156 |
27 /** | 157 /** |
28 * Create a new QuadTree | 158 * Create a new QuadTree |
reed1
2014/03/05 14:33:01
What is the bounds parameter?
Can the factory ever
iancottrell
2014/03/07 15:06:34
To be honest, I have no idea why this code has a f
| |
29 */ | 159 */ |
30 static SkQuadTree* Create(const SkIRect& bounds); | 160 static SkQuadTree* Create(const SkIRect& bounds); |
31 virtual ~SkQuadTree(); | 161 virtual ~SkQuadTree(); |
32 | 162 |
33 /** | 163 /** |
34 * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately | 164 * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately |
35 * need to use the tree; we may allow the insert to be deferred (this can al low us to bulk-load | 165 * need to use the tree; we may allow the insert to be deferred (this can al low us to bulk-load |
36 * a large batch of nodes at once, which tends to be faster and produce a be tter tree). | 166 * a large batch of nodes at once, which tends to be faster and produce a be tter tree). |
37 * @param data The data value | 167 * @param data The data value |
38 * @param bounds The corresponding bounding box | 168 * @param bounds The corresponding bounding box |
39 * @param defer Can this insert be deferred? (this may be ignored) | 169 * @param defer Can this insert be deferred? (this may be ignored) |
40 */ | 170 */ |
41 virtual void insert(void* data, const SkIRect& bounds, bool defer = false) S K_OVERRIDE; | 171 virtual void insert(void* data, const SkIRect& bounds, bool defer = false) S K_OVERRIDE; |
42 | 172 |
43 /** | 173 /** |
44 * If any inserts have been deferred, this will add them into the tree | 174 * If any inserts have been deferred, this will add them into the tree |
45 */ | 175 */ |
46 virtual void flushDeferredInserts() SK_OVERRIDE {} | 176 virtual void flushDeferredInserts() SK_OVERRIDE; |
47 | 177 |
48 /** | 178 /** |
49 * Given a query rectangle, populates the passed-in array with the elements it intersects | 179 * Given a query rectangle, populates the passed-in array with the elements it intersects |
50 */ | 180 */ |
51 virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVER RIDE; | 181 virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVER RIDE; |
52 | 182 |
53 virtual void clear() SK_OVERRIDE; | 183 virtual void clear() SK_OVERRIDE; |
54 | 184 |
55 /** | 185 /** |
56 * Gets the depth of the tree structure | 186 * Gets the depth of the tree structure |
57 */ | 187 */ |
58 virtual int getDepth() const SK_OVERRIDE; | 188 virtual int getDepth() const SK_OVERRIDE; |
59 | 189 |
60 /** | 190 /** |
61 * This gets the insertion count (rather than the node count) | 191 * This gets the insertion count (rather than the node count) |
62 */ | 192 */ |
63 virtual int getCount() const SK_OVERRIDE { return fCount; } | 193 virtual int getCount() const SK_OVERRIDE { return fEntryCount; } |
64 | 194 |
65 virtual void rewindInserts() SK_OVERRIDE; | 195 virtual void rewindInserts() SK_OVERRIDE; |
66 | 196 |
67 private: | 197 private: |
68 class QuadTreeNode; | 198 struct Entry { |
199 Entry() : fNext(NULL), fData(NULL) {} | |
200 Entry* fNext; | |
201 SkIRect fBounds; | |
202 void* fData; | |
203 }; | |
204 | |
205 static const int kChildCount = 4; | |
206 | |
207 struct Node { | |
208 Node() : fNext(NULL) { | |
209 for (int index=0; index<kChildCount; ++index) { | |
210 fChildren[index] = NULL; | |
211 } | |
212 } | |
213 SkSList<Entry> fEntries; | |
214 SkIRect fBounds; | |
215 SkIPoint fSplitPoint; // Only valid if the node has children. | |
216 union { // Unioned only to save space | |
217 Node* fNext; // Used when in a free list, where it has no children. | |
218 Node* fChildren[kChildCount]; | |
219 }; | |
220 }; | |
221 | |
222 SkFreeList<Entry> fFreeEntries; | |
223 SkFreeList<Node> fFreeNodes; | |
224 int fEntryCount; | |
225 Node* fRoot; | |
226 SkSList<Entry> fDeferred; | |
69 | 227 |
70 SkQuadTree(const SkIRect& bounds); | 228 SkQuadTree(const SkIRect& bounds); |
71 | 229 Node* pickChild(Node* node, const SkIRect& bounds) const; |
72 // This is the count of data elements (rather than total nodes in the tree) | 230 void insert(Node* node, Entry* entry); |
73 int fCount; | 231 void search(Node* node, const SkIRect& query, SkTDArray<void*>* results) con st; |
74 | 232 void clear(Node* node); |
75 QuadTreeNode* fRoot; | 233 int getDepth(Node* node) const; |
76 | 234 |
77 typedef SkBBoxHierarchy INHERITED; | 235 typedef SkBBoxHierarchy INHERITED; |
78 }; | 236 }; |
79 | 237 |
80 #endif | 238 #endif |
OLD | NEW |