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