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 2005 The Android Open Source Project |
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 | |
michael@0 | 9 | |
michael@0 | 10 | #ifndef SkRegion_DEFINED |
michael@0 | 11 | #define SkRegion_DEFINED |
michael@0 | 12 | |
michael@0 | 13 | #include "SkRect.h" |
michael@0 | 14 | |
michael@0 | 15 | class SkPath; |
michael@0 | 16 | class SkRgnBuilder; |
michael@0 | 17 | |
michael@0 | 18 | namespace android { |
michael@0 | 19 | class Region; |
michael@0 | 20 | } |
michael@0 | 21 | |
michael@0 | 22 | #define SkRegion_gEmptyRunHeadPtr ((SkRegion::RunHead*)-1) |
michael@0 | 23 | #define SkRegion_gRectRunHeadPtr 0 |
michael@0 | 24 | |
michael@0 | 25 | /** \class SkRegion |
michael@0 | 26 | |
michael@0 | 27 | The SkRegion class encapsulates the geometric region used to specify |
michael@0 | 28 | clipping areas for drawing. |
michael@0 | 29 | */ |
michael@0 | 30 | class SK_API SkRegion { |
michael@0 | 31 | public: |
michael@0 | 32 | typedef int32_t RunType; |
michael@0 | 33 | enum { |
michael@0 | 34 | kRunTypeSentinel = 0x7FFFFFFF |
michael@0 | 35 | }; |
michael@0 | 36 | |
michael@0 | 37 | SkRegion(); |
michael@0 | 38 | SkRegion(const SkRegion&); |
michael@0 | 39 | explicit SkRegion(const SkIRect&); |
michael@0 | 40 | ~SkRegion(); |
michael@0 | 41 | |
michael@0 | 42 | SkRegion& operator=(const SkRegion&); |
michael@0 | 43 | |
michael@0 | 44 | /** |
michael@0 | 45 | * Return true if the two regions are equal. i.e. The enclose exactly |
michael@0 | 46 | * the same area. |
michael@0 | 47 | */ |
michael@0 | 48 | bool operator==(const SkRegion& other) const; |
michael@0 | 49 | |
michael@0 | 50 | /** |
michael@0 | 51 | * Return true if the two regions are not equal. |
michael@0 | 52 | */ |
michael@0 | 53 | bool operator!=(const SkRegion& other) const { |
michael@0 | 54 | return !(*this == other); |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | /** |
michael@0 | 58 | * Replace this region with the specified region, and return true if the |
michael@0 | 59 | * resulting region is non-empty. |
michael@0 | 60 | */ |
michael@0 | 61 | bool set(const SkRegion& src) { |
michael@0 | 62 | SkASSERT(&src); |
michael@0 | 63 | *this = src; |
michael@0 | 64 | return !this->isEmpty(); |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | /** |
michael@0 | 68 | * Swap the contents of this and the specified region. This operation |
michael@0 | 69 | * is gauarenteed to never fail. |
michael@0 | 70 | */ |
michael@0 | 71 | void swap(SkRegion&); |
michael@0 | 72 | |
michael@0 | 73 | /** Return true if this region is empty */ |
michael@0 | 74 | bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; } |
michael@0 | 75 | |
michael@0 | 76 | /** Return true if this region is a single, non-empty rectangle */ |
michael@0 | 77 | bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; } |
michael@0 | 78 | |
michael@0 | 79 | /** Return true if this region consists of more than 1 rectangular area */ |
michael@0 | 80 | bool isComplex() const { return !this->isEmpty() && !this->isRect(); } |
michael@0 | 81 | |
michael@0 | 82 | /** |
michael@0 | 83 | * Return the bounds of this region. If the region is empty, returns an |
michael@0 | 84 | * empty rectangle. |
michael@0 | 85 | */ |
michael@0 | 86 | const SkIRect& getBounds() const { return fBounds; } |
michael@0 | 87 | |
michael@0 | 88 | /** |
michael@0 | 89 | * Returns a value that grows approximately linearly with the number of |
michael@0 | 90 | * intervals comprised in the region. Empty region will return 0, Rect |
michael@0 | 91 | * will return 1, Complex will return a value > 1. |
michael@0 | 92 | * |
michael@0 | 93 | * Use this to compare two regions, where the larger count likely |
michael@0 | 94 | * indicates a more complex region. |
michael@0 | 95 | */ |
michael@0 | 96 | int computeRegionComplexity() const; |
michael@0 | 97 | |
michael@0 | 98 | /** |
michael@0 | 99 | * Returns true if the region is non-empty, and if so, appends the |
michael@0 | 100 | * boundary(s) of the region to the specified path. |
michael@0 | 101 | * If the region is empty, returns false, and path is left unmodified. |
michael@0 | 102 | */ |
michael@0 | 103 | bool getBoundaryPath(SkPath* path) const; |
michael@0 | 104 | |
michael@0 | 105 | /** |
michael@0 | 106 | * Set the region to be empty, and return false, since the resulting |
michael@0 | 107 | * region is empty |
michael@0 | 108 | */ |
michael@0 | 109 | bool setEmpty(); |
michael@0 | 110 | |
michael@0 | 111 | /** |
michael@0 | 112 | * If rect is non-empty, set this region to that rectangle and return true, |
michael@0 | 113 | * otherwise set this region to empty and return false. |
michael@0 | 114 | */ |
michael@0 | 115 | bool setRect(const SkIRect&); |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * If left < right and top < bottom, set this region to that rectangle and |
michael@0 | 119 | * return true, otherwise set this region to empty and return false. |
michael@0 | 120 | */ |
michael@0 | 121 | bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom); |
michael@0 | 122 | |
michael@0 | 123 | /** |
michael@0 | 124 | * Set this region to the union of an array of rects. This is generally |
michael@0 | 125 | * faster than calling region.op(rect, kUnion_Op) in a loop. If count is |
michael@0 | 126 | * 0, then this region is set to the empty region. |
michael@0 | 127 | * @return true if the resulting region is non-empty |
michael@0 | 128 | */ |
michael@0 | 129 | bool setRects(const SkIRect rects[], int count); |
michael@0 | 130 | |
michael@0 | 131 | /** |
michael@0 | 132 | * Set this region to the specified region, and return true if it is |
michael@0 | 133 | * non-empty. |
michael@0 | 134 | */ |
michael@0 | 135 | bool setRegion(const SkRegion&); |
michael@0 | 136 | |
michael@0 | 137 | /** |
michael@0 | 138 | * Set this region to the area described by the path, clipped. |
michael@0 | 139 | * Return true if the resulting region is non-empty. |
michael@0 | 140 | * This produces a region that is identical to the pixels that would be |
michael@0 | 141 | * drawn by the path (with no antialiasing) with the specified clip. |
michael@0 | 142 | */ |
michael@0 | 143 | bool setPath(const SkPath&, const SkRegion& clip); |
michael@0 | 144 | |
michael@0 | 145 | /** |
michael@0 | 146 | * Returns true if the specified rectangle has a non-empty intersection |
michael@0 | 147 | * with this region. |
michael@0 | 148 | */ |
michael@0 | 149 | bool intersects(const SkIRect&) const; |
michael@0 | 150 | |
michael@0 | 151 | /** |
michael@0 | 152 | * Returns true if the specified region has a non-empty intersection |
michael@0 | 153 | * with this region. |
michael@0 | 154 | */ |
michael@0 | 155 | bool intersects(const SkRegion&) const; |
michael@0 | 156 | |
michael@0 | 157 | /** |
michael@0 | 158 | * Return true if the specified x,y coordinate is inside the region. |
michael@0 | 159 | */ |
michael@0 | 160 | bool contains(int32_t x, int32_t y) const; |
michael@0 | 161 | |
michael@0 | 162 | /** |
michael@0 | 163 | * Return true if the specified rectangle is completely inside the region. |
michael@0 | 164 | * This works for simple (rectangular) and complex regions, and always |
michael@0 | 165 | * returns the correct result. Note: if either this region or the rectangle |
michael@0 | 166 | * is empty, contains() returns false. |
michael@0 | 167 | */ |
michael@0 | 168 | bool contains(const SkIRect&) const; |
michael@0 | 169 | |
michael@0 | 170 | /** |
michael@0 | 171 | * Return true if the specified region is completely inside the region. |
michael@0 | 172 | * This works for simple (rectangular) and complex regions, and always |
michael@0 | 173 | * returns the correct result. Note: if either region is empty, contains() |
michael@0 | 174 | * returns false. |
michael@0 | 175 | */ |
michael@0 | 176 | bool contains(const SkRegion&) const; |
michael@0 | 177 | |
michael@0 | 178 | /** |
michael@0 | 179 | * Return true if this region is a single rectangle (not complex) and the |
michael@0 | 180 | * specified rectangle is contained by this region. Returning false is not |
michael@0 | 181 | * a guarantee that the rectangle is not contained by this region, but |
michael@0 | 182 | * return true is a guarantee that the rectangle is contained by this region. |
michael@0 | 183 | */ |
michael@0 | 184 | bool quickContains(const SkIRect& r) const { |
michael@0 | 185 | return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom); |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | /** |
michael@0 | 189 | * Return true if this region is a single rectangle (not complex) and the |
michael@0 | 190 | * specified rectangle is contained by this region. Returning false is not |
michael@0 | 191 | * a guarantee that the rectangle is not contained by this region, but |
michael@0 | 192 | * return true is a guarantee that the rectangle is contained by this |
michael@0 | 193 | * region. |
michael@0 | 194 | */ |
michael@0 | 195 | bool quickContains(int32_t left, int32_t top, int32_t right, |
michael@0 | 196 | int32_t bottom) const { |
michael@0 | 197 | SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region |
michael@0 | 198 | |
michael@0 | 199 | return left < right && top < bottom && |
michael@0 | 200 | fRunHead == SkRegion_gRectRunHeadPtr && // this->isRect() |
michael@0 | 201 | /* fBounds.contains(left, top, right, bottom); */ |
michael@0 | 202 | fBounds.fLeft <= left && fBounds.fTop <= top && |
michael@0 | 203 | fBounds.fRight >= right && fBounds.fBottom >= bottom; |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | /** |
michael@0 | 207 | * Return true if this region is empty, or if the specified rectangle does |
michael@0 | 208 | * not intersect the region. Returning false is not a guarantee that they |
michael@0 | 209 | * intersect, but returning true is a guarantee that they do not. |
michael@0 | 210 | */ |
michael@0 | 211 | bool quickReject(const SkIRect& rect) const { |
michael@0 | 212 | return this->isEmpty() || rect.isEmpty() || |
michael@0 | 213 | !SkIRect::Intersects(fBounds, rect); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | /** |
michael@0 | 217 | * Return true if this region, or rgn, is empty, or if their bounds do not |
michael@0 | 218 | * intersect. Returning false is not a guarantee that they intersect, but |
michael@0 | 219 | * returning true is a guarantee that they do not. |
michael@0 | 220 | */ |
michael@0 | 221 | bool quickReject(const SkRegion& rgn) const { |
michael@0 | 222 | return this->isEmpty() || rgn.isEmpty() || |
michael@0 | 223 | !SkIRect::Intersects(fBounds, rgn.fBounds); |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | /** Translate the region by the specified (dx, dy) amount. */ |
michael@0 | 227 | void translate(int dx, int dy) { this->translate(dx, dy, this); } |
michael@0 | 228 | |
michael@0 | 229 | /** |
michael@0 | 230 | * Translate the region by the specified (dx, dy) amount, writing the |
michael@0 | 231 | * resulting region into dst. Note: it is legal to pass this region as the |
michael@0 | 232 | * dst parameter, effectively translating the region in place. If dst is |
michael@0 | 233 | * null, nothing happens. |
michael@0 | 234 | */ |
michael@0 | 235 | void translate(int dx, int dy, SkRegion* dst) const; |
michael@0 | 236 | |
michael@0 | 237 | /** |
michael@0 | 238 | * The logical operations that can be performed when combining two regions. |
michael@0 | 239 | */ |
michael@0 | 240 | enum Op { |
michael@0 | 241 | kDifference_Op, //!< subtract the op region from the first region |
michael@0 | 242 | kIntersect_Op, //!< intersect the two regions |
michael@0 | 243 | kUnion_Op, //!< union (inclusive-or) the two regions |
michael@0 | 244 | kXOR_Op, //!< exclusive-or the two regions |
michael@0 | 245 | /** subtract the first region from the op region */ |
michael@0 | 246 | kReverseDifference_Op, |
michael@0 | 247 | kReplace_Op //!< replace the dst region with the op region |
michael@0 | 248 | }; |
michael@0 | 249 | |
michael@0 | 250 | /** |
michael@0 | 251 | * Set this region to the result of applying the Op to this region and the |
michael@0 | 252 | * specified rectangle: this = (this op rect). |
michael@0 | 253 | * Return true if the resulting region is non-empty. |
michael@0 | 254 | */ |
michael@0 | 255 | bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); } |
michael@0 | 256 | |
michael@0 | 257 | /** |
michael@0 | 258 | * Set this region to the result of applying the Op to this region and the |
michael@0 | 259 | * specified rectangle: this = (this op rect). |
michael@0 | 260 | * Return true if the resulting region is non-empty. |
michael@0 | 261 | */ |
michael@0 | 262 | bool op(int left, int top, int right, int bottom, Op op) { |
michael@0 | 263 | SkIRect rect; |
michael@0 | 264 | rect.set(left, top, right, bottom); |
michael@0 | 265 | return this->op(*this, rect, op); |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | /** |
michael@0 | 269 | * Set this region to the result of applying the Op to this region and the |
michael@0 | 270 | * specified region: this = (this op rgn). |
michael@0 | 271 | * Return true if the resulting region is non-empty. |
michael@0 | 272 | */ |
michael@0 | 273 | bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); } |
michael@0 | 274 | |
michael@0 | 275 | /** |
michael@0 | 276 | * Set this region to the result of applying the Op to the specified |
michael@0 | 277 | * rectangle and region: this = (rect op rgn). |
michael@0 | 278 | * Return true if the resulting region is non-empty. |
michael@0 | 279 | */ |
michael@0 | 280 | bool op(const SkIRect& rect, const SkRegion& rgn, Op); |
michael@0 | 281 | |
michael@0 | 282 | /** |
michael@0 | 283 | * Set this region to the result of applying the Op to the specified |
michael@0 | 284 | * region and rectangle: this = (rgn op rect). |
michael@0 | 285 | * Return true if the resulting region is non-empty. |
michael@0 | 286 | */ |
michael@0 | 287 | bool op(const SkRegion& rgn, const SkIRect& rect, Op); |
michael@0 | 288 | |
michael@0 | 289 | /** |
michael@0 | 290 | * Set this region to the result of applying the Op to the specified |
michael@0 | 291 | * regions: this = (rgna op rgnb). |
michael@0 | 292 | * Return true if the resulting region is non-empty. |
michael@0 | 293 | */ |
michael@0 | 294 | bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op); |
michael@0 | 295 | |
michael@0 | 296 | #ifdef SK_BUILD_FOR_ANDROID |
michael@0 | 297 | /** Returns a new char* containing the list of rectangles in this region |
michael@0 | 298 | */ |
michael@0 | 299 | char* toString(); |
michael@0 | 300 | #endif |
michael@0 | 301 | |
michael@0 | 302 | /** |
michael@0 | 303 | * Returns the sequence of rectangles, sorted in Y and X, that make up |
michael@0 | 304 | * this region. |
michael@0 | 305 | */ |
michael@0 | 306 | class SK_API Iterator { |
michael@0 | 307 | public: |
michael@0 | 308 | Iterator() : fRgn(NULL), fDone(true) {} |
michael@0 | 309 | Iterator(const SkRegion&); |
michael@0 | 310 | // if we have a region, reset to it and return true, else return false |
michael@0 | 311 | bool rewind(); |
michael@0 | 312 | // reset the iterator, using the new region |
michael@0 | 313 | void reset(const SkRegion&); |
michael@0 | 314 | bool done() const { return fDone; } |
michael@0 | 315 | void next(); |
michael@0 | 316 | const SkIRect& rect() const { return fRect; } |
michael@0 | 317 | // may return null |
michael@0 | 318 | const SkRegion* rgn() const { return fRgn; } |
michael@0 | 319 | |
michael@0 | 320 | private: |
michael@0 | 321 | const SkRegion* fRgn; |
michael@0 | 322 | const RunType* fRuns; |
michael@0 | 323 | SkIRect fRect; |
michael@0 | 324 | bool fDone; |
michael@0 | 325 | }; |
michael@0 | 326 | |
michael@0 | 327 | /** |
michael@0 | 328 | * Returns the sequence of rectangles, sorted in Y and X, that make up |
michael@0 | 329 | * this region intersected with the specified clip rectangle. |
michael@0 | 330 | */ |
michael@0 | 331 | class SK_API Cliperator { |
michael@0 | 332 | public: |
michael@0 | 333 | Cliperator(const SkRegion&, const SkIRect& clip); |
michael@0 | 334 | bool done() { return fDone; } |
michael@0 | 335 | void next(); |
michael@0 | 336 | const SkIRect& rect() const { return fRect; } |
michael@0 | 337 | |
michael@0 | 338 | private: |
michael@0 | 339 | Iterator fIter; |
michael@0 | 340 | SkIRect fClip; |
michael@0 | 341 | SkIRect fRect; |
michael@0 | 342 | bool fDone; |
michael@0 | 343 | }; |
michael@0 | 344 | |
michael@0 | 345 | /** |
michael@0 | 346 | * Returns the sequence of runs that make up this region for the specified |
michael@0 | 347 | * Y scanline, clipped to the specified left and right X values. |
michael@0 | 348 | */ |
michael@0 | 349 | class Spanerator { |
michael@0 | 350 | public: |
michael@0 | 351 | Spanerator(const SkRegion&, int y, int left, int right); |
michael@0 | 352 | bool next(int* left, int* right); |
michael@0 | 353 | |
michael@0 | 354 | private: |
michael@0 | 355 | const SkRegion::RunType* fRuns; |
michael@0 | 356 | int fLeft, fRight; |
michael@0 | 357 | bool fDone; |
michael@0 | 358 | }; |
michael@0 | 359 | |
michael@0 | 360 | /** |
michael@0 | 361 | * Write the region to the buffer, and return the number of bytes written. |
michael@0 | 362 | * If buffer is NULL, it still returns the number of bytes. |
michael@0 | 363 | */ |
michael@0 | 364 | size_t writeToMemory(void* buffer) const; |
michael@0 | 365 | /** |
michael@0 | 366 | * Initializes the region from the buffer |
michael@0 | 367 | * |
michael@0 | 368 | * @param buffer Memory to read from |
michael@0 | 369 | * @param length Amount of memory available in the buffer |
michael@0 | 370 | * @return number of bytes read (must be a multiple of 4) or |
michael@0 | 371 | * 0 if there was not enough memory available |
michael@0 | 372 | */ |
michael@0 | 373 | size_t readFromMemory(const void* buffer, size_t length); |
michael@0 | 374 | |
michael@0 | 375 | /** |
michael@0 | 376 | * Returns a reference to a global empty region. Just a convenience for |
michael@0 | 377 | * callers that need a const empty region. |
michael@0 | 378 | */ |
michael@0 | 379 | static const SkRegion& GetEmptyRegion(); |
michael@0 | 380 | |
michael@0 | 381 | SkDEBUGCODE(void dump() const;) |
michael@0 | 382 | SkDEBUGCODE(void validate() const;) |
michael@0 | 383 | SkDEBUGCODE(static void UnitTest();) |
michael@0 | 384 | |
michael@0 | 385 | // expose this to allow for regression test on complex regions |
michael@0 | 386 | SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);) |
michael@0 | 387 | |
michael@0 | 388 | private: |
michael@0 | 389 | enum { |
michael@0 | 390 | kOpCount = kReplace_Op + 1 |
michael@0 | 391 | }; |
michael@0 | 392 | |
michael@0 | 393 | enum { |
michael@0 | 394 | // T |
michael@0 | 395 | // [B N L R S] |
michael@0 | 396 | // S |
michael@0 | 397 | kRectRegionRuns = 7 |
michael@0 | 398 | }; |
michael@0 | 399 | |
michael@0 | 400 | friend class android::Region; // needed for marshalling efficiently |
michael@0 | 401 | |
michael@0 | 402 | struct RunHead; |
michael@0 | 403 | |
michael@0 | 404 | // allocate space for count runs |
michael@0 | 405 | void allocateRuns(int count); |
michael@0 | 406 | void allocateRuns(int count, int ySpanCount, int intervalCount); |
michael@0 | 407 | void allocateRuns(const RunHead& src); |
michael@0 | 408 | |
michael@0 | 409 | SkIRect fBounds; |
michael@0 | 410 | RunHead* fRunHead; |
michael@0 | 411 | |
michael@0 | 412 | void freeRuns(); |
michael@0 | 413 | |
michael@0 | 414 | /** |
michael@0 | 415 | * Return the runs from this region, consing up fake runs if the region |
michael@0 | 416 | * is empty or a rect. In those 2 cases, we use tmpStorage to hold the |
michael@0 | 417 | * run data. |
michael@0 | 418 | */ |
michael@0 | 419 | const RunType* getRuns(RunType tmpStorage[], int* intervals) const; |
michael@0 | 420 | |
michael@0 | 421 | // This is called with runs[] that do not yet have their interval-count |
michael@0 | 422 | // field set on each scanline. That is computed as part of this call |
michael@0 | 423 | // (inside ComputeRunBounds). |
michael@0 | 424 | bool setRuns(RunType runs[], int count); |
michael@0 | 425 | |
michael@0 | 426 | int count_runtype_values(int* itop, int* ibot) const; |
michael@0 | 427 | |
michael@0 | 428 | static void BuildRectRuns(const SkIRect& bounds, |
michael@0 | 429 | RunType runs[kRectRegionRuns]); |
michael@0 | 430 | |
michael@0 | 431 | // If the runs define a simple rect, return true and set bounds to that |
michael@0 | 432 | // rect. If not, return false and ignore bounds. |
michael@0 | 433 | static bool RunsAreARect(const SkRegion::RunType runs[], int count, |
michael@0 | 434 | SkIRect* bounds); |
michael@0 | 435 | |
michael@0 | 436 | /** |
michael@0 | 437 | * If the last arg is null, just return if the result is non-empty, |
michael@0 | 438 | * else store the result in the last arg. |
michael@0 | 439 | */ |
michael@0 | 440 | static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*); |
michael@0 | 441 | |
michael@0 | 442 | friend struct RunHead; |
michael@0 | 443 | friend class Iterator; |
michael@0 | 444 | friend class Spanerator; |
michael@0 | 445 | friend class SkRgnBuilder; |
michael@0 | 446 | friend class SkFlatRegion; |
michael@0 | 447 | }; |
michael@0 | 448 | |
michael@0 | 449 | #endif |