Sat, 03 Jan 2015 20:18:00 +0100
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 |