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