SkRegion.cpp revision 0a0a236c3ba241046d38caaf78226ec68ff9c998
1/* libs/corecg/SkRegion.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkRegionPriv.h" 19#include "SkTemplates.h" 20#include "SkThread.h" 21 22#ifdef ANDROID 23#include <stdio.h> 24#endif 25 26SkDEBUGCODE(int32_t gRgnAllocCounter;) 27 28///////////////////////////////////////////////////////////////////////////////////////////////// 29 30/* Pass in a scanline, beginning with the Left value of the pair (i.e. not the Y beginning) 31*/ 32static SkRegion::RunType* skip_scanline(const SkRegion::RunType runs[]) 33{ 34 while (runs[0] != SkRegion::kRunTypeSentinel) 35 { 36 SkASSERT(runs[0] < runs[1]); // valid span 37 runs += 2; 38 } 39 return (SkRegion::RunType*)(runs + 1); // return past the X-sentinel 40} 41 42// returns true if runs are just a rect 43bool SkRegion::ComputeRunBounds(const SkRegion::RunType runs[], int count, SkIRect* bounds) 44{ 45 assert_sentinel(runs[0], false); // top 46 47 if (count == kRectRegionRuns) 48 { 49 assert_sentinel(runs[1], false); // bottom 50 assert_sentinel(runs[2], false); // left 51 assert_sentinel(runs[3], false); // right 52 assert_sentinel(runs[4], true); 53 assert_sentinel(runs[5], true); 54 55 SkASSERT(runs[0] < runs[1]); // valid height 56 SkASSERT(runs[2] < runs[3]); // valid width 57 58 bounds->set(runs[2], runs[0], runs[3], runs[1]); 59 return true; 60 } 61 62 int left = SK_MaxS32; 63 int rite = SK_MinS32; 64 int bot; 65 66 bounds->fTop = *runs++; 67 do { 68 bot = *runs++; 69 if (*runs < SkRegion::kRunTypeSentinel) 70 { 71 if (left > *runs) 72 left = *runs; 73 runs = skip_scanline(runs); 74 if (rite < runs[-2]) 75 rite = runs[-2]; 76 } 77 else 78 runs += 1; // skip X-sentinel 79 } while (runs[0] < SkRegion::kRunTypeSentinel); 80 bounds->fLeft = left; 81 bounds->fRight = rite; 82 bounds->fBottom = bot; 83 return false; 84} 85 86////////////////////////////////////////////////////////////////////////// 87 88SkRegion::SkRegion() { 89 fBounds.set(0, 0, 0, 0); 90 fRunHead = SkRegion_gEmptyRunHeadPtr; 91} 92 93SkRegion::SkRegion(const SkRegion& src) { 94 fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 95 this->setRegion(src); 96} 97 98SkRegion::SkRegion(const SkIRect& rect) { 99 fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 100 this->setRect(rect); 101} 102 103SkRegion::~SkRegion() { 104 this->freeRuns(); 105} 106 107void SkRegion::freeRuns() { 108 if (fRunHead->isComplex()) { 109 SkASSERT(fRunHead->fRefCnt >= 1); 110 if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) { 111 //SkASSERT(gRgnAllocCounter > 0); 112 //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter)); 113 //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter)); 114 sk_free(fRunHead); 115 } 116 } 117} 118 119void SkRegion::allocateRuns(int count) { 120 fRunHead = RunHead::Alloc(count); 121} 122 123SkRegion& SkRegion::operator=(const SkRegion& src) { 124 (void)this->setRegion(src); 125 return *this; 126} 127 128void SkRegion::swap(SkRegion& other) { 129 SkTSwap<SkIRect>(fBounds, other.fBounds); 130 SkTSwap<RunHead*>(fRunHead, other.fRunHead); 131} 132 133bool SkRegion::setEmpty() { 134 this->freeRuns(); 135 fBounds.set(0, 0, 0, 0); 136 fRunHead = SkRegion_gEmptyRunHeadPtr; 137 return false; 138} 139 140bool SkRegion::setRect(int32_t left, int32_t top, 141 int32_t right, int32_t bottom) { 142 if (left >= right || top >= bottom) { 143 return this->setEmpty(); 144 } 145 this->freeRuns(); 146 fBounds.set(left, top, right, bottom); 147 fRunHead = SkRegion_gRectRunHeadPtr; 148 return true; 149} 150 151bool SkRegion::setRect(const SkIRect& r) { 152 return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom); 153} 154 155bool SkRegion::setRegion(const SkRegion& src) { 156 if (this != &src) { 157 this->freeRuns(); 158 159 fBounds = src.fBounds; 160 fRunHead = src.fRunHead; 161 if (fRunHead->isComplex()) { 162 sk_atomic_inc(&fRunHead->fRefCnt); 163 } 164 } 165 return fRunHead != SkRegion_gEmptyRunHeadPtr; 166} 167 168bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) { 169 SkRegion tmp(rect); 170 171 return this->op(tmp, rgn, op); 172} 173 174bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) { 175 SkRegion tmp(rect); 176 177 return this->op(rgn, tmp, op); 178} 179 180/////////////////////////////////////////////////////////////////////////////// 181 182#ifdef ANDROID 183char* SkRegion::toString() 184{ 185 Iterator iter(*this); 186 int count = 0; 187 while (!iter.done()) { 188 count++; 189 iter.next(); 190 } 191 // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0' 192 const int max = (count*((11*4)+5))+11+1; 193 char* result = (char*)malloc(max); 194 if (result == NULL) { 195 return NULL; 196 } 197 count = sprintf(result, "SkRegion("); 198 iter.reset(*this); 199 while (!iter.done()) { 200 const SkIRect& r = iter.rect(); 201 count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom); 202 iter.next(); 203 } 204 count += sprintf(result+count, ")"); 205 return result; 206} 207#endif 208 209////////////////////////////////////////////////////////////////////////////////////// 210 211int SkRegion::count_runtype_values(int* itop, int* ibot) const 212{ 213 if (this == NULL) 214 { 215 *itop = SK_MinS32; 216 *ibot = SK_MaxS32; 217 return 0; 218 } 219 220 int maxT; 221 222 if (this->isRect()) 223 maxT = 2; 224 else 225 { 226 SkASSERT(this->isComplex()); 227 // skip the top 228 const RunType* runs = fRunHead->readonly_runs() + 1; 229 maxT = 0; 230 231 do { 232 const RunType* next = skip_scanline(runs + 1); 233 SkASSERT(next > runs); 234 int T = (int)(next - runs - 1); 235 if (maxT < T) 236 maxT = T; 237 runs = next; 238 } while (runs[0] < SkRegion::kRunTypeSentinel); 239 } 240 *itop = fBounds.fTop; 241 *ibot = fBounds.fBottom; 242 return maxT; 243} 244 245bool SkRegion::setRuns(RunType runs[], int count) 246{ 247 SkDEBUGCODE(this->validate();) 248 SkASSERT(count > 0); 249 250 if (count <= 2) 251 { 252 // SkDEBUGF(("setRuns: empty\n")); 253 assert_sentinel(runs[count-1], true); 254 return this->setEmpty(); 255 } 256 257 // trim off any empty spans from the top and bottom 258 // weird I should need this, perhaps op() could be smarter... 259 if (count > kRectRegionRuns) 260 { 261 RunType* stop = runs + count; 262 assert_sentinel(runs[0], false); // top 263 assert_sentinel(runs[1], false); // bottom 264 if (runs[2] == SkRegion::kRunTypeSentinel) // should be first left... 265 { 266 runs += 2; // skip empty initial span 267 runs[0] = runs[-1]; // set new top to prev bottom 268 assert_sentinel(runs[1], false); // bot: a sentinal would mean two in a row 269 assert_sentinel(runs[2], false); // left 270 assert_sentinel(runs[3], false); // right 271 } 272 273 // now check for a trailing empty span 274 assert_sentinel(stop[-1], true); 275 assert_sentinel(stop[-2], true); 276 assert_sentinel(stop[-3], false); // should be last right 277 if (stop[-4] == SkRegion::kRunTypeSentinel) // eek, stop[-3] was a bottom with no x-runs 278 { 279 stop[-3] = SkRegion::kRunTypeSentinel; // kill empty last span 280 stop -= 2; 281 assert_sentinel(stop[-1], true); 282 assert_sentinel(stop[-2], true); 283 assert_sentinel(stop[-3], false); 284 assert_sentinel(stop[-4], false); 285 assert_sentinel(stop[-5], false); 286 } 287 count = (int)(stop - runs); 288 } 289 290 SkASSERT(count >= kRectRegionRuns); 291 292 if (ComputeRunBounds(runs, count, &fBounds)) 293 { 294 // SkDEBUGF(("setRuns: rect[%d %d %d %d]\n", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom)); 295 return this->setRect(fBounds); 296 } 297 298 // if we get here, we need to become a complex region 299 300 if (!fRunHead->isComplex() || fRunHead->fRunCount != count) 301 { 302#ifdef SK_DEBUGx 303 SkDebugf("setRuns: rgn ["); 304 { 305 const RunType* r = runs; 306 307 SkDebugf(" top: %d\n", *r++); 308 while (*r < SkRegion::kRunTypeSentinel) 309 { 310 SkDebugf(" bottom: %d", *r++); 311 while (*r < SkRegion::kRunTypeSentinel) 312 { 313 SkDebugf(" [%d %d]", r[0], r[1]); 314 r += 2; 315 } 316 SkDebugf("\n"); 317 } 318 } 319#endif 320 this->freeRuns(); 321 this->allocateRuns(count); 322 } 323 324 // must call this before we can write directly into runs() 325 // in case we are sharing the buffer with another region (copy on write) 326 fRunHead = fRunHead->ensureWritable(); 327 memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType)); 328 329 SkDEBUGCODE(this->validate();) 330 331 return true; 332} 333 334void SkRegion::BuildRectRuns(const SkIRect& bounds, 335 RunType runs[kRectRegionRuns]) 336{ 337 runs[0] = bounds.fTop; 338 runs[1] = bounds.fBottom; 339 runs[2] = bounds.fLeft; 340 runs[3] = bounds.fRight; 341 runs[4] = kRunTypeSentinel; 342 runs[5] = kRunTypeSentinel; 343} 344 345static SkRegion::RunType* find_scanline(const SkRegion::RunType runs[], int y) 346{ 347 SkASSERT(y >= runs[0]); // if this fails, we didn't do a quick check on the boudns 348 349 runs += 1; // skip top-Y 350 for (;;) 351 { 352 if (runs[0] == SkRegion::kRunTypeSentinel) 353 break; 354 if (y < runs[0]) 355 return (SkRegion::RunType*)&runs[1]; 356 runs = skip_scanline(runs + 1); // skip the Y value before calling 357 } 358 return NULL; 359} 360 361bool SkRegion::contains(int32_t x, int32_t y) const 362{ 363 if (!fBounds.contains(x, y)) 364 return false; 365 366 if (this->isRect()) 367 return true; 368 369 SkASSERT(this->isComplex()); 370 const RunType* runs = find_scanline(fRunHead->readonly_runs(), y); 371 372 if (runs) 373 { for (;;) 374 { if (x < runs[0]) 375 break; 376 if (x < runs[1]) 377 return true; 378 runs += 2; 379 } 380 } 381 return false; 382} 383 384bool SkRegion::contains(const SkIRect& r) const 385{ 386 SkRegion tmp(r); 387 388 return this->contains(tmp); 389} 390 391bool SkRegion::contains(const SkRegion& rgn) const 392{ 393 if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds)) 394 return false; 395 396 if (this->isRect()) 397 return true; 398 399 SkRegion tmp; 400 401 tmp.op(*this, rgn, kUnion_Op); 402 return tmp == *this; 403} 404 405const SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], int* count) const 406{ 407 SkASSERT(tmpStorage && count); 408 const RunType* runs = tmpStorage; 409 410 if (this->isEmpty()) 411 { 412 tmpStorage[0] = kRunTypeSentinel; 413 *count = 1; 414 } 415 else if (this->isRect()) 416 { 417 BuildRectRuns(fBounds, tmpStorage); 418 *count = kRectRegionRuns; 419 } 420 else 421 { 422 *count = fRunHead->fRunCount; 423 runs = fRunHead->readonly_runs(); 424 } 425 return runs; 426} 427 428///////////////////////////////////////////////////////////////////////////////////// 429 430bool SkRegion::intersects(const SkIRect& r) const { 431 if (this->isEmpty() || r.isEmpty()) { 432 return false; 433 } 434 435 if (!SkIRect::Intersects(fBounds, r)) { 436 return false; 437 } 438 439 if (this->isRect()) { 440 return true; 441 } 442 443 // we are complex 444 SkRegion tmp; 445 return tmp.op(*this, r, kIntersect_Op); 446} 447 448bool SkRegion::intersects(const SkRegion& rgn) const { 449 if (this->isEmpty() || rgn.isEmpty()) { 450 return false; 451 } 452 453 if (!SkIRect::Intersects(fBounds, rgn.fBounds)) { 454 return false; 455 } 456 457 if (this->isRect() && rgn.isRect()) { 458 return true; 459 } 460 461 // one or both of us is complex 462 // TODO: write a faster version that aborts as soon as we write the first 463 // non-empty span, to avoid build the entire result 464 SkRegion tmp; 465 return tmp.op(*this, rgn, kIntersect_Op); 466} 467 468///////////////////////////////////////////////////////////////////////////////////// 469 470bool operator==(const SkRegion& a, const SkRegion& b) { 471 SkDEBUGCODE(a.validate();) 472 SkDEBUGCODE(b.validate();) 473 474 if (&a == &b) { 475 return true; 476 } 477 if (a.fBounds != b.fBounds) { 478 return false; 479 } 480 481 const SkRegion::RunHead* ah = a.fRunHead; 482 const SkRegion::RunHead* bh = b.fRunHead; 483 484 // this catches empties and rects being equal 485 if (ah == bh) { 486 return true; 487 } 488 // now we insist that both are complex (but different ptrs) 489 if (!ah->isComplex() || !bh->isComplex()) { 490 return false; 491 } 492 return ah->fRunCount == bh->fRunCount && 493 !memcmp(ah->readonly_runs(), bh->readonly_runs(), 494 ah->fRunCount * sizeof(SkRegion::RunType)); 495} 496 497void SkRegion::translate(int dx, int dy, SkRegion* dst) const { 498 SkDEBUGCODE(this->validate();) 499 500 if (NULL == dst) { 501 return; 502 } 503 if (this->isEmpty()) { 504 dst->setEmpty(); 505 } else if (this->isRect()) { 506 dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, 507 fBounds.fRight + dx, fBounds.fBottom + dy); 508 } else { 509 if (this == dst) { 510 dst->fRunHead = dst->fRunHead->ensureWritable(); 511 } else { 512 SkRegion tmp; 513 tmp.allocateRuns(fRunHead->fRunCount); 514 tmp.fBounds = fBounds; 515 dst->swap(tmp); 516 } 517 518 dst->fBounds.offset(dx, dy); 519 520 const RunType* sruns = fRunHead->readonly_runs(); 521 RunType* druns = dst->fRunHead->writable_runs(); 522 523 *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top 524 for (;;) { 525 int bottom = *sruns++; 526 if (bottom == kRunTypeSentinel) { 527 break; 528 } 529 *druns++ = (SkRegion::RunType)(bottom + dy); // bottom; 530 for (;;) { 531 int x = *sruns++; 532 if (x == kRunTypeSentinel) { 533 break; 534 } 535 *druns++ = (SkRegion::RunType)(x + dx); 536 *druns++ = (SkRegion::RunType)(*sruns++ + dx); 537 } 538 *druns++ = kRunTypeSentinel; // x sentinel 539 } 540 *druns++ = kRunTypeSentinel; // y sentinel 541 542 SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount); 543 SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount); 544 } 545 546 SkDEBUGCODE(this->validate();) 547} 548 549/////////////////////////////////////////////////////////////////////////////// 550 551bool SkRegion::setRects(const SkIRect rects[], int count) { 552 if (0 == count) { 553 this->setEmpty(); 554 } else { 555 this->setRect(rects[0]); 556 for (int i = 1; i < count; i++) { 557 this->op(rects[i], kUnion_Op); 558 } 559 } 560 return !this->isEmpty(); 561} 562 563/////////////////////////////////////////////////////////////////////////////// 564 565#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 566#pragma warning ( push ) 567#pragma warning ( disable : 4701 ) 568#endif 569 570#ifdef SK_DEBUG 571static void assert_valid_pair(int left, int rite) 572{ 573 SkASSERT(left == SkRegion::kRunTypeSentinel || left < rite); 574} 575#else 576 #define assert_valid_pair(left, rite) 577#endif 578 579struct spanRec { 580 const SkRegion::RunType* fA_runs; 581 const SkRegion::RunType* fB_runs; 582 int fA_left, fA_rite, fB_left, fB_rite; 583 int fLeft, fRite, fInside; 584 585 void init(const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[]) 586 { 587 fA_left = *a_runs++; 588 fA_rite = *a_runs++; 589 fB_left = *b_runs++; 590 fB_rite = *b_runs++; 591 592 fA_runs = a_runs; 593 fB_runs = b_runs; 594 } 595 596 bool done() const 597 { 598 SkASSERT(fA_left <= SkRegion::kRunTypeSentinel); 599 SkASSERT(fB_left <= SkRegion::kRunTypeSentinel); 600 return fA_left == SkRegion::kRunTypeSentinel && fB_left == SkRegion::kRunTypeSentinel; 601 } 602 603 void next() 604 { 605 assert_valid_pair(fA_left, fA_rite); 606 assert_valid_pair(fB_left, fB_rite); 607 608 int inside, left, rite SK_INIT_TO_AVOID_WARNING; 609 bool a_flush = false; 610 bool b_flush = false; 611 612 int a_left = fA_left; 613 int a_rite = fA_rite; 614 int b_left = fB_left; 615 int b_rite = fB_rite; 616 617 if (a_left < b_left) 618 { 619 inside = 1; 620 left = a_left; 621 if (a_rite <= b_left) // [...] <...> 622 { 623 rite = a_rite; 624 a_flush = true; 625 } 626 else // [...<..]...> or [...<...>...] 627 rite = a_left = b_left; 628 } 629 else if (b_left < a_left) 630 { 631 inside = 2; 632 left = b_left; 633 if (b_rite <= a_left) // [...] <...> 634 { 635 rite = b_rite; 636 b_flush = true; 637 } 638 else // [...<..]...> or [...<...>...] 639 rite = b_left = a_left; 640 } 641 else // a_left == b_left 642 { 643 inside = 3; 644 left = a_left; // or b_left 645 if (a_rite <= b_rite) 646 { 647 rite = b_left = a_rite; 648 a_flush = true; 649 } 650 if (b_rite <= a_rite) 651 { 652 rite = a_left = b_rite; 653 b_flush = true; 654 } 655 } 656 657 if (a_flush) 658 { 659 a_left = *fA_runs++; 660 a_rite = *fA_runs++; 661 } 662 if (b_flush) 663 { 664 b_left = *fB_runs++; 665 b_rite = *fB_runs++; 666 } 667 668 SkASSERT(left <= rite); 669 670 // now update our state 671 fA_left = a_left; 672 fA_rite = a_rite; 673 fB_left = b_left; 674 fB_rite = b_rite; 675 676 fLeft = left; 677 fRite = rite; 678 fInside = inside; 679 } 680}; 681 682static SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[], 683 const SkRegion::RunType b_runs[], 684 SkRegion::RunType dst[], 685 int min, int max) 686{ 687 spanRec rec; 688 bool firstInterval = true; 689 690 rec.init(a_runs, b_runs); 691 692 while (!rec.done()) 693 { 694 rec.next(); 695 696 int left = rec.fLeft; 697 int rite = rec.fRite; 698 699 // add left,rite to our dst buffer (checking for coincidence 700 if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) && 701 left < rite) // skip if equal 702 { 703 if (firstInterval || dst[-1] < left) 704 { 705 *dst++ = (SkRegion::RunType)(left); 706 *dst++ = (SkRegion::RunType)(rite); 707 firstInterval = false; 708 } 709 else // update the right edge 710 dst[-1] = (SkRegion::RunType)(rite); 711 } 712 } 713 714 *dst++ = SkRegion::kRunTypeSentinel; 715 return dst; 716} 717 718#if defined _WIN32 && _MSC_VER >= 1300 719#pragma warning ( pop ) 720#endif 721 722static const struct { 723 uint8_t fMin; 724 uint8_t fMax; 725} gOpMinMax[] = { 726 { 1, 1 }, // Difference 727 { 3, 3 }, // Intersection 728 { 1, 3 }, // Union 729 { 1, 2 } // XOR 730}; 731 732class RgnOper { 733public: 734 RgnOper(int top, SkRegion::RunType dst[], SkRegion::Op op) 735 { 736 // need to ensure that the op enum lines up with our minmax array 737 SkASSERT(SkRegion::kDifference_Op == 0); 738 SkASSERT(SkRegion::kIntersect_Op == 1); 739 SkASSERT(SkRegion::kUnion_Op == 2); 740 SkASSERT(SkRegion::kXOR_Op == 3); 741 SkASSERT((unsigned)op <= 3); 742 743 fStartDst = dst; 744 fPrevDst = dst + 1; 745 fPrevLen = 0; // will never match a length from operate_on_span 746 fTop = (SkRegion::RunType)(top); // just a first guess, we might update this 747 748 fMin = gOpMinMax[op].fMin; 749 fMax = gOpMinMax[op].fMax; 750 } 751 752 void addSpan(int bottom, const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[]) 753 { 754 SkRegion::RunType* start = fPrevDst + fPrevLen + 1; // skip X values and slot for the next Y 755 SkRegion::RunType* stop = operate_on_span(a_runs, b_runs, start, fMin, fMax); 756 size_t len = stop - start; 757 758 if (fPrevLen == len && !memcmp(fPrevDst, start, len * sizeof(SkRegion::RunType))) // update Y value 759 fPrevDst[-1] = (SkRegion::RunType)(bottom); 760 else // accept the new span 761 { 762 if (len == 1 && fPrevLen == 0) { 763 fTop = (SkRegion::RunType)(bottom); // just update our bottom 764 } else { 765 start[-1] = (SkRegion::RunType)(bottom); 766 fPrevDst = start; 767 fPrevLen = len; 768 } 769 } 770 } 771 772 int flush() 773 { 774 fStartDst[0] = fTop; 775 fPrevDst[fPrevLen] = SkRegion::kRunTypeSentinel; 776 return (int)(fPrevDst - fStartDst + fPrevLen + 1); 777 } 778 779 uint8_t fMin, fMax; 780 781private: 782 SkRegion::RunType* fStartDst; 783 SkRegion::RunType* fPrevDst; 784 size_t fPrevLen; 785 SkRegion::RunType fTop; 786}; 787 788static int operate( const SkRegion::RunType a_runs[], 789 const SkRegion::RunType b_runs[], 790 SkRegion::RunType dst[], 791 SkRegion::Op op) 792{ 793 const SkRegion::RunType gSentinel[] = { 794 SkRegion::kRunTypeSentinel, 795 // just need a 2nd value, since spanRec.init() reads 2 values, even 796 // though if the first value is the sentinel, it ignores the 2nd value. 797 // w/o the 2nd value here, we might read uninitialized memory. 798 0, 799 }; 800 801 int a_top = *a_runs++; 802 int a_bot = *a_runs++; 803 int b_top = *b_runs++; 804 int b_bot = *b_runs++; 805 806 assert_sentinel(a_top, false); 807 assert_sentinel(a_bot, false); 808 assert_sentinel(b_top, false); 809 assert_sentinel(b_bot, false); 810 811 RgnOper oper(SkMin32(a_top, b_top), dst, op); 812 813 bool firstInterval = true; 814 int prevBot = SkRegion::kRunTypeSentinel; // so we fail the first test 815 816 while (a_bot < SkRegion::kRunTypeSentinel || b_bot < SkRegion::kRunTypeSentinel) 817 { 818 int top, bot SK_INIT_TO_AVOID_WARNING; 819 const SkRegion::RunType* run0 = gSentinel; 820 const SkRegion::RunType* run1 = gSentinel; 821 bool a_flush = false; 822 bool b_flush = false; 823 int inside; 824 825 if (a_top < b_top) 826 { 827 inside = 1; 828 top = a_top; 829 run0 = a_runs; 830 if (a_bot <= b_top) // [...] <...> 831 { 832 bot = a_bot; 833 a_flush = true; 834 } 835 else // [...<..]...> or [...<...>...] 836 bot = a_top = b_top; 837 } 838 else if (b_top < a_top) 839 { 840 inside = 2; 841 top = b_top; 842 run1 = b_runs; 843 if (b_bot <= a_top) // [...] <...> 844 { 845 bot = b_bot; 846 b_flush = true; 847 } 848 else // [...<..]...> or [...<...>...] 849 bot = b_top = a_top; 850 } 851 else // a_top == b_top 852 { 853 inside = 3; 854 top = a_top; // or b_top 855 run0 = a_runs; 856 run1 = b_runs; 857 if (a_bot <= b_bot) 858 { 859 bot = b_top = a_bot; 860 a_flush = true; 861 } 862 if (b_bot <= a_bot) 863 { 864 bot = a_top = b_bot; 865 b_flush = true; 866 } 867 } 868 869 if (top > prevBot) 870 oper.addSpan(top, gSentinel, gSentinel); 871 872// if ((unsigned)(inside - oper.fMin) <= (unsigned)(oper.fMax - oper.fMin)) 873 { 874 oper.addSpan(bot, run0, run1); 875 firstInterval = false; 876 } 877 878 if (a_flush) 879 { 880 a_runs = skip_scanline(a_runs); 881 a_top = a_bot; 882 a_bot = *a_runs++; 883 if (a_bot == SkRegion::kRunTypeSentinel) 884 a_top = a_bot; 885 } 886 if (b_flush) 887 { 888 b_runs = skip_scanline(b_runs); 889 b_top = b_bot; 890 b_bot = *b_runs++; 891 if (b_bot == SkRegion::kRunTypeSentinel) 892 b_top = b_bot; 893 } 894 895 prevBot = bot; 896 } 897 return oper.flush(); 898} 899 900/////////////////////////////////////////////////////////////////////////////// 901 902/* Given count RunTypes in a complex region, return the worst case number of 903 logical intervals that represents (i.e. number of rects that would be 904 returned from the iterator). 905 906 We could just return count/2, since there must be at least 2 values per 907 interval, but we can first trim off the const overhead of the initial TOP 908 value, plus the final BOTTOM + 2 sentinels. 909 */ 910static int count_to_intervals(int count) { 911 SkASSERT(count >= 6); // a single rect is 6 values 912 return (count - 4) >> 1; 913} 914 915/* Given a number of intervals, what is the worst case representation of that 916 many intervals? 917 918 Worst case (from a storage perspective), is a vertical stack of single 919 intervals: TOP + N * (BOTTOM LEFT RIGHT SENTINEL) + SENTINEL 920 */ 921static int intervals_to_count(int intervals) { 922 return 1 + intervals * 4 + 1; 923} 924 925/* Given the counts of RunTypes in two regions, return the worst-case number 926 of RunTypes need to store the result after a region-op. 927 */ 928static int compute_worst_case_count(int a_count, int b_count) { 929 int a_intervals = count_to_intervals(a_count); 930 int b_intervals = count_to_intervals(b_count); 931 // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1) 932 int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals; 933 // convert back to number of RunType values 934 return intervals_to_count(intervals); 935} 936 937bool SkRegion::op(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op) 938{ 939 SkDEBUGCODE(this->validate();) 940 941 SkASSERT((unsigned)op < kOpCount); 942 943 if (kReplace_Op == op) 944 return this->set(rgnbOrig); 945 946 // swith to using pointers, so we can swap them as needed 947 const SkRegion* rgna = &rgnaOrig; 948 const SkRegion* rgnb = &rgnbOrig; 949 // after this point, do not refer to rgnaOrig or rgnbOrig!!! 950 951 // collaps difference and reverse-difference into just difference 952 if (kReverseDifference_Op == op) 953 { 954 SkTSwap<const SkRegion*>(rgna, rgnb); 955 op = kDifference_Op; 956 } 957 958 SkIRect bounds; 959 bool a_empty = rgna->isEmpty(); 960 bool b_empty = rgnb->isEmpty(); 961 bool a_rect = rgna->isRect(); 962 bool b_rect = rgnb->isRect(); 963 964 switch (op) { 965 case kDifference_Op: 966 if (a_empty) 967 return this->setEmpty(); 968 if (b_empty || !SkIRect::Intersects(rgna->fBounds, rgnb->fBounds)) 969 return this->setRegion(*rgna); 970 break; 971 972 case kIntersect_Op: 973 if ((a_empty | b_empty) 974 || !bounds.intersect(rgna->fBounds, rgnb->fBounds)) 975 return this->setEmpty(); 976 if (a_rect & b_rect) 977 return this->setRect(bounds); 978 break; 979 980 case kUnion_Op: 981 if (a_empty) 982 return this->setRegion(*rgnb); 983 if (b_empty) 984 return this->setRegion(*rgna); 985 if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) 986 return this->setRegion(*rgna); 987 if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) 988 return this->setRegion(*rgnb); 989 break; 990 991 case kXOR_Op: 992 if (a_empty) 993 return this->setRegion(*rgnb); 994 if (b_empty) 995 return this->setRegion(*rgna); 996 break; 997 default: 998 SkASSERT(!"unknown region op"); 999 return !this->isEmpty(); 1000 } 1001 1002 RunType tmpA[kRectRegionRuns]; 1003 RunType tmpB[kRectRegionRuns]; 1004 1005 int a_count, b_count; 1006 const RunType* a_runs = rgna->getRuns(tmpA, &a_count); 1007 const RunType* b_runs = rgnb->getRuns(tmpB, &b_count); 1008 1009 int dstCount = compute_worst_case_count(a_count, b_count); 1010 SkAutoSTMalloc<32, RunType> array(dstCount); 1011 1012 int count = operate(a_runs, b_runs, array.get(), op); 1013 SkASSERT(count <= dstCount); 1014 return this->setRuns(array.get(), count); 1015} 1016 1017////////////////////////////////////////////////////////////////////////////////////////////////////////// 1018 1019#include "SkBuffer.h" 1020 1021uint32_t SkRegion::flatten(void* storage) const { 1022 if (NULL == storage) { 1023 uint32_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount 1024 if (!this->isEmpty()) { 1025 size += sizeof(fBounds); 1026 if (this->isComplex()) { 1027 size += fRunHead->fRunCount * sizeof(RunType); 1028 } 1029 } 1030 return size; 1031 } 1032 1033 SkWBuffer buffer(storage); 1034 1035 if (this->isEmpty()) { 1036 buffer.write32(-1); 1037 } else { 1038 bool isRect = this->isRect(); 1039 1040 buffer.write32(isRect ? 0 : fRunHead->fRunCount); 1041 buffer.write(&fBounds, sizeof(fBounds)); 1042 1043 if (!isRect) { 1044 buffer.write(fRunHead->readonly_runs(), 1045 fRunHead->fRunCount * sizeof(RunType)); 1046 } 1047 } 1048 return buffer.pos(); 1049} 1050 1051uint32_t SkRegion::unflatten(const void* storage) { 1052 SkRBuffer buffer(storage); 1053 SkRegion tmp; 1054 int32_t count; 1055 1056 count = buffer.readS32(); 1057 if (count >= 0) { 1058 buffer.read(&tmp.fBounds, sizeof(tmp.fBounds)); 1059 if (count == 0) { 1060 tmp.fRunHead = SkRegion_gRectRunHeadPtr; 1061 } else { 1062 tmp.allocateRuns(count); 1063 buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType)); 1064 } 1065 } 1066 this->swap(tmp); 1067 return buffer.pos(); 1068} 1069 1070/////////////////////////////////////////////////////////////////////////////// 1071 1072const SkRegion& SkRegion::GetEmptyRegion() { 1073 static SkRegion gEmpty; 1074 return gEmpty; 1075} 1076 1077/////////////////////////////////////////////////////////////////////////////// 1078 1079#ifdef SK_DEBUG 1080 1081static const SkRegion::RunType* validate_line(const SkRegion::RunType run[], const SkIRect& bounds) 1082{ 1083 // *run is the bottom of the current span 1084 SkASSERT(*run > bounds.fTop); 1085 SkASSERT(*run <= bounds.fBottom); 1086 run += 1; 1087 1088 // check for empty span 1089 if (*run != SkRegion::kRunTypeSentinel) 1090 { 1091 int prevRite = bounds.fLeft - 1; 1092 do { 1093 int left = *run++; 1094 int rite = *run++; 1095 SkASSERT(left < rite); 1096 SkASSERT(left > prevRite); 1097 SkASSERT(rite <= bounds.fRight); 1098 prevRite = rite; 1099 } while (*run < SkRegion::kRunTypeSentinel); 1100 } 1101 return run + 1; // skip sentinel 1102} 1103 1104void SkRegion::validate() const 1105{ 1106 if (this->isEmpty()) 1107 { 1108 // check for explicit empty (the zero rect), so we can compare rects to know when 1109 // two regions are equal (i.e. emptyRectA == emptyRectB) 1110 // this is stricter than just asserting fBounds.isEmpty() 1111 SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0); 1112 } 1113 else 1114 { 1115 SkASSERT(!fBounds.isEmpty()); 1116 if (!this->isRect()) 1117 { 1118 SkASSERT(fRunHead->fRefCnt >= 1); 1119 SkASSERT(fRunHead->fRunCount >= kRectRegionRuns); 1120 1121 const RunType* run = fRunHead->readonly_runs(); 1122 const RunType* stop = run + fRunHead->fRunCount; 1123 1124 // check that our bounds match our runs 1125 { 1126 SkIRect bounds; 1127 bool isARect = ComputeRunBounds(run, stop - run, &bounds); 1128 SkASSERT(!isARect); 1129 SkASSERT(bounds == fBounds); 1130 } 1131 1132 SkASSERT(*run == fBounds.fTop); 1133 run++; 1134 do { 1135 run = validate_line(run, fBounds); 1136 } while (*run < kRunTypeSentinel); 1137 SkASSERT(run + 1 == stop); 1138 } 1139 } 1140} 1141 1142void SkRegion::dump() const 1143{ 1144 if (this->isEmpty()) 1145 SkDebugf(" rgn: empty\n"); 1146 else 1147 { 1148 SkDebugf(" rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 1149 if (this->isComplex()) 1150 { 1151 const RunType* runs = fRunHead->readonly_runs(); 1152 for (int i = 0; i < fRunHead->fRunCount; i++) 1153 SkDebugf(" %d", runs[i]); 1154 } 1155 SkDebugf("\n"); 1156 } 1157} 1158 1159#endif 1160 1161///////////////////////////////////////////////////////////////////////////////////// 1162 1163SkRegion::Iterator::Iterator(const SkRegion& rgn) { 1164 this->reset(rgn); 1165} 1166 1167bool SkRegion::Iterator::rewind() { 1168 if (fRgn) { 1169 this->reset(*fRgn); 1170 return true; 1171 } 1172 return false; 1173} 1174 1175void SkRegion::Iterator::reset(const SkRegion& rgn) { 1176 fRgn = &rgn; 1177 if (rgn.isEmpty()) { 1178 fDone = true; 1179 } else { 1180 fDone = false; 1181 if (rgn.isRect()) { 1182 fRect = rgn.fBounds; 1183 fRuns = NULL; 1184 } else { 1185 fRuns = rgn.fRunHead->readonly_runs(); 1186 fRect.set(fRuns[2], fRuns[0], fRuns[3], fRuns[1]); 1187 fRuns += 4; 1188 } 1189 } 1190} 1191 1192void SkRegion::Iterator::next() { 1193 if (fDone) { 1194 return; 1195 } 1196 1197 if (fRuns == NULL) { // rect case 1198 fDone = true; 1199 return; 1200 } 1201 1202 const RunType* runs = fRuns; 1203 1204 if (runs[0] < kRunTypeSentinel) { // valid X value 1205 fRect.fLeft = runs[0]; 1206 fRect.fRight = runs[1]; 1207 runs += 2; 1208 } else { // we're at the end of a line 1209 runs += 1; 1210 if (runs[0] < kRunTypeSentinel) { // valid Y value 1211 if (runs[1] == kRunTypeSentinel) { // empty line 1212 fRect.fTop = runs[0]; 1213 runs += 2; 1214 } else { 1215 fRect.fTop = fRect.fBottom; 1216 } 1217 1218 fRect.fBottom = runs[0]; 1219 assert_sentinel(runs[1], false); 1220 fRect.fLeft = runs[1]; 1221 fRect.fRight = runs[2]; 1222 runs += 3; 1223 } else { // end of rgn 1224 fDone = true; 1225 } 1226 } 1227 fRuns = runs; 1228} 1229 1230SkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip) 1231 : fIter(rgn), fClip(clip), fDone(true) { 1232 const SkIRect& r = fIter.rect(); 1233 1234 while (!fIter.done()) { 1235 if (r.fTop >= clip.fBottom) { 1236 break; 1237 } 1238 if (fRect.intersect(clip, r)) { 1239 fDone = false; 1240 break; 1241 } 1242 fIter.next(); 1243 } 1244} 1245 1246void SkRegion::Cliperator::next() { 1247 if (fDone) { 1248 return; 1249 } 1250 1251 const SkIRect& r = fIter.rect(); 1252 1253 fDone = true; 1254 fIter.next(); 1255 while (!fIter.done()) { 1256 if (r.fTop >= fClip.fBottom) { 1257 break; 1258 } 1259 if (fRect.intersect(fClip, r)) { 1260 fDone = false; 1261 break; 1262 } 1263 fIter.next(); 1264 } 1265} 1266 1267/////////////////////////////////////////////////////////////////////////////// 1268 1269static SkRegion::RunType* find_y(const SkRegion::RunType runs[], int y) { 1270 int top = *runs++; 1271 if (top <= y) { 1272 for (;;) { 1273 int bot = *runs++; 1274 if (bot > y) { 1275 if (bot == SkRegion::kRunTypeSentinel || 1276 *runs == SkRegion::kRunTypeSentinel) { 1277 break; 1278 } 1279 return (SkRegion::RunType*)runs; 1280 } 1281 runs = skip_scanline(runs); 1282 } 1283 } 1284 return NULL; 1285} 1286 1287SkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left, 1288 int right) { 1289 SkDEBUGCODE(rgn.validate();) 1290 1291 const SkIRect& r = rgn.getBounds(); 1292 1293 fDone = true; 1294 if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom && 1295 right > r.fLeft && left < r.fRight) { 1296 if (rgn.isRect()) { 1297 if (left < r.fLeft) { 1298 left = r.fLeft; 1299 } 1300 if (right > r.fRight) { 1301 right = r.fRight; 1302 } 1303 fLeft = left; 1304 fRight = right; 1305 fRuns = NULL; // means we're a rect, not a rgn 1306 fDone = false; 1307 } else { 1308 const SkRegion::RunType* runs = find_y( 1309 rgn.fRunHead->readonly_runs(), y); 1310 if (runs) { 1311 for (;;) { 1312 // runs[0..1] is to the right of the span, so we're done 1313 if (runs[0] >= right) { 1314 break; 1315 } 1316 // runs[0..1] is to the left of the span, so continue 1317 if (runs[1] <= left) { 1318 runs += 2; 1319 continue; 1320 } 1321 // runs[0..1] intersects the span 1322 fRuns = runs; 1323 fLeft = left; 1324 fRight = right; 1325 fDone = false; 1326 break; 1327 } 1328 } 1329 } 1330 } 1331} 1332 1333bool SkRegion::Spanerator::next(int* left, int* right) { 1334 if (fDone) { 1335 return false; 1336 } 1337 1338 if (fRuns == NULL) { // we're a rect 1339 fDone = true; // ok, now we're done 1340 if (left) { 1341 *left = fLeft; 1342 } 1343 if (right) { 1344 *right = fRight; 1345 } 1346 return true; // this interval is legal 1347 } 1348 1349 const SkRegion::RunType* runs = fRuns; 1350 1351 if (runs[0] >= fRight) { 1352 fDone = true; 1353 return false; 1354 } 1355 1356 SkASSERT(runs[1] > fLeft); 1357 1358 if (left) { 1359 *left = SkMax32(fLeft, runs[0]); 1360 } 1361 if (right) { 1362 *right = SkMin32(fRight, runs[1]); 1363 } 1364 fRuns = runs + 2; 1365 return true; 1366} 1367 1368/////////////////////////////////////////////////////////////////////////////// 1369 1370#ifdef SK_DEBUG 1371 1372bool SkRegion::debugSetRuns(const RunType runs[], int count) { 1373 // we need to make a copy, since the real method may modify the array, and 1374 // so it cannot be const. 1375 1376 SkAutoTArray<RunType> storage(count); 1377 memcpy(storage.get(), runs, count * sizeof(RunType)); 1378 return this->setRuns(storage.get(), count); 1379} 1380 1381#endif 1382