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) { return this->op(*this, rect, op); } 259 260 /** 261 * Set this region to the result of applying the Op to this region and the 262 * specified rectangle: this = (this op rect). 263 * Return true if the resulting region is non-empty. 264 */ op(int left,int top,int right,int bottom,Op op)265 bool op(int left, int top, int right, int bottom, Op op) { 266 SkIRect rect; 267 rect.set(left, top, right, bottom); 268 return this->op(*this, rect, op); 269 } 270 271 /** 272 * Set this region to the result of applying the Op to this region and the 273 * specified region: this = (this op rgn). 274 * Return true if the resulting region is non-empty. 275 */ op(const SkRegion & rgn,Op op)276 bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); } 277 278 /** 279 * Set this region to the result of applying the Op to the specified 280 * rectangle and region: this = (rect op rgn). 281 * Return true if the resulting region is non-empty. 282 */ 283 bool op(const SkIRect& rect, const SkRegion& rgn, Op); 284 285 /** 286 * Set this region to the result of applying the Op to the specified 287 * region and rectangle: this = (rgn op rect). 288 * Return true if the resulting region is non-empty. 289 */ 290 bool op(const SkRegion& rgn, const SkIRect& rect, Op); 291 292 /** 293 * Set this region to the result of applying the Op to the specified 294 * regions: this = (rgna op rgnb). 295 * Return true if the resulting region is non-empty. 296 */ 297 bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op); 298 299 #ifdef SK_BUILD_FOR_ANDROID 300 /** Returns a new char* containing the list of rectangles in this region 301 */ 302 char* toString(); 303 #endif 304 305 /** 306 * Returns the sequence of rectangles, sorted in Y and X, that make up 307 * this region. 308 */ 309 class SK_API Iterator { 310 public: Iterator()311 Iterator() : fRgn(NULL), fDone(true) {} 312 Iterator(const SkRegion&); 313 // if we have a region, reset to it and return true, else return false 314 bool rewind(); 315 // reset the iterator, using the new region 316 void reset(const SkRegion&); done()317 bool done() const { return fDone; } 318 void next(); rect()319 const SkIRect& rect() const { return fRect; } 320 // may return null rgn()321 const SkRegion* rgn() const { return fRgn; } 322 323 private: 324 const SkRegion* fRgn; 325 const RunType* fRuns; 326 SkIRect fRect; 327 bool fDone; 328 }; 329 330 /** 331 * Returns the sequence of rectangles, sorted in Y and X, that make up 332 * this region intersected with the specified clip rectangle. 333 */ 334 class SK_API Cliperator { 335 public: 336 Cliperator(const SkRegion&, const SkIRect& clip); done()337 bool done() { return fDone; } 338 void next(); rect()339 const SkIRect& rect() const { return fRect; } 340 341 private: 342 Iterator fIter; 343 SkIRect fClip; 344 SkIRect fRect; 345 bool fDone; 346 }; 347 348 /** 349 * Returns the sequence of runs that make up this region for the specified 350 * Y scanline, clipped to the specified left and right X values. 351 */ 352 class Spanerator { 353 public: 354 Spanerator(const SkRegion&, int y, int left, int right); 355 bool next(int* left, int* right); 356 357 private: 358 const SkRegion::RunType* fRuns; 359 int fLeft, fRight; 360 bool fDone; 361 }; 362 363 /** 364 * Write the region to the buffer, and return the number of bytes written. 365 * If buffer is NULL, it still returns the number of bytes. 366 */ 367 size_t writeToMemory(void* buffer) const; 368 /** 369 * Initializes the region from the buffer 370 * 371 * @param buffer Memory to read from 372 * @param length Amount of memory available in the buffer 373 * @return number of bytes read (must be a multiple of 4) or 374 * 0 if there was not enough memory available 375 */ 376 size_t readFromMemory(const void* buffer, size_t length); 377 378 /** 379 * Returns a reference to a global empty region. Just a convenience for 380 * callers that need a const empty region. 381 */ 382 static const SkRegion& GetEmptyRegion(); 383 384 SkDEBUGCODE(void dump() const;) 385 SkDEBUGCODE(void validate() const;) 386 SkDEBUGCODE(static void UnitTest();) 387 388 // expose this to allow for regression test on complex regions 389 SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);) 390 391 private: 392 enum { 393 kOpCount = kReplace_Op + 1 394 }; 395 396 enum { 397 // T 398 // [B N L R S] 399 // S 400 kRectRegionRuns = 7 401 }; 402 403 friend class android::Region; // needed for marshalling efficiently 404 405 struct RunHead; 406 407 // allocate space for count runs 408 void allocateRuns(int count); 409 void allocateRuns(int count, int ySpanCount, int intervalCount); 410 void allocateRuns(const RunHead& src); 411 412 SkIRect fBounds; 413 RunHead* fRunHead; 414 415 void freeRuns(); 416 417 /** 418 * Return the runs from this region, consing up fake runs if the region 419 * is empty or a rect. In those 2 cases, we use tmpStorage to hold the 420 * run data. 421 */ 422 const RunType* getRuns(RunType tmpStorage[], int* intervals) const; 423 424 // This is called with runs[] that do not yet have their interval-count 425 // field set on each scanline. That is computed as part of this call 426 // (inside ComputeRunBounds). 427 bool setRuns(RunType runs[], int count); 428 429 int count_runtype_values(int* itop, int* ibot) const; 430 431 static void BuildRectRuns(const SkIRect& bounds, 432 RunType runs[kRectRegionRuns]); 433 434 // If the runs define a simple rect, return true and set bounds to that 435 // rect. If not, return false and ignore bounds. 436 static bool RunsAreARect(const SkRegion::RunType runs[], int count, 437 SkIRect* bounds); 438 439 /** 440 * If the last arg is null, just return if the result is non-empty, 441 * else store the result in the last arg. 442 */ 443 static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*); 444 445 friend struct RunHead; 446 friend class Iterator; 447 friend class Spanerator; 448 friend class SkRgnBuilder; 449 friend class SkFlatRegion; 450 }; 451 452 #endif 453