gfx/skia/trunk/src/core/SkRegion_rects.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 /*
michael@0 3 * Copyright 2011 Google Inc.
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8 #include "SkRegion.h"
michael@0 9 #include "SkChunkAlloc.h"
michael@0 10 #include "SkTDArray.h"
michael@0 11 #include "SkTemplates.h"
michael@0 12
michael@0 13 #if 0
michael@0 14
michael@0 15 struct VEdge {
michael@0 16 VEdge* fPrev;
michael@0 17 VEdge* fNext;
michael@0 18
michael@0 19 SkRegion::RunType fX;
michael@0 20 SkRegion::RunType fTop;
michael@0 21 SkRegion::RunType fBottom;
michael@0 22 int fWinding;
michael@0 23
michael@0 24 void removeFromList() {
michael@0 25 fPrev->fNext = fNext;
michael@0 26 fNext->fPrev = fPrev;
michael@0 27 }
michael@0 28
michael@0 29 void backwardsInsert() {
michael@0 30 while (fPrev->fX > fX) {
michael@0 31 VEdge* prev = fPrev;
michael@0 32 VEdge* next = this;
michael@0 33
michael@0 34 // remove prev from the list
michael@0 35 prev->fPrev->fNext = next;
michael@0 36 next->fPrev = prev->fPrev;
michael@0 37
michael@0 38 // insert prev after next
michael@0 39 prev->fNext = next->fNext;
michael@0 40 next->fNext->fPrev = prev;
michael@0 41 next->fNext = prev;
michael@0 42 prev->fPrev = next;
michael@0 43 }
michael@0 44 }
michael@0 45
michael@0 46 static void SetFromRect(VEdge edges[], const SkIRect& r) {
michael@0 47 edges[0].fX = r.fLeft;
michael@0 48 edges[0].fTop = r.fTop;
michael@0 49 edges[0].fBottom = r.fBottom;
michael@0 50 edges[0].fWinding = -1;
michael@0 51
michael@0 52 edges[1].fX = r.fRight;
michael@0 53 edges[1].fTop = r.fTop;
michael@0 54 edges[1].fBottom = r.fBottom;
michael@0 55 edges[1].fWinding = 1;
michael@0 56 }
michael@0 57 };
michael@0 58
michael@0 59 class Accumulator {
michael@0 60 public:
michael@0 61 Accumulator(SkRegion::RunType top, int numRects);
michael@0 62 ~Accumulator() {}
michael@0 63
michael@0 64 SkRegion::RunType append(SkRegion::RunType top, const VEdge* edge);
michael@0 65
michael@0 66 int count() const { return fTotalCount; }
michael@0 67 void copyTo(SkRegion::RunType dst[]);
michael@0 68
michael@0 69 private:
michael@0 70 struct Row {
michael@0 71 SkRegion::RunType* fPtr;
michael@0 72 SkRegion::RunType fBottom;
michael@0 73 int fCount; // just [L R] count
michael@0 74 };
michael@0 75 SkChunkAlloc fAlloc;
michael@0 76 SkTDArray<Row> fRows;
michael@0 77 SkRegion::RunType fTop;
michael@0 78 int fTotalCount;
michael@0 79 int fRectCount;
michael@0 80 };
michael@0 81
michael@0 82 Accumulator::Accumulator(SkRegion::RunType top, int numRects)
michael@0 83 : fAlloc((1 + numRects * 2 + 1) * sizeof(int32_t)) {
michael@0 84 fRectCount = numRects;
michael@0 85 fTop = top;
michael@0 86 fTotalCount = 2; // Top + final sentinel
michael@0 87 }
michael@0 88
michael@0 89 //#define TRACE_ROW(code) code
michael@0 90 #define TRACE_ROW(code)
michael@0 91
michael@0 92 SkRegion::RunType Accumulator::append(SkRegion::RunType currY, const VEdge* edge) {
michael@0 93 // worst-case size
michael@0 94 size_t size = fRectCount * 2 * sizeof(SkRegion::RunType);
michael@0 95 SkRegion::RunType* row = (SkRegion::RunType*)fAlloc.allocThrow(size);
michael@0 96 SkRegion::RunType* rowHead = row;
michael@0 97
michael@0 98 SkRegion::RunType nextY = SkRegion::kRunTypeSentinel;
michael@0 99 int winding = edge->fWinding;
michael@0 100
michael@0 101 // record the L R values for this row
michael@0 102
michael@0 103 if (edge->fTop > currY) {
michael@0 104 nextY = SkMin32(nextY, edge->fTop);
michael@0 105 TRACE_ROW(SkDebugf("Y %d\n", currY);)
michael@0 106 } else {
michael@0 107 SkRegion::RunType currR;
michael@0 108 *row++ = edge->fX;
michael@0 109 TRACE_ROW(SkDebugf("Y %d [%d", currY, edge->fX);)
michael@0 110 edge = edge->fNext;
michael@0 111 for (;;) {
michael@0 112 if (edge->fTop > currY) {
michael@0 113 nextY = SkMin32(nextY, edge->fTop);
michael@0 114 break;
michael@0 115 }
michael@0 116
michael@0 117 int prevWinding = winding;
michael@0 118 winding += edge->fWinding;
michael@0 119 if (0 == winding) { // we finished an interval
michael@0 120 currR = edge->fX;
michael@0 121 } else if (0 == prevWinding && edge->fX > currR) {
michael@0 122 *row++ = currR;
michael@0 123 *row++ = edge->fX;
michael@0 124 TRACE_ROW(SkDebugf(" %d] [%d", currR, edge->fX);)
michael@0 125 }
michael@0 126
michael@0 127 nextY = SkMin32(nextY, edge->fBottom);
michael@0 128 edge = edge->fNext;
michael@0 129 }
michael@0 130 SkASSERT(0 == winding);
michael@0 131 *row++ = currR;
michael@0 132 TRACE_ROW(SkDebugf(" %d]\n", currR);)
michael@0 133 }
michael@0 134 int rowCount = row - rowHead;
michael@0 135
michael@0 136 // now see if we have already seen this row, or if its unique
michael@0 137
michael@0 138 Row* r = fRows.count() ? &fRows[fRows.count() - 1] : NULL;
michael@0 139 if (r && (r->fCount == rowCount) &&
michael@0 140 !memcmp(r->fPtr, rowHead,
michael@0 141 rowCount * sizeof(SkRegion::RunType))) {
michael@0 142 r->fBottom = nextY; // update bottom
michael@0 143 fAlloc.unalloc(rowHead);
michael@0 144 } else {
michael@0 145 Row* r = fRows.append();
michael@0 146 r->fPtr = rowHead;
michael@0 147 r->fBottom = nextY;
michael@0 148 r->fCount = rowCount;
michael@0 149 fTotalCount += 1 + rowCount + 1;
michael@0 150 }
michael@0 151
michael@0 152 return nextY;
michael@0 153 }
michael@0 154
michael@0 155 void Accumulator::copyTo(SkRegion::RunType dst[]) {
michael@0 156 SkDEBUGCODE(SkRegion::RunType* startDst = dst;)
michael@0 157
michael@0 158 *dst++ = fTop;
michael@0 159
michael@0 160 const Row* curr = fRows.begin();
michael@0 161 const Row* stop = fRows.end();
michael@0 162 while (curr < stop) {
michael@0 163 *dst++ = curr->fBottom;
michael@0 164 memcpy(dst, curr->fPtr, curr->fCount * sizeof(SkRegion::RunType));
michael@0 165 dst += curr->fCount;
michael@0 166 *dst++ = SkRegion::kRunTypeSentinel;
michael@0 167 curr += 1;
michael@0 168 }
michael@0 169 *dst++ = SkRegion::kRunTypeSentinel;
michael@0 170 SkASSERT(dst - startDst == fTotalCount);
michael@0 171 }
michael@0 172
michael@0 173 ///////////////////////////////////////////////////////////////////////////////
michael@0 174
michael@0 175 template <typename T> int SkTCmp2Int(const T& a, const T& b) {
michael@0 176 return (a < b) ? -1 : ((b < a) ? 1 : 0);
michael@0 177 }
michael@0 178
michael@0 179 static inline int SkCmp32(int32_t a, int32_t b) {
michael@0 180 return (a < b) ? -1 : ((b < a) ? 1 : 0);
michael@0 181 }
michael@0 182
michael@0 183 static int compare_edgeptr(const void* p0, const void* p1) {
michael@0 184 const VEdge* e0 = *static_cast<VEdge*const*>(p0);
michael@0 185 const VEdge* e1 = *static_cast<VEdge*const*>(p1);
michael@0 186
michael@0 187 SkRegion::RunType v0 = e0->fTop;
michael@0 188 SkRegion::RunType v1 = e1->fTop;
michael@0 189
michael@0 190 if (v0 == v1) {
michael@0 191 v0 = e0->fX;
michael@0 192 v1 = e1->fX;
michael@0 193 }
michael@0 194 return SkCmp32(v0, v1);
michael@0 195 }
michael@0 196
michael@0 197 // fillout edge[] from rects[], sorted. Return the head, and set the tail
michael@0 198 //
michael@0 199 static VEdge* sort_edges(VEdge** edgePtr, VEdge edge[], const SkIRect rects[],
michael@0 200 int rectCount, VEdge** edgeTail) {
michael@0 201 int i;
michael@0 202 VEdge** ptr = edgePtr;
michael@0 203 for (int i = 0; i < rectCount; i++) {
michael@0 204 if (!rects[i].isEmpty()) {
michael@0 205 VEdge::SetFromRect(edge, rects[i]);
michael@0 206 *ptr++ = edge++;
michael@0 207 *ptr++ = edge++;
michael@0 208 }
michael@0 209 }
michael@0 210
michael@0 211 int edgeCount = ptr - edgePtr;
michael@0 212 if (0 == edgeCount) {
michael@0 213 // all the rects[] were empty
michael@0 214 return NULL;
michael@0 215 }
michael@0 216
michael@0 217 qsort(edgePtr, edgeCount, sizeof(*edgePtr), compare_edgeptr);
michael@0 218 for (i = 1; i < edgeCount; i++) {
michael@0 219 edgePtr[i - 1]->fNext = edgePtr[i];
michael@0 220 edgePtr[i]->fPrev = edgePtr[i - 1];
michael@0 221 }
michael@0 222 *edgeTail = edgePtr[edgeCount - 1];
michael@0 223 return edgePtr[0];
michael@0 224 }
michael@0 225
michael@0 226 bool SkRegion::setRects(const SkIRect rects[], int rectCount) {
michael@0 227 if (0 == rectCount) {
michael@0 228 return this->setEmpty();
michael@0 229 }
michael@0 230 if (1 == rectCount) {
michael@0 231 return this->setRect(rects[0]);
michael@0 232 }
michael@0 233
michael@0 234 int edgeCount = rectCount * 2;
michael@0 235 SkAutoMalloc memory((sizeof(VEdge) + sizeof(VEdge*)) * edgeCount);
michael@0 236 VEdge** edgePtr = (VEdge**)memory.get();
michael@0 237 VEdge* tail, *head = (VEdge*)(edgePtr + edgeCount);
michael@0 238 head = sort_edges(edgePtr, head, rects, rectCount, &tail);
michael@0 239 // check if we have no edges
michael@0 240 if (NULL == head) {
michael@0 241 return this->setEmpty();
michael@0 242 }
michael@0 243
michael@0 244 // at this stage, we don't really care about edgeCount, or if rectCount is
michael@0 245 // larger that it should be (since sort_edges might have skipped some
michael@0 246 // empty rects[]). rectCount now is just used for worst-case allocations
michael@0 247
michael@0 248 VEdge headEdge, tailEdge;
michael@0 249 headEdge.fPrev = NULL;
michael@0 250 headEdge.fNext = head;
michael@0 251 headEdge.fTop = SK_MinS32;
michael@0 252 headEdge.fX = SK_MinS32;
michael@0 253 head->fPrev = &headEdge;
michael@0 254
michael@0 255 tailEdge.fPrev = tail;
michael@0 256 tailEdge.fNext = NULL;
michael@0 257 tailEdge.fTop = SK_MaxS32;
michael@0 258 tail->fNext = &tailEdge;
michael@0 259
michael@0 260 int32_t currY = head->fTop;
michael@0 261 Accumulator accum(currY, rectCount);
michael@0 262
michael@0 263 while (head->fNext) {
michael@0 264 VEdge* edge = head;
michael@0 265 // accumulate the current
michael@0 266 SkRegion::RunType nextY = accum.append(currY, edge);
michael@0 267 // remove the old
michael@0 268 while (edge->fTop <= currY) {
michael@0 269 VEdge* next = edge->fNext;
michael@0 270 if (edge->fBottom <= nextY) {
michael@0 271 edge->removeFromList();
michael@0 272 }
michael@0 273 edge = next;
michael@0 274 }
michael@0 275 // insert (sorted) the new
michael@0 276 while (edge->fTop == nextY) {
michael@0 277 VEdge* next = edge->fNext;
michael@0 278 edge->backwardsInsert();
michael@0 279 edge = next;
michael@0 280 }
michael@0 281 currY = nextY;
michael@0 282 head = headEdge.fNext;
michael@0 283 }
michael@0 284
michael@0 285 SkAutoTArray<RunType> runs(accum.count());
michael@0 286 accum.copyTo(runs.get());
michael@0 287 return this->setRuns(runs.get(), accum.count());
michael@0 288 }
michael@0 289
michael@0 290 #endif

mercurial