gfx/skia/trunk/src/core/SkQuadTree.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial