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