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