1 /* 2 * Copyright 2005 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 /* Generated by tools/bookmaker from include/core/SkRegion.h and docs/SkRegion_Reference.bmh 9 on 2018-08-10 12:59:44. Additional documentation and examples can be found at: 10 https://skia.org/user/api/SkRegion_Reference 11 12 You may edit either file directly. Structural changes to public interfaces require 13 editing both files. After editing docs/SkRegion_Reference.bmh, run: 14 bookmaker -b docs -i include/core/SkRegion.h -p 15 to create an updated version of this file. 16 */ 17 18 #ifndef SkRegion_DEFINED 19 #define SkRegion_DEFINED 20 21 #include "SkRect.h" 22 23 class SkPath; 24 class SkRgnBuilder; 25 26 /** \class SkRegion 27 SkRegion describes the set of pixels used to clip SkCanvas. SkRegion is compact, 28 efficiently storing a single integer rectangle, or a run length encoded array 29 of rectangles. SkRegion may reduce the current SkCanvas clip, or may be drawn as 30 one or more integer rectangles. SkRegion iterator returns the scan lines or 31 rectangles contained by it, optionally intersecting a bounding rectangle. 32 */ 33 class SK_API SkRegion { 34 typedef int32_t RunType; 35 public: 36 37 /** Constructs an empty SkRegion. SkRegion is set to empty bounds 38 at (0, 0) with zero width and height. 39 40 @return empty SkRegion 41 */ 42 SkRegion(); 43 44 /** Constructs a copy of an existing region. 45 Copy constructor makes two regions identical by value. Internally, region and 46 the returned result share pointer values. The underlying SkRect array is 47 copied when modified. 48 49 Creating a SkRegion copy is very efficient and never allocates memory. 50 SkRegion are always copied by value from the interface; the underlying shared 51 pointers are not exposed. 52 53 @param region SkRegion to copy by value 54 @return copy of SkRegion 55 */ 56 SkRegion(const SkRegion& region); 57 58 /** Constructs a rectangular SkRegion matching the bounds of rect. 59 60 @param rect bounds of constructed SkRegion 61 @return rectangular SkRegion 62 */ 63 explicit SkRegion(const SkIRect& rect); 64 65 /** Releases ownership of any shared data and deletes data if SkRegion is sole owner. 66 */ 67 ~SkRegion(); 68 69 /** Constructs a copy of an existing region. 70 Makes two regions identical by value. Internally, region and 71 the returned result share pointer values. The underlying SkRect array is 72 copied when modified. 73 74 Creating a SkRegion copy is very efficient and never allocates memory. 75 SkRegion are always copied by value from the interface; the underlying shared 76 pointers are not exposed. 77 78 @param region SkRegion to copy by value 79 @return SkRegion to copy by value 80 */ 81 SkRegion& operator=(const SkRegion& region); 82 83 /** Compares SkRegion and other; returns true if they enclose exactly 84 the same area. 85 86 @param other SkRegion to compare 87 @return true if SkRegion pair are equivalent 88 */ 89 bool operator==(const SkRegion& other) const; 90 91 /** Compares SkRegion and other; returns true if they do not enclose the same area. 92 93 @param other SkRegion to compare 94 @return true if SkRegion pair are not equivalent 95 */ 96 bool operator!=(const SkRegion& other) const { 97 return !(*this == other); 98 } 99 100 /** Sets SkRegion to src, and returns true if src bounds is not empty. 101 This makes SkRegion and src identical by value. Internally, 102 SkRegion and src share pointer values. The underlying SkRect array is 103 copied when modified. 104 105 Creating a SkRegion copy is very efficient and never allocates memory. 106 SkRegion are always copied by value from the interface; the underlying shared 107 pointers are not exposed. 108 109 @param src SkRegion to copy 110 @return copy of src 111 */ set(const SkRegion & src)112 bool set(const SkRegion& src) { 113 *this = src; 114 return !this->isEmpty(); 115 } 116 117 /** Exchanges SkIRect array of SkRegion and other. swap() internally exchanges pointers, 118 so it is lightweight and does not allocate memory. 119 120 swap() usage has largely been replaced by operator=(const SkRegion& region). 121 SkPath do not copy their content on assignment until they are written to, 122 making assignment as efficient as swap(). 123 124 @param other operator=(const SkRegion& region) set 125 */ 126 void swap(SkRegion& other); 127 128 /** Returns true if SkRegion is empty. 129 Empty SkRegion has bounds width or height less than or equal to zero. 130 SkRegion() constructs empty SkRegion; setEmpty() 131 and setRect() with dimensionless data make SkRegion empty. 132 133 @return true if bounds has no width or height 134 */ isEmpty()135 bool isEmpty() const { return fRunHead == emptyRunHeadPtr(); } 136 137 /** Returns true if SkRegion is one SkIRect with positive dimensions. 138 139 @return true if SkRegion contains one SkIRect 140 */ isRect()141 bool isRect() const { return fRunHead == kRectRunHeadPtr; } 142 143 /** Returns true if SkRegion is described by more than one rectangle. 144 145 @return true if SkRegion contains more than one SkIRect 146 */ isComplex()147 bool isComplex() const { return !this->isEmpty() && !this->isRect(); } 148 149 /** Returns minimum and maximum axes values of SkIRect array. 150 Returns (0, 0, 0, 0) if SkRegion is empty. 151 152 @return combined bounds of all SkIRect elements 153 */ getBounds()154 const SkIRect& getBounds() const { return fBounds; } 155 156 /** Returns a value that increases with the number of 157 elements in SkRegion. Returns zero if SkRegion is empty. 158 Returns one if SkRegion equals SkIRect; otherwise, returns 159 value greater than one indicating that SkRegion is complex. 160 161 Call to compare SkRegion for relative complexity. 162 163 @return relative complexity 164 */ 165 int computeRegionComplexity() const; 166 167 /** Appends outline of SkRegion to path. 168 Returns true if SkRegion is not empty; otherwise, returns false, and leaves path 169 unmodified. 170 171 @param path SkPath to append to 172 @return true if path changed 173 */ 174 bool getBoundaryPath(SkPath* path) const; 175 176 /** Constructs an empty SkRegion. SkRegion is set to empty bounds 177 at (0, 0) with zero width and height. Always returns false. 178 179 @return false 180 */ 181 bool setEmpty(); 182 183 /** Constructs a rectangular SkRegion matching the bounds of rect. 184 If rect is empty, constructs empty and returns false. 185 186 @param rect bounds of constructed SkRegion 187 @return true if rect is not empty 188 */ 189 bool setRect(const SkIRect& rect); 190 191 /** Constructs SkRegion with bounds (left, top, right, bottom). 192 Returns true if left is less than right and top is less than bottom; otherwise, 193 constructs empty SkRegion and returns false. 194 195 @param left edge of bounds on x-axis 196 @param top edge of bounds on y-axis 197 @param right edge of bounds on x-axis 198 @param bottom edge of bounds on y-axis 199 @return rectangular SkRegion 200 */ setRect(int32_t left,int32_t top,int32_t right,int32_t bottom)201 bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) { 202 return this->setRect({ left, top, right, bottom }); 203 } 204 205 /** Constructs SkRegion as the union of SkIRect in rects array. If count is 206 zero, constructs empty SkRegion. Returns false if constructed SkRegion is empty. 207 208 May be faster than repeated calls to op(). 209 210 @param rects array of SkIRect 211 @param count array size 212 @return true if constructed SkRegion is not empty 213 */ 214 bool setRects(const SkIRect rects[], int count); 215 216 /** Constructs a copy of an existing region. 217 Makes two regions identical by value. Internally, region and 218 the returned result share pointer values. The underlying SkRect array is 219 copied when modified. 220 221 Creating a SkRegion copy is very efficient and never allocates memory. 222 SkRegion are always copied by value from the interface; the underlying shared 223 pointers are not exposed. 224 225 @param region SkRegion to copy by value 226 @return SkRegion to copy by value 227 */ 228 bool setRegion(const SkRegion& region); 229 230 /** Constructs SkRegion to match outline of path within clip. 231 Returns false if constructed SkRegion is empty. 232 233 Constructed SkRegion draws the same pixels as path through clip when 234 anti-aliasing is disabled. 235 236 @param path SkPath providing outline 237 @param clip SkRegion containing path 238 @return true if constructed SkRegion is not empty 239 */ 240 bool setPath(const SkPath& path, const SkRegion& clip); 241 242 /** Returns true if SkRegion intersects rect. 243 Returns false if either rect or SkRegion is empty, or do not intersect. 244 245 @param rect SkIRect to intersect 246 @return true if rect and SkRegion have area in common 247 */ 248 bool intersects(const SkIRect& rect) const; 249 250 /** Returns true if SkRegion intersects other. 251 Returns false if either other or SkRegion is empty, or do not intersect. 252 253 @param other SkRegion to intersect 254 @return true if other and SkRegion have area in common 255 */ 256 bool intersects(const SkRegion& other) const; 257 258 /** Returns true if SkIPoint (x, y) is inside SkRegion. 259 Returns false if SkRegion is empty. 260 261 @param x test SkIPoint x-coordinate 262 @param y test SkIPoint y-coordinate 263 @return true if (x, y) is inside SkRegion 264 */ 265 bool contains(int32_t x, int32_t y) const; 266 267 /** Returns true if other is completely inside SkRegion. 268 Returns false if SkRegion or other is empty. 269 270 @param other SkIRect to contain 271 @return true if other is inside SkRegion 272 */ 273 bool contains(const SkIRect& other) const; 274 275 /** Returns true if other is completely inside SkRegion. 276 Returns false if SkRegion or other is empty. 277 278 @param other SkRegion to contain 279 @return true if other is inside SkRegion 280 */ 281 bool contains(const SkRegion& other) const; 282 283 /** Returns true if SkRegion is a single rectangle and contains r. 284 May return false even though SkRegion contains r. 285 286 @param r SkIRect to contain 287 @return true quickly if r points are equal or inside 288 */ quickContains(const SkIRect & r)289 bool quickContains(const SkIRect& r) const { 290 return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom); 291 } 292 293 /** Returns true if SkRegion is a single rectangle and contains SkIRect 294 (left, top, right, bottom). 295 Returns false if SkRegion is empty or SkIRect (left, top, right, bottom) is empty. 296 May return false even though SkRegion contains (left, top, right, bottom). 297 298 @param left edge of bounds on x-axis 299 @param top edge of bounds on y-axis 300 @param right edge of bounds on x-axis 301 @param bottom edge of bounds on y-axis 302 @return true quickly if SkIRect are equal or inside 303 */ quickContains(int32_t left,int32_t top,int32_t right,int32_t bottom)304 bool quickContains(int32_t left, int32_t top, int32_t right, 305 int32_t bottom) const { 306 SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region 307 308 return left < right && top < bottom && 309 fRunHead == kRectRunHeadPtr && // this->isRect() 310 /* fBounds.contains(left, top, right, bottom); */ 311 fBounds.fLeft <= left && fBounds.fTop <= top && 312 fBounds.fRight >= right && fBounds.fBottom >= bottom; 313 } 314 315 /** Returns true if SkRegion does not intersect rect. 316 Returns true if rect is empty or SkRegion is empty. 317 May return false even though SkRegion does not intersect rect. 318 319 @param rect SkIRect to intersect 320 @return true if rect does not intersect 321 */ quickReject(const SkIRect & rect)322 bool quickReject(const SkIRect& rect) const { 323 return this->isEmpty() || rect.isEmpty() || 324 !SkIRect::Intersects(fBounds, rect); 325 } 326 327 /** Returns true if SkRegion does not intersect rgn. 328 Returns true if rgn is empty or SkRegion is empty. 329 May return false even though SkRegion does not intersect rgn. 330 331 @param rgn SkRegion to intersect 332 @return true if rgn does not intersect 333 */ quickReject(const SkRegion & rgn)334 bool quickReject(const SkRegion& rgn) const { 335 return this->isEmpty() || rgn.isEmpty() || 336 !SkIRect::Intersects(fBounds, rgn.fBounds); 337 } 338 339 /** Offsets SkRegion by ivector (dx, dy). Has no effect if SkRegion is empty. 340 341 @param dx x-axis offset 342 @param dy y-axis offset 343 */ translate(int dx,int dy)344 void translate(int dx, int dy) { this->translate(dx, dy, this); } 345 346 /** Offsets SkRegion by ivector (dx, dy), writing result to dst. SkRegion may be passed 347 as dst parameter, translating SkRegion in place. Has no effect if dst is nullptr. 348 If SkRegion is empty, sets dst to empty. 349 350 @param dx x-axis offset 351 @param dy y-axis offset 352 @param dst translated result 353 */ 354 void translate(int dx, int dy, SkRegion* dst) const; 355 356 /** \enum SkRegion::Op 357 The logical operations that can be performed when combining two SkRegion. 358 */ 359 enum Op { 360 kDifference_Op, //!< target minus operand 361 kIntersect_Op, //!< target intersected with operand 362 kUnion_Op, //!< target unioned with operand 363 kXOR_Op, //!< target exclusive or with operand 364 kReverseDifference_Op, //!< operand minus target 365 kReplace_Op, //!< replace target with operand 366 kLastOp = kReplace_Op, //!< last operator 367 }; 368 369 static const int kOpCnt = kLastOp + 1; 370 371 /** Replaces SkRegion with the result of SkRegion op rect. 372 Returns true if replaced SkRegion is not empty. 373 374 @param rect SkIRect operand 375 @param op operator, one of: 376 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 377 kReplace_Op 378 @return false if result is empty 379 */ op(const SkIRect & rect,Op op)380 bool op(const SkIRect& rect, Op op) { 381 if (this->isRect() && kIntersect_Op == op) { 382 if (!fBounds.intersect(rect)) { 383 return this->setEmpty(); 384 } 385 return true; 386 } 387 return this->op(*this, rect, op); 388 } 389 390 /** Replaces SkRegion with the result of SkRegion op SkIRect (left, top, right, bottom). 391 Returns true if replaced SkRegion is not empty. 392 393 @param left edge of bounds on x-axis 394 @param top edge of bounds on y-axis 395 @param right edge of bounds on x-axis 396 @param bottom edge of bounds on y-axis 397 @param op operator, one of: 398 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 399 kReplace_Op 400 @return false if result is empty 401 */ op(int left,int top,int right,int bottom,Op op)402 bool op(int left, int top, int right, int bottom, Op op) { 403 SkIRect rect; 404 rect.set(left, top, right, bottom); 405 return this->op(*this, rect, op); 406 } 407 408 /** Replaces SkRegion with the result of SkRegion op rgn. 409 Returns true if replaced SkRegion is not empty. 410 411 @param rgn SkRegion operand 412 @param op operator, one of: 413 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 414 kReplace_Op 415 @return false if result is empty 416 */ op(const SkRegion & rgn,Op op)417 bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); } 418 419 /** Replaces SkRegion with the result of rect op rgn. 420 Returns true if replaced SkRegion is not empty. 421 422 @param rect SkIRect operand 423 @param rgn SkRegion operand 424 @param op operator, one of: 425 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 426 kReplace_Op 427 @return false if result is empty 428 */ 429 bool op(const SkIRect& rect, const SkRegion& rgn, Op op); 430 431 /** Replaces SkRegion with the result of rgn op rect. 432 Returns true if replaced SkRegion is not empty. 433 434 @param rgn SkRegion operand 435 @param rect SkIRect operand 436 @param op operator, one of: 437 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 438 kReplace_Op 439 @return false if result is empty 440 */ 441 bool op(const SkRegion& rgn, const SkIRect& rect, Op op); 442 443 /** Replaces SkRegion with the result of rgna op rgnb. 444 Returns true if replaced SkRegion is not empty. 445 446 @param rgna SkRegion operand 447 @param rgnb SkRegion operand 448 @param op operator, one of: 449 kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op, 450 kReplace_Op 451 @return false if result is empty 452 */ 453 bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op); 454 455 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 456 /** Private. Android framework only. 457 458 @return string representation of SkRegion 459 */ 460 char* toString(); 461 #endif 462 463 /** \class SkRegion::Iterator 464 Returns sequence of rectangles, sorted along y-axis, then x-axis, that make 465 up SkRegion. 466 */ 467 class SK_API Iterator { 468 public: 469 470 /** Initializes SkRegion::Iterator with an empty SkRegion. done() on SkRegion::Iterator 471 returns true. 472 Call reset() to initialized SkRegion::Iterator at a later time. 473 474 @return empty SkRegion iterator 475 */ Iterator()476 Iterator() : fRgn(nullptr), fDone(true) {} 477 478 /** Sets SkRegion::Iterator to return elements of SkIRect array in region. 479 480 @param region SkRegion to iterate 481 @return SkRegion iterator 482 */ 483 Iterator(const SkRegion& region); 484 485 /** SkPoint SkRegion::Iterator to start of SkRegion. 486 Returns true if SkRegion was set; otherwise, returns false. 487 488 @return true if SkRegion was set 489 */ 490 bool rewind(); 491 492 /** Resets iterator, using the new SkRegion. 493 494 @param region SkRegion to iterate 495 */ 496 void reset(const SkRegion& region); 497 498 /** Returns true if SkRegion::Iterator is pointing to final SkIRect in SkRegion. 499 500 @return true if data parsing is complete 501 */ done()502 bool done() const { return fDone; } 503 504 /** Advances SkRegion::Iterator to next SkIRect in SkRegion if it is not done. 505 */ 506 void next(); 507 508 /** Returns SkIRect element in SkRegion. Does not return predictable results if SkRegion 509 is empty. 510 511 @return part of SkRegion as SkIRect 512 */ rect()513 const SkIRect& rect() const { return fRect; } 514 515 /** Returns SkRegion if set; otherwise, returns nullptr. 516 517 @return iterated SkRegion 518 */ rgn()519 const SkRegion* rgn() const { return fRgn; } 520 521 private: 522 const SkRegion* fRgn; 523 const SkRegion::RunType* fRuns; 524 SkIRect fRect = {0, 0, 0, 0}; 525 bool fDone; 526 }; 527 528 /** \class SkRegion::Cliperator 529 Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make 530 up SkRegion intersected with the specified clip rectangle. 531 */ 532 class SK_API Cliperator { 533 public: 534 535 /** Sets SkRegion::Cliperator to return elements of SkIRect array in SkRegion within clip. 536 537 @param region SkRegion to iterate 538 @param clip bounds of iteration 539 @return SkRegion iterator 540 */ 541 Cliperator(const SkRegion& region, const SkIRect& clip); 542 543 /** Returns true if SkRegion::Cliperator is pointing to final SkIRect in SkRegion. 544 545 @return true if data parsing is complete 546 */ done()547 bool done() { return fDone; } 548 549 /** Advances iterator to next SkIRect in SkRegion contained by clip. 550 */ 551 void next(); 552 553 /** Returns SkIRect element in SkRegion, intersected with clip passed to 554 SkRegion::Cliperator constructor. Does not return predictable results if SkRegion 555 is empty. 556 557 @return part of SkRegion inside clip as SkIRect 558 */ rect()559 const SkIRect& rect() const { return fRect; } 560 561 private: 562 Iterator fIter; 563 SkIRect fClip; 564 SkIRect fRect = {0, 0, 0, 0}; 565 bool fDone; 566 }; 567 568 /** \class SkRegion::Spanerator 569 Returns the line segment ends within SkRegion that intersect a horizontal line. 570 */ 571 class Spanerator { 572 public: 573 574 /** Sets SkRegion::Spanerator to return line segments in SkRegion on scan line. 575 576 @param region SkRegion to iterate 577 @param y horizontal line to intersect 578 @param left bounds of iteration 579 @param right bounds of iteration 580 @return SkRegion iterator 581 */ 582 Spanerator(const SkRegion& region, int y, int left, int right); 583 584 /** Advances iterator to next span intersecting SkRegion within line segment provided 585 in constructor. Returns true if interval was found. 586 587 @param left pointer to span start; may be nullptr 588 @param right pointer to span end; may be nullptr 589 @return true if interval was found 590 */ 591 bool next(int* left, int* right); 592 593 private: 594 const SkRegion::RunType* fRuns; 595 int fLeft, fRight; 596 bool fDone; 597 }; 598 599 /** Writes SkRegion to buffer, and returns number of bytes written. 600 If buffer is nullptr, returns number number of bytes that would be written. 601 602 @param buffer storage for binary data 603 @return size of SkRegion 604 */ 605 size_t writeToMemory(void* buffer) const; 606 607 /** Constructs SkRegion from buffer of size length. Returns bytes read. 608 Returned value will be multiple of four or zero if length was too small. 609 610 @param buffer storage for binary data 611 @param length size of buffer 612 @return bytes read 613 */ 614 size_t readFromMemory(const void* buffer, size_t length); 615 616 private: 617 static constexpr int kOpCount = kReplace_Op + 1; 618 619 // T 620 // [B N L R S] 621 // S 622 static constexpr int kRectRegionRuns = 7; 623 624 struct RunHead; 625 emptyRunHeadPtr()626 static RunHead* emptyRunHeadPtr() { return (SkRegion::RunHead*) -1; } 627 static constexpr RunHead* kRectRunHeadPtr = nullptr; 628 629 // allocate space for count runs 630 void allocateRuns(int count); 631 void allocateRuns(int count, int ySpanCount, int intervalCount); 632 void allocateRuns(const RunHead& src); 633 634 SkDEBUGCODE(void dump() const;) 635 636 SkIRect fBounds; 637 RunHead* fRunHead; 638 639 void freeRuns(); 640 641 /** 642 * Return the runs from this region, consing up fake runs if the region 643 * is empty or a rect. In those 2 cases, we use tmpStorage to hold the 644 * run data. 645 */ 646 const RunType* getRuns(RunType tmpStorage[], int* intervals) const; 647 648 // This is called with runs[] that do not yet have their interval-count 649 // field set on each scanline. That is computed as part of this call 650 // (inside ComputeRunBounds). 651 bool setRuns(RunType runs[], int count); 652 653 int count_runtype_values(int* itop, int* ibot) const; 654 655 bool isValid() const; 656 657 static void BuildRectRuns(const SkIRect& bounds, 658 RunType runs[kRectRegionRuns]); 659 660 // If the runs define a simple rect, return true and set bounds to that 661 // rect. If not, return false and ignore bounds. 662 static bool RunsAreARect(const SkRegion::RunType runs[], int count, 663 SkIRect* bounds); 664 665 /** 666 * If the last arg is null, just return if the result is non-empty, 667 * else store the result in the last arg. 668 */ 669 static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*); 670 671 friend struct RunHead; 672 friend class Iterator; 673 friend class Spanerator; 674 friend class SkRegionPriv; 675 friend class SkRgnBuilder; 676 friend class SkFlatRegion; 677 }; 678 679 #endif 680