Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      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 #include "SkAAClip.h"
     10 #include "SkBlitter.h"
     11 #include "SkColorPriv.h"
     12 #include "SkPath.h"
     13 #include "SkScan.h"
     14 #include "SkThread.h"
     15 #include "SkUtils.h"
     16 
     17 class AutoAAClipValidate {
     18 public:
     19     AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) {
     20         fClip.validate();
     21     }
     22     ~AutoAAClipValidate() {
     23         fClip.validate();
     24     }
     25 private:
     26     const SkAAClip& fClip;
     27 };
     28 
     29 #ifdef SK_DEBUG
     30     #define AUTO_AACLIP_VALIDATE(clip)  AutoAAClipValidate acv(clip)
     31 #else
     32     #define AUTO_AACLIP_VALIDATE(clip)
     33 #endif
     34 
     35 ///////////////////////////////////////////////////////////////////////////////
     36 
     37 #define kMaxInt32   0x7FFFFFFF
     38 
     39 static inline bool x_in_rect(int x, const SkIRect& rect) {
     40     return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
     41 }
     42 
     43 static inline bool y_in_rect(int y, const SkIRect& rect) {
     44     return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
     45 }
     46 
     47 /*
     48  *  Data runs are packed [count, alpha]
     49  */
     50 
     51 struct SkAAClip::YOffset {
     52     int32_t  fY;
     53     uint32_t fOffset;
     54 };
     55 
     56 struct SkAAClip::RunHead {
     57     int32_t fRefCnt;
     58     int32_t fRowCount;
     59     int32_t fDataSize;
     60 
     61     YOffset* yoffsets() {
     62         return (YOffset*)((char*)this + sizeof(RunHead));
     63     }
     64     const YOffset* yoffsets() const {
     65         return (const YOffset*)((const char*)this + sizeof(RunHead));
     66     }
     67     uint8_t* data() {
     68         return (uint8_t*)(this->yoffsets() + fRowCount);
     69     }
     70     const uint8_t* data() const {
     71         return (const uint8_t*)(this->yoffsets() + fRowCount);
     72     }
     73 
     74     static RunHead* Alloc(int rowCount, size_t dataSize) {
     75         size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize;
     76         RunHead* head = (RunHead*)sk_malloc_throw(size);
     77         head->fRefCnt = 1;
     78         head->fRowCount = rowCount;
     79         head->fDataSize = dataSize;
     80         return head;
     81     }
     82 
     83     static int ComputeRowSizeForWidth(int width) {
     84         // 2 bytes per segment, where each segment can store up to 255 for count
     85         int segments = 0;
     86         while (width > 0) {
     87             segments += 1;
     88             int n = SkMin32(width, 255);
     89             width -= n;
     90         }
     91         return segments * 2;    // each segment is row[0] + row[1] (n + alpha)
     92     }
     93 
     94     static RunHead* AllocRect(const SkIRect& bounds) {
     95         SkASSERT(!bounds.isEmpty());
     96         int width = bounds.width();
     97         size_t rowSize = ComputeRowSizeForWidth(width);
     98         RunHead* head = RunHead::Alloc(1, rowSize);
     99         YOffset* yoff = head->yoffsets();
    100         yoff->fY = bounds.height() - 1;
    101         yoff->fOffset = 0;
    102         uint8_t* row = head->data();
    103         while (width > 0) {
    104             int n = SkMin32(width, 255);
    105             row[0] = n;
    106             row[1] = 0xFF;
    107             width -= n;
    108             row += 2;
    109         }
    110         return head;
    111     }
    112 };
    113 
    114 class SkAAClip::Iter {
    115 public:
    116     Iter(const SkAAClip&);
    117 
    118     bool done() const { return fDone; }
    119     int top() const { return fTop; }
    120     int bottom() const { return fBottom; }
    121     const uint8_t* data() const { return fData; }
    122     void next();
    123 
    124 private:
    125     const YOffset* fCurrYOff;
    126     const YOffset* fStopYOff;
    127     const uint8_t* fData;
    128 
    129     int fTop, fBottom;
    130     bool fDone;
    131 };
    132 
    133 SkAAClip::Iter::Iter(const SkAAClip& clip) {
    134     if (clip.isEmpty()) {
    135         fDone = true;
    136         fTop = fBottom = clip.fBounds.fBottom;
    137         fData = NULL;
    138         return;
    139     }
    140 
    141     const RunHead* head = clip.fRunHead;
    142     fCurrYOff = head->yoffsets();
    143     fStopYOff = fCurrYOff + head->fRowCount;
    144     fData     = head->data() + fCurrYOff->fOffset;
    145 
    146     // setup first value
    147     fTop = clip.fBounds.fTop;
    148     fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1;
    149     fDone = false;
    150 }
    151 
    152 void SkAAClip::Iter::next() {
    153     if (!fDone) {
    154         const YOffset* prev = fCurrYOff;
    155         const YOffset* curr = prev + 1;
    156         SkASSERT(curr <= fStopYOff);
    157 
    158         fTop = fBottom;
    159         if (curr >= fStopYOff) {
    160             fDone = true;
    161             fBottom = kMaxInt32;
    162             fData = NULL;
    163         } else {
    164             fBottom += curr->fY - prev->fY;
    165             fData += curr->fOffset - prev->fOffset;
    166             fCurrYOff = curr;
    167         }
    168     }
    169 }
    170 
    171 #ifdef SK_DEBUG
    172 // assert we're exactly width-wide, and then return the number of bytes used
    173 static size_t compute_row_length(const uint8_t row[], int width) {
    174     const uint8_t* origRow = row;
    175     while (width > 0) {
    176         int n = row[0];
    177         SkASSERT(n > 0);
    178         SkASSERT(n <= width);
    179         row += 2;
    180         width -= n;
    181     }
    182     SkASSERT(0 == width);
    183     return row - origRow;
    184 }
    185 
    186 void SkAAClip::validate() const {
    187     if (NULL == fRunHead) {
    188         SkASSERT(fBounds.isEmpty());
    189         return;
    190     }
    191 
    192     const RunHead* head = fRunHead;
    193     SkASSERT(head->fRefCnt > 0);
    194     SkASSERT(head->fRowCount > 0);
    195     SkASSERT(head->fDataSize > 0);
    196 
    197     const YOffset* yoff = head->yoffsets();
    198     const YOffset* ystop = yoff + head->fRowCount;
    199     const int lastY = fBounds.height() - 1;
    200 
    201     // Y and offset must be monotonic
    202     int prevY = -1;
    203     int32_t prevOffset = -1;
    204     while (yoff < ystop) {
    205         SkASSERT(prevY < yoff->fY);
    206         SkASSERT(yoff->fY <= lastY);
    207         prevY = yoff->fY;
    208         SkASSERT(prevOffset < (int32_t)yoff->fOffset);
    209         prevOffset = yoff->fOffset;
    210         const uint8_t* row = head->data() + yoff->fOffset;
    211         size_t rowLength = compute_row_length(row, fBounds.width());
    212         SkASSERT(yoff->fOffset + rowLength <= (size_t) head->fDataSize);
    213         yoff += 1;
    214     }
    215     // check the last entry;
    216     --yoff;
    217     SkASSERT(yoff->fY == lastY);
    218 }
    219 #endif
    220 
    221 ///////////////////////////////////////////////////////////////////////////////
    222 
    223 static void count_left_right_zeros(const uint8_t* row, int width,
    224                                    int* leftZ, int* riteZ) {
    225     int zeros = 0;
    226     do {
    227         if (row[1]) {
    228             break;
    229         }
    230         int n = row[0];
    231         SkASSERT(n > 0);
    232         SkASSERT(n <= width);
    233         zeros += n;
    234         row += 2;
    235         width -= n;
    236     } while (width > 0);
    237     *leftZ = zeros;
    238 
    239     zeros = 0;
    240     while (width > 0) {
    241         int n = row[0];
    242         SkASSERT(n > 0);
    243         if (0 == row[1]) {
    244             zeros += n;
    245         } else {
    246             zeros = 0;
    247         }
    248         row += 2;
    249         width -= n;
    250     }
    251     *riteZ = zeros;
    252 }
    253 
    254 #ifdef SK_DEBUG
    255 static void test_count_left_right_zeros() {
    256     static bool gOnce;
    257     if (gOnce) {
    258         return;
    259     }
    260     gOnce = true;
    261 
    262     const uint8_t data0[] = {  0, 0,     10, 0xFF };
    263     const uint8_t data1[] = {  0, 0,     5, 0xFF, 2, 0, 3, 0xFF };
    264     const uint8_t data2[] = {  7, 0,     5, 0, 2, 0, 3, 0xFF };
    265     const uint8_t data3[] = {  0, 5,     5, 0xFF, 2, 0, 3, 0 };
    266     const uint8_t data4[] = {  2, 3,     2, 0, 5, 0xFF, 3, 0 };
    267     const uint8_t data5[] = { 10, 0,     10, 0 };
    268     const uint8_t data6[] = {  2, 2,     2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    269 
    270     const uint8_t* array[] = {
    271         data0, data1, data2, data3, data4, data5, data6
    272     };
    273 
    274     for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
    275         const uint8_t* data = array[i];
    276         const int expectedL = *data++;
    277         const int expectedR = *data++;
    278         int L = 12345, R = 12345;
    279         count_left_right_zeros(data, 10, &L, &R);
    280         SkASSERT(expectedL == L);
    281         SkASSERT(expectedR == R);
    282     }
    283 }
    284 #endif
    285 
    286 // modify row in place, trimming off (zeros) from the left and right sides.
    287 // return the number of bytes that were completely eliminated from the left
    288 static int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) {
    289     int trim = 0;
    290     while (leftZ > 0) {
    291         SkASSERT(0 == row[1]);
    292         int n = row[0];
    293         SkASSERT(n > 0);
    294         SkASSERT(n <= width);
    295         width -= n;
    296         row += 2;
    297         if (n > leftZ) {
    298             row[-2] = n - leftZ;
    299             break;
    300         }
    301         trim += 2;
    302         leftZ -= n;
    303         SkASSERT(leftZ >= 0);
    304     }
    305 
    306     if (riteZ) {
    307         // walk row to the end, and then we'll back up to trim riteZ
    308         while (width > 0) {
    309             int n = row[0];
    310             SkASSERT(n <= width);
    311             width -= n;
    312             row += 2;
    313         }
    314         // now skip whole runs of zeros
    315         do {
    316             row -= 2;
    317             SkASSERT(0 == row[1]);
    318             int n = row[0];
    319             SkASSERT(n > 0);
    320             if (n > riteZ) {
    321                 row[0] = n - riteZ;
    322                 break;
    323             }
    324             riteZ -= n;
    325             SkASSERT(riteZ >= 0);
    326         } while (riteZ > 0);
    327     }
    328 
    329     return trim;
    330 }
    331 
    332 #ifdef SK_DEBUG
    333 // assert that this row is exactly this width
    334 static void assert_row_width(const uint8_t* row, int width) {
    335     while (width > 0) {
    336         int n = row[0];
    337         SkASSERT(n > 0);
    338         SkASSERT(n <= width);
    339         width -= n;
    340         row += 2;
    341     }
    342     SkASSERT(0 == width);
    343 }
    344 
    345 static void test_trim_row_left_right() {
    346     static bool gOnce;
    347     if (gOnce) {
    348         return;
    349     }
    350     gOnce = true;
    351 
    352     uint8_t data0[] = {  0, 0, 0,   10,    10, 0xFF };
    353     uint8_t data1[] = {  2, 0, 0,   10,    5, 0, 2, 0, 3, 0xFF };
    354     uint8_t data2[] = {  5, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
    355     uint8_t data3[] = {  6, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
    356     uint8_t data4[] = {  0, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    357     uint8_t data5[] = {  1, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    358     uint8_t data6[] = {  0, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    359     uint8_t data7[] = {  1, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    360     uint8_t data8[] = {  2, 2, 2,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
    361     uint8_t data9[] = {  5, 2, 4,   10,    2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 };
    362     uint8_t data10[] ={  74, 0, 4, 150,    9, 0, 65, 0, 76, 0xFF };
    363 
    364     uint8_t* array[] = {
    365         data0, data1, data2, data3, data4,
    366         data5, data6, data7, data8, data9,
    367         data10
    368     };
    369 
    370     for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
    371         uint8_t* data = array[i];
    372         const int trimL = *data++;
    373         const int trimR = *data++;
    374         const int expectedSkip = *data++;
    375         const int origWidth = *data++;
    376         assert_row_width(data, origWidth);
    377         int skip = trim_row_left_right(data, origWidth, trimL, trimR);
    378         SkASSERT(expectedSkip == skip);
    379         int expectedWidth = origWidth - trimL - trimR;
    380         assert_row_width(data + skip, expectedWidth);
    381     }
    382 }
    383 #endif
    384 
    385 bool SkAAClip::trimLeftRight() {
    386     SkDEBUGCODE(test_trim_row_left_right();)
    387 
    388     if (this->isEmpty()) {
    389         return false;
    390     }
    391 
    392     AUTO_AACLIP_VALIDATE(*this);
    393 
    394     const int width = fBounds.width();
    395     RunHead* head = fRunHead;
    396     YOffset* yoff = head->yoffsets();
    397     YOffset* stop = yoff + head->fRowCount;
    398     uint8_t* base = head->data();
    399 
    400     int leftZeros = width;
    401     int riteZeros = width;
    402     while (yoff < stop) {
    403         int L, R;
    404         count_left_right_zeros(base + yoff->fOffset, width, &L, &R);
    405         if (L < leftZeros) {
    406             leftZeros = L;
    407         }
    408         if (R < riteZeros) {
    409             riteZeros = R;
    410         }
    411         if (0 == (leftZeros | riteZeros)) {
    412             // no trimming to do
    413             return true;
    414         }
    415         yoff += 1;
    416     }
    417 
    418     SkASSERT(leftZeros || riteZeros);
    419     if (width == (leftZeros + riteZeros)) {
    420         return this->setEmpty();
    421     }
    422 
    423     this->validate();
    424 
    425     fBounds.fLeft += leftZeros;
    426     fBounds.fRight -= riteZeros;
    427     SkASSERT(!fBounds.isEmpty());
    428 
    429     // For now we don't realloc the storage (for time), we just shrink in place
    430     // This means we don't have to do any memmoves either, since we can just
    431     // play tricks with the yoff->fOffset for each row
    432     yoff = head->yoffsets();
    433     while (yoff < stop) {
    434         uint8_t* row = base + yoff->fOffset;
    435         SkDEBUGCODE((void)compute_row_length(row, width);)
    436         yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros);
    437         SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);)
    438         yoff += 1;
    439     }
    440     return true;
    441 }
    442 
    443 static bool row_is_all_zeros(const uint8_t* row, int width) {
    444     SkASSERT(width > 0);
    445     do {
    446         if (row[1]) {
    447             return false;
    448         }
    449         int n = row[0];
    450         SkASSERT(n <= width);
    451         width -= n;
    452         row += 2;
    453     } while (width > 0);
    454     SkASSERT(0 == width);
    455     return true;
    456 }
    457 
    458 bool SkAAClip::trimTopBottom() {
    459     if (this->isEmpty()) {
    460         return false;
    461     }
    462 
    463     this->validate();
    464 
    465     const int width = fBounds.width();
    466     RunHead* head = fRunHead;
    467     YOffset* yoff = head->yoffsets();
    468     YOffset* stop = yoff + head->fRowCount;
    469     const uint8_t* base = head->data();
    470 
    471     //  Look to trim away empty rows from the top.
    472     //
    473     int skip = 0;
    474     while (yoff < stop) {
    475         const uint8_t* data = base + yoff->fOffset;
    476         if (!row_is_all_zeros(data, width)) {
    477             break;
    478         }
    479         skip += 1;
    480         yoff += 1;
    481     }
    482     SkASSERT(skip <= head->fRowCount);
    483     if (skip == head->fRowCount) {
    484         return this->setEmpty();
    485     }
    486     if (skip > 0) {
    487         // adjust fRowCount and fBounds.fTop, and slide all the data up
    488         // as we remove [skip] number of YOffset entries
    489         yoff = head->yoffsets();
    490         int dy = yoff[skip - 1].fY + 1;
    491         for (int i = skip; i < head->fRowCount; ++i) {
    492             SkASSERT(yoff[i].fY >= dy);
    493             yoff[i].fY -= dy;
    494         }
    495         YOffset* dst = head->yoffsets();
    496         size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize;
    497         memmove(dst, dst + skip, size - skip * sizeof(YOffset));
    498 
    499         fBounds.fTop += dy;
    500         SkASSERT(!fBounds.isEmpty());
    501         head->fRowCount -= skip;
    502         SkASSERT(head->fRowCount > 0);
    503 
    504         this->validate();
    505         // need to reset this after the memmove
    506         base = head->data();
    507     }
    508 
    509     //  Look to trim away empty rows from the bottom.
    510     //  We know that we have at least one non-zero row, so we can just walk
    511     //  backwards without checking for running past the start.
    512     //
    513     stop = yoff = head->yoffsets() + head->fRowCount;
    514     do {
    515         yoff -= 1;
    516     } while (row_is_all_zeros(base + yoff->fOffset, width));
    517     skip = stop - yoff - 1;
    518     SkASSERT(skip >= 0 && skip < head->fRowCount);
    519     if (skip > 0) {
    520         // removing from the bottom is easier than from the top, as we don't
    521         // have to adjust any of the Y values, we just have to trim the array
    522         memmove(stop - skip, stop, head->fDataSize);
    523 
    524         fBounds.fBottom = fBounds.fTop + yoff->fY + 1;
    525         SkASSERT(!fBounds.isEmpty());
    526         head->fRowCount -= skip;
    527         SkASSERT(head->fRowCount > 0);
    528     }
    529     this->validate();
    530 
    531     return true;
    532 }
    533 
    534 // can't validate before we're done, since trimming is part of the process of
    535 // making us valid after the Builder. Since we build from top to bottom, its
    536 // possible our fBounds.fBottom is bigger than our last scanline of data, so
    537 // we trim fBounds.fBottom back up.
    538 //
    539 // TODO: check for duplicates in X and Y to further compress our data
    540 //
    541 bool SkAAClip::trimBounds() {
    542     if (this->isEmpty()) {
    543         return false;
    544     }
    545 
    546     const RunHead* head = fRunHead;
    547     const YOffset* yoff = head->yoffsets();
    548 
    549     SkASSERT(head->fRowCount > 0);
    550     const YOffset& lastY = yoff[head->fRowCount - 1];
    551     SkASSERT(lastY.fY + 1 <= fBounds.height());
    552     fBounds.fBottom = fBounds.fTop + lastY.fY + 1;
    553     SkASSERT(lastY.fY + 1 == fBounds.height());
    554     SkASSERT(!fBounds.isEmpty());
    555 
    556     return this->trimTopBottom() && this->trimLeftRight();
    557 }
    558 
    559 ///////////////////////////////////////////////////////////////////////////////
    560 
    561 void SkAAClip::freeRuns() {
    562     if (fRunHead) {
    563         SkASSERT(fRunHead->fRefCnt >= 1);
    564         if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) {
    565             sk_free(fRunHead);
    566         }
    567     }
    568 }
    569 
    570 SkAAClip::SkAAClip() {
    571     fBounds.setEmpty();
    572     fRunHead = NULL;
    573 }
    574 
    575 SkAAClip::SkAAClip(const SkAAClip& src) {
    576     SkDEBUGCODE(fBounds.setEmpty();)    // need this for validate
    577     fRunHead = NULL;
    578     *this = src;
    579 }
    580 
    581 SkAAClip::~SkAAClip() {
    582     this->freeRuns();
    583 }
    584 
    585 SkAAClip& SkAAClip::operator=(const SkAAClip& src) {
    586     AUTO_AACLIP_VALIDATE(*this);
    587     src.validate();
    588 
    589     if (this != &src) {
    590         this->freeRuns();
    591         fBounds = src.fBounds;
    592         fRunHead = src.fRunHead;
    593         if (fRunHead) {
    594             sk_atomic_inc(&fRunHead->fRefCnt);
    595         }
    596     }
    597     return *this;
    598 }
    599 
    600 bool operator==(const SkAAClip& a, const SkAAClip& b) {
    601     a.validate();
    602     b.validate();
    603 
    604     if (&a == &b) {
    605         return true;
    606     }
    607     if (a.fBounds != b.fBounds) {
    608         return false;
    609     }
    610 
    611     const SkAAClip::RunHead* ah = a.fRunHead;
    612     const SkAAClip::RunHead* bh = b.fRunHead;
    613 
    614     // this catches empties and rects being equal
    615     if (ah == bh) {
    616         return true;
    617     }
    618 
    619     // now we insist that both are complex (but different ptrs)
    620     if (!a.fRunHead || !b.fRunHead) {
    621         return false;
    622     }
    623 
    624     return  ah->fRowCount == bh->fRowCount &&
    625             ah->fDataSize == bh->fDataSize &&
    626             !memcmp(ah->data(), bh->data(), ah->fDataSize);
    627 }
    628 
    629 void SkAAClip::swap(SkAAClip& other) {
    630     AUTO_AACLIP_VALIDATE(*this);
    631     other.validate();
    632 
    633     SkTSwap(fBounds, other.fBounds);
    634     SkTSwap(fRunHead, other.fRunHead);
    635 }
    636 
    637 bool SkAAClip::set(const SkAAClip& src) {
    638     *this = src;
    639     return !this->isEmpty();
    640 }
    641 
    642 bool SkAAClip::setEmpty() {
    643     this->freeRuns();
    644     fBounds.setEmpty();
    645     fRunHead = NULL;
    646     return false;
    647 }
    648 
    649 bool SkAAClip::setRect(const SkIRect& bounds) {
    650     if (bounds.isEmpty()) {
    651         return this->setEmpty();
    652     }
    653 
    654     AUTO_AACLIP_VALIDATE(*this);
    655 
    656 #if 0
    657     SkRect r;
    658     r.set(bounds);
    659     SkPath path;
    660     path.addRect(r);
    661     return this->setPath(path);
    662 #else
    663     this->freeRuns();
    664     fBounds = bounds;
    665     fRunHead = RunHead::AllocRect(bounds);
    666     SkASSERT(!this->isEmpty());
    667     return true;
    668 #endif
    669 }
    670 
    671 bool SkAAClip::setRect(const SkRect& r, bool doAA) {
    672     if (r.isEmpty()) {
    673         return this->setEmpty();
    674     }
    675 
    676     AUTO_AACLIP_VALIDATE(*this);
    677 
    678     // TODO: special case this
    679 
    680     SkPath path;
    681     path.addRect(r);
    682     return this->setPath(path, NULL, doAA);
    683 }
    684 
    685 static void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) {
    686     SkASSERT(count >= 0);
    687     while (count > 0) {
    688         int n = count;
    689         if (n > 255) {
    690             n = 255;
    691         }
    692         uint8_t* data = array.append(2);
    693         data[0] = n;
    694         data[1] = value;
    695         count -= n;
    696     }
    697 }
    698 
    699 bool SkAAClip::setRegion(const SkRegion& rgn) {
    700     if (rgn.isEmpty()) {
    701         return this->setEmpty();
    702     }
    703     if (rgn.isRect()) {
    704         return this->setRect(rgn.getBounds());
    705     }
    706 
    707 #if 0
    708     SkAAClip clip;
    709     SkRegion::Iterator iter(rgn);
    710     for (; !iter.done(); iter.next()) {
    711         clip.op(iter.rect(), SkRegion::kUnion_Op);
    712     }
    713     this->swap(clip);
    714     return !this->isEmpty();
    715 #else
    716     const SkIRect& bounds = rgn.getBounds();
    717     const int offsetX = bounds.fLeft;
    718     const int offsetY = bounds.fTop;
    719 
    720     SkTDArray<YOffset> yArray;
    721     SkTDArray<uint8_t> xArray;
    722 
    723     yArray.setReserve(SkMin32(bounds.height(), 1024));
    724     xArray.setReserve(SkMin32(bounds.width() * 128, 64 * 1024));
    725 
    726     SkRegion::Iterator iter(rgn);
    727     int prevRight = 0;
    728     int prevBot = 0;
    729     YOffset* currY = NULL;
    730 
    731     for (; !iter.done(); iter.next()) {
    732         const SkIRect& r = iter.rect();
    733         SkASSERT(bounds.contains(r));
    734 
    735         int bot = r.fBottom - offsetY;
    736         SkASSERT(bot >= prevBot);
    737         if (bot > prevBot) {
    738             if (currY) {
    739                 // flush current row
    740                 append_run(xArray, 0, bounds.width() - prevRight);
    741             }
    742             // did we introduce an empty-gap from the prev row?
    743             int top = r.fTop - offsetY;
    744             if (top > prevBot) {
    745                 currY = yArray.append();
    746                 currY->fY = top - 1;
    747                 currY->fOffset = xArray.count();
    748                 append_run(xArray, 0, bounds.width());
    749             }
    750             // create a new record for this Y value
    751             currY = yArray.append();
    752             currY->fY = bot - 1;
    753             currY->fOffset = xArray.count();
    754             prevRight = 0;
    755             prevBot = bot;
    756         }
    757 
    758         int x = r.fLeft - offsetX;
    759         append_run(xArray, 0, x - prevRight);
    760 
    761         int w = r.fRight - r.fLeft;
    762         append_run(xArray, 0xFF, w);
    763         prevRight = x + w;
    764         SkASSERT(prevRight <= bounds.width());
    765     }
    766     // flush last row
    767     append_run(xArray, 0, bounds.width() - prevRight);
    768 
    769     // now pack everything into a RunHead
    770     RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes());
    771     memcpy(head->yoffsets(), yArray.begin(), yArray.bytes());
    772     memcpy(head->data(), xArray.begin(), xArray.bytes());
    773 
    774     this->setEmpty();
    775     fBounds = bounds;
    776     fRunHead = head;
    777     this->validate();
    778     return true;
    779 #endif
    780 }
    781 
    782 ///////////////////////////////////////////////////////////////////////////////
    783 
    784 const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
    785     SkASSERT(fRunHead);
    786 
    787     if (!y_in_rect(y, fBounds)) {
    788         return NULL;
    789     }
    790     y -= fBounds.y();  // our yoffs values are relative to the top
    791 
    792     const YOffset* yoff = fRunHead->yoffsets();
    793     while (yoff->fY < y) {
    794         yoff += 1;
    795         SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
    796     }
    797 
    798     if (lastYForRow) {
    799         *lastYForRow = fBounds.y() + yoff->fY;
    800     }
    801     return fRunHead->data() + yoff->fOffset;
    802 }
    803 
    804 const uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
    805     SkASSERT(x_in_rect(x, fBounds));
    806     x -= fBounds.x();
    807 
    808     // first skip up to X
    809     for (;;) {
    810         int n = data[0];
    811         if (x < n) {
    812             *initialCount = n - x;
    813             break;
    814         }
    815         data += 2;
    816         x -= n;
    817     }
    818     return data;
    819 }
    820 
    821 bool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
    822     if (this->isEmpty()) {
    823         return false;
    824     }
    825     if (!fBounds.contains(left, top, right, bottom)) {
    826         return false;
    827     }
    828 #if 0
    829     if (this->isRect()) {
    830         return true;
    831     }
    832 #endif
    833 
    834     int lastY;
    835     const uint8_t* row = this->findRow(top, &lastY);
    836     if (lastY < bottom) {
    837         return false;
    838     }
    839     // now just need to check in X
    840     int count;
    841     row = this->findX(row, left, &count);
    842 #if 0
    843     return count >= (right - left) && 0xFF == row[1];
    844 #else
    845     int rectWidth = right - left;
    846     while (0xFF == row[1]) {
    847         if (count >= rectWidth) {
    848             return true;
    849         }
    850         rectWidth -= count;
    851         row += 2;
    852         count = row[0];
    853     }
    854     return false;
    855 #endif
    856 }
    857 
    858 ///////////////////////////////////////////////////////////////////////////////
    859 
    860 class SkAAClip::Builder {
    861     SkIRect fBounds;
    862     struct Row {
    863         int fY;
    864         int fWidth;
    865         SkTDArray<uint8_t>* fData;
    866     };
    867     SkTDArray<Row>  fRows;
    868     Row* fCurrRow;
    869     int fPrevY;
    870     int fWidth;
    871     int fMinY;
    872 
    873 public:
    874     Builder(const SkIRect& bounds) : fBounds(bounds) {
    875         fPrevY = -1;
    876         fWidth = bounds.width();
    877         fCurrRow = NULL;
    878         fMinY = bounds.fTop;
    879     }
    880 
    881     ~Builder() {
    882         Row* row = fRows.begin();
    883         Row* stop = fRows.end();
    884         while (row < stop) {
    885             delete row->fData;
    886             row += 1;
    887         }
    888     }
    889 
    890     const SkIRect& getBounds() const { return fBounds; }
    891 
    892     void addRun(int x, int y, U8CPU alpha, int count) {
    893         SkASSERT(count > 0);
    894         SkASSERT(fBounds.contains(x, y));
    895         SkASSERT(fBounds.contains(x + count - 1, y));
    896 
    897         x -= fBounds.left();
    898         y -= fBounds.top();
    899 
    900         Row* row = fCurrRow;
    901         if (y != fPrevY) {
    902             SkASSERT(y > fPrevY);
    903             fPrevY = y;
    904             row = this->flushRow(true);
    905             row->fY = y;
    906             row->fWidth = 0;
    907             SkASSERT(row->fData);
    908             SkASSERT(0 == row->fData->count());
    909             fCurrRow = row;
    910         }
    911 
    912         SkASSERT(row->fWidth <= x);
    913         SkASSERT(row->fWidth < fBounds.width());
    914 
    915         SkTDArray<uint8_t>& data = *row->fData;
    916 
    917         int gap = x - row->fWidth;
    918         if (gap) {
    919             AppendRun(data, 0, gap);
    920             row->fWidth += gap;
    921             SkASSERT(row->fWidth < fBounds.width());
    922         }
    923 
    924         AppendRun(data, alpha, count);
    925         row->fWidth += count;
    926         SkASSERT(row->fWidth <= fBounds.width());
    927     }
    928 
    929     void addColumn(int x, int y, U8CPU alpha, int height) {
    930         SkASSERT(fBounds.contains(x, y + height - 1));
    931 
    932         this->addRun(x, y, alpha, 1);
    933         this->flushRowH(fCurrRow);
    934         y -= fBounds.fTop;
    935         SkASSERT(y == fCurrRow->fY);
    936         fCurrRow->fY = y + height - 1;
    937     }
    938 
    939     void addRectRun(int x, int y, int width, int height) {
    940         SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
    941         this->addRun(x, y, 0xFF, width);
    942 
    943         // we assum the rect must be all we'll see for these scanlines
    944         // so we ensure our row goes all the way to our right
    945         this->flushRowH(fCurrRow);
    946 
    947         y -= fBounds.fTop;
    948         SkASSERT(y == fCurrRow->fY);
    949         fCurrRow->fY = y + height - 1;
    950     }
    951 
    952     void addAntiRectRun(int x, int y, int width, int height,
    953                         SkAlpha leftAlpha, SkAlpha rightAlpha) {
    954         SkASSERT(fBounds.contains(x + width - 1 +
    955                  (leftAlpha > 0 ? 1 : 0) + (rightAlpha > 0 ? 1 : 0),
    956                  y + height - 1));
    957         SkASSERT(width >= 0);
    958 
    959         // Conceptually we're always adding 3 runs, but we should
    960         // merge or omit them if possible.
    961         if (leftAlpha == 0xFF) {
    962             width++;
    963         } else if (leftAlpha > 0) {
    964           this->addRun(x++, y, leftAlpha, 1);
    965         }
    966         if (rightAlpha == 0xFF) {
    967             width++;
    968         }
    969         if (width > 0) {
    970             this->addRun(x, y, 0xFF, width);
    971         }
    972         if (rightAlpha > 0 && rightAlpha < 255) {
    973             this->addRun(x + width, y, rightAlpha, 1);
    974         }
    975 
    976         // we assume the rect must be all we'll see for these scanlines
    977         // so we ensure our row goes all the way to our right
    978         this->flushRowH(fCurrRow);
    979 
    980         y -= fBounds.fTop;
    981         SkASSERT(y == fCurrRow->fY);
    982         fCurrRow->fY = y + height - 1;
    983     }
    984 
    985     bool finish(SkAAClip* target) {
    986         this->flushRow(false);
    987 
    988         const Row* row = fRows.begin();
    989         const Row* stop = fRows.end();
    990 
    991         size_t dataSize = 0;
    992         while (row < stop) {
    993             dataSize += row->fData->count();
    994             row += 1;
    995         }
    996 
    997         if (0 == dataSize) {
    998             return target->setEmpty();
    999         }
   1000 
   1001         SkASSERT(fMinY >= fBounds.fTop);
   1002         SkASSERT(fMinY < fBounds.fBottom);
   1003         int adjustY = fMinY - fBounds.fTop;
   1004         fBounds.fTop = fMinY;
   1005 
   1006         RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
   1007         YOffset* yoffset = head->yoffsets();
   1008         uint8_t* data = head->data();
   1009         uint8_t* baseData = data;
   1010 
   1011         row = fRows.begin();
   1012         SkDEBUGCODE(int prevY = row->fY - 1;)
   1013         while (row < stop) {
   1014             SkASSERT(prevY < row->fY);  // must be monotonic
   1015             SkDEBUGCODE(prevY = row->fY);
   1016 
   1017             yoffset->fY = row->fY - adjustY;
   1018             yoffset->fOffset = data - baseData;
   1019             yoffset += 1;
   1020 
   1021             size_t n = row->fData->count();
   1022             memcpy(data, row->fData->begin(), n);
   1023 #ifdef SK_DEBUG
   1024             size_t bytesNeeded = compute_row_length(data, fBounds.width());
   1025             SkASSERT(bytesNeeded == n);
   1026 #endif
   1027             data += n;
   1028 
   1029             row += 1;
   1030         }
   1031 
   1032         target->freeRuns();
   1033         target->fBounds = fBounds;
   1034         target->fRunHead = head;
   1035         return target->trimBounds();
   1036     }
   1037 
   1038     void dump() {
   1039         this->validate();
   1040         int y;
   1041         for (y = 0; y < fRows.count(); ++y) {
   1042             const Row& row = fRows[y];
   1043             SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
   1044             const SkTDArray<uint8_t>& data = *row.fData;
   1045             int count = data.count();
   1046             SkASSERT(!(count & 1));
   1047             const uint8_t* ptr = data.begin();
   1048             for (int x = 0; x < count; x += 2) {
   1049                 SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
   1050                 ptr += 2;
   1051             }
   1052             SkDebugf("\n");
   1053         }
   1054     }
   1055 
   1056     void validate() {
   1057 #ifdef SK_DEBUG
   1058         int prevY = -1;
   1059         for (int i = 0; i < fRows.count(); ++i) {
   1060             const Row& row = fRows[i];
   1061             SkASSERT(prevY < row.fY);
   1062             SkASSERT(fWidth == row.fWidth);
   1063             int count = row.fData->count();
   1064             const uint8_t* ptr = row.fData->begin();
   1065             SkASSERT(!(count & 1));
   1066             int w = 0;
   1067             for (int x = 0; x < count; x += 2) {
   1068                 int n = ptr[0];
   1069                 SkASSERT(n > 0);
   1070                 w += n;
   1071                 SkASSERT(w <= fWidth);
   1072                 ptr += 2;
   1073             }
   1074             SkASSERT(w == fWidth);
   1075             prevY = row.fY;
   1076         }
   1077 #endif
   1078     }
   1079 
   1080     // only called by BuilderBlitter
   1081     void setMinY(int y) {
   1082         fMinY = y;
   1083     }
   1084 
   1085 private:
   1086     void flushRowH(Row* row) {
   1087         // flush current row if needed
   1088         if (row->fWidth < fWidth) {
   1089             AppendRun(*row->fData, 0, fWidth - row->fWidth);
   1090             row->fWidth = fWidth;
   1091         }
   1092     }
   1093 
   1094     Row* flushRow(bool readyForAnother) {
   1095         Row* next = NULL;
   1096         int count = fRows.count();
   1097         if (count > 0) {
   1098             this->flushRowH(&fRows[count - 1]);
   1099         }
   1100         if (count > 1) {
   1101             // are our last two runs the same?
   1102             Row* prev = &fRows[count - 2];
   1103             Row* curr = &fRows[count - 1];
   1104             SkASSERT(prev->fWidth == fWidth);
   1105             SkASSERT(curr->fWidth == fWidth);
   1106             if (*prev->fData == *curr->fData) {
   1107                 prev->fY = curr->fY;
   1108                 if (readyForAnother) {
   1109                     curr->fData->rewind();
   1110                     next = curr;
   1111                 } else {
   1112                     delete curr->fData;
   1113                     fRows.removeShuffle(count - 1);
   1114                 }
   1115             } else {
   1116                 if (readyForAnother) {
   1117                     next = fRows.append();
   1118                     next->fData = new SkTDArray<uint8_t>;
   1119                 }
   1120             }
   1121         } else {
   1122             if (readyForAnother) {
   1123                 next = fRows.append();
   1124                 next->fData = new SkTDArray<uint8_t>;
   1125             }
   1126         }
   1127         return next;
   1128     }
   1129 
   1130     static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
   1131         do {
   1132             int n = count;
   1133             if (n > 255) {
   1134                 n = 255;
   1135             }
   1136             uint8_t* ptr = data.append(2);
   1137             ptr[0] = n;
   1138             ptr[1] = alpha;
   1139             count -= n;
   1140         } while (count > 0);
   1141     }
   1142 };
   1143 
   1144 class SkAAClip::BuilderBlitter : public SkBlitter {
   1145     int fLastY;
   1146 
   1147     /*
   1148         If we see a gap of 1 or more empty scanlines while building in Y-order,
   1149         we inject an explicit empty scanline (alpha==0)
   1150 
   1151         See AAClipTest.cpp : test_path_with_hole()
   1152      */
   1153     void checkForYGap(int y) {
   1154         SkASSERT(y >= fLastY);
   1155         if (fLastY > -SK_MaxS32) {
   1156             int gap = y - fLastY;
   1157             if (gap > 1) {
   1158                 fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft);
   1159             }
   1160         }
   1161         fLastY = y;
   1162     }
   1163 
   1164 public:
   1165 
   1166     BuilderBlitter(Builder* builder) {
   1167         fBuilder = builder;
   1168         fLeft = builder->getBounds().fLeft;
   1169         fRight = builder->getBounds().fRight;
   1170         fMinY = SK_MaxS32;
   1171         fLastY = -SK_MaxS32;    // sentinel
   1172     }
   1173 
   1174     void finish() {
   1175         if (fMinY < SK_MaxS32) {
   1176             fBuilder->setMinY(fMinY);
   1177         }
   1178     }
   1179 
   1180     /**
   1181        Must evaluate clips in scan-line order, so don't want to allow blitV(),
   1182        but an AAClip can be clipped down to a single pixel wide, so we
   1183        must support it (given AntiRect semantics: minimum width is 2).
   1184        Instead we'll rely on the runtime asserts to guarantee Y monotonicity;
   1185        any failure cases that misses may have minor artifacts.
   1186     */
   1187     virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE {
   1188         this->recordMinY(y);
   1189         fBuilder->addColumn(x, y, alpha, height);
   1190         fLastY = y + height - 1;
   1191     }
   1192 
   1193     virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE {
   1194         this->recordMinY(y);
   1195         this->checkForYGap(y);
   1196         fBuilder->addRectRun(x, y, width, height);
   1197         fLastY = y + height - 1;
   1198     }
   1199 
   1200     virtual void blitAntiRect(int x, int y, int width, int height,
   1201                      SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE {
   1202         this->recordMinY(y);
   1203         this->checkForYGap(y);
   1204         fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha);
   1205         fLastY = y + height - 1;
   1206     }
   1207 
   1208     virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
   1209         { unexpected(); }
   1210 
   1211     virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE {
   1212         return NULL;
   1213     }
   1214 
   1215     virtual void blitH(int x, int y, int width) SK_OVERRIDE {
   1216         this->recordMinY(y);
   1217         this->checkForYGap(y);
   1218         fBuilder->addRun(x, y, 0xFF, width);
   1219     }
   1220 
   1221     virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
   1222                            const int16_t runs[]) SK_OVERRIDE {
   1223         this->recordMinY(y);
   1224         this->checkForYGap(y);
   1225         for (;;) {
   1226             int count = *runs;
   1227             if (count <= 0) {
   1228                 return;
   1229             }
   1230 
   1231             // The supersampler's buffer can be the width of the device, so
   1232             // we may have to trim the run to our bounds. If so, we assert that
   1233             // the extra spans are always alpha==0
   1234             int localX = x;
   1235             int localCount = count;
   1236             if (x < fLeft) {
   1237                 SkASSERT(0 == *alpha);
   1238                 int gap = fLeft - x;
   1239                 SkASSERT(gap <= count);
   1240                 localX += gap;
   1241                 localCount -= gap;
   1242             }
   1243             int right = x + count;
   1244             if (right > fRight) {
   1245                 SkASSERT(0 == *alpha);
   1246                 localCount -= right - fRight;
   1247                 SkASSERT(localCount >= 0);
   1248             }
   1249 
   1250             if (localCount) {
   1251                 fBuilder->addRun(localX, y, *alpha, localCount);
   1252             }
   1253             // Next run
   1254             runs += count;
   1255             alpha += count;
   1256             x += count;
   1257         }
   1258     }
   1259 
   1260 private:
   1261     Builder* fBuilder;
   1262     int      fLeft; // cache of builder's bounds' left edge
   1263     int      fRight;
   1264     int      fMinY;
   1265 
   1266     /*
   1267      *  We track this, in case the scan converter skipped some number of
   1268      *  scanlines at the (relative to the bounds it was given). This allows
   1269      *  the builder, during its finish, to trip its bounds down to the "real"
   1270      *  top.
   1271      */
   1272     void recordMinY(int y) {
   1273         if (y < fMinY) {
   1274             fMinY = y;
   1275         }
   1276     }
   1277 
   1278     void unexpected() {
   1279         SkDebugf("---- did not expect to get called here");
   1280         sk_throw();
   1281     }
   1282 };
   1283 
   1284 bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
   1285     AUTO_AACLIP_VALIDATE(*this);
   1286 
   1287     if (clip && clip->isEmpty()) {
   1288         return this->setEmpty();
   1289     }
   1290 
   1291     SkIRect ibounds;
   1292     path.getBounds().roundOut(&ibounds);
   1293 
   1294     SkRegion tmpClip;
   1295     if (NULL == clip) {
   1296         tmpClip.setRect(ibounds);
   1297         clip = &tmpClip;
   1298     }
   1299 
   1300     if (path.isInverseFillType()) {
   1301         ibounds = clip->getBounds();
   1302     } else {
   1303         if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
   1304             return this->setEmpty();
   1305         }
   1306     }
   1307 
   1308     Builder        builder(ibounds);
   1309     BuilderBlitter blitter(&builder);
   1310 
   1311     if (doAA) {
   1312         SkScan::AntiFillPath(path, *clip, &blitter, true);
   1313     } else {
   1314         SkScan::FillPath(path, *clip, &blitter);
   1315     }
   1316 
   1317     blitter.finish();
   1318     return builder.finish(this);
   1319 }
   1320 
   1321 ///////////////////////////////////////////////////////////////////////////////
   1322 
   1323 typedef void (*RowProc)(SkAAClip::Builder&, int bottom,
   1324                         const uint8_t* rowA, const SkIRect& rectA,
   1325                         const uint8_t* rowB, const SkIRect& rectB);
   1326 
   1327 static void sectRowProc(SkAAClip::Builder& builder, int bottom,
   1328                         const uint8_t* rowA, const SkIRect& rectA,
   1329                         const uint8_t* rowB, const SkIRect& rectB) {
   1330 
   1331 }
   1332 
   1333 typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
   1334 
   1335 static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
   1336     // Multiply
   1337     return SkMulDiv255Round(alphaA, alphaB);
   1338 }
   1339 
   1340 static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
   1341     // SrcOver
   1342     return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
   1343 }
   1344 
   1345 static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
   1346     // SrcOut
   1347     return SkMulDiv255Round(alphaA, 0xFF - alphaB);
   1348 }
   1349 
   1350 static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
   1351     // XOR
   1352     return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
   1353 }
   1354 
   1355 static AlphaProc find_alpha_proc(SkRegion::Op op) {
   1356     switch (op) {
   1357         case SkRegion::kIntersect_Op:
   1358             return sectAlphaProc;
   1359         case SkRegion::kDifference_Op:
   1360             return diffAlphaProc;
   1361         case SkRegion::kUnion_Op:
   1362             return unionAlphaProc;
   1363         case SkRegion::kXOR_Op:
   1364             return xorAlphaProc;
   1365         default:
   1366             SkDEBUGFAIL("unexpected region op");
   1367             return sectAlphaProc;
   1368     }
   1369 }
   1370 
   1371 static const uint8_t gEmptyRow[] = {
   1372     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1373     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1374     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1375     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1376     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1377     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1378     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1379     0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
   1380 };
   1381 
   1382 class RowIter {
   1383 public:
   1384     RowIter(const uint8_t* row, const SkIRect& bounds) {
   1385         fRow = row;
   1386         fLeft = bounds.fLeft;
   1387         fBoundsRight = bounds.fRight;
   1388         if (row) {
   1389             fRight = bounds.fLeft + row[0];
   1390             SkASSERT(fRight <= fBoundsRight);
   1391             fAlpha = row[1];
   1392             fDone = false;
   1393         } else {
   1394             fDone = true;
   1395             fRight = kMaxInt32;
   1396             fAlpha = 0;
   1397         }
   1398     }
   1399 
   1400     bool done() const { return fDone; }
   1401     int left() const { return fLeft; }
   1402     int right() const { return fRight; }
   1403     U8CPU alpha() const { return fAlpha; }
   1404     void next() {
   1405         if (!fDone) {
   1406             fLeft = fRight;
   1407             if (fRight == fBoundsRight) {
   1408                 fDone = true;
   1409                 fRight = kMaxInt32;
   1410                 fAlpha = 0;
   1411             } else {
   1412                 fRow += 2;
   1413                 fRight += fRow[0];
   1414                 fAlpha = fRow[1];
   1415                 SkASSERT(fRight <= fBoundsRight);
   1416             }
   1417         }
   1418     }
   1419 
   1420 private:
   1421     const uint8_t*  fRow;
   1422     int             fLeft;
   1423     int             fRight;
   1424     int             fBoundsRight;
   1425     bool            fDone;
   1426     uint8_t         fAlpha;
   1427 };
   1428 
   1429 static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
   1430     if (rite == riteA) {
   1431         iter.next();
   1432         leftA = iter.left();
   1433         riteA = iter.right();
   1434     }
   1435 }
   1436 
   1437 static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
   1438     SkASSERT(min < max);
   1439     SkASSERT(boundsMin < boundsMax);
   1440     if (min >= boundsMax || max <= boundsMin) {
   1441         return false;
   1442     }
   1443     if (min < boundsMin) {
   1444         min = boundsMin;
   1445     }
   1446     if (max > boundsMax) {
   1447         max = boundsMax;
   1448     }
   1449     return true;
   1450 }
   1451 
   1452 static void operatorX(SkAAClip::Builder& builder, int lastY,
   1453                       RowIter& iterA, RowIter& iterB,
   1454                       AlphaProc proc, const SkIRect& bounds) {
   1455     int leftA = iterA.left();
   1456     int riteA = iterA.right();
   1457     int leftB = iterB.left();
   1458     int riteB = iterB.right();
   1459 
   1460     int prevRite = bounds.fLeft;
   1461 
   1462     do {
   1463         U8CPU alphaA = 0;
   1464         U8CPU alphaB = 0;
   1465         int left, rite;
   1466 
   1467         if (leftA < leftB) {
   1468             left = leftA;
   1469             alphaA = iterA.alpha();
   1470             if (riteA <= leftB) {
   1471                 rite = riteA;
   1472             } else {
   1473                 rite = leftA = leftB;
   1474             }
   1475         } else if (leftB < leftA) {
   1476             left = leftB;
   1477             alphaB = iterB.alpha();
   1478             if (riteB <= leftA) {
   1479                 rite = riteB;
   1480             } else {
   1481                 rite = leftB = leftA;
   1482             }
   1483         } else {
   1484             left = leftA;   // or leftB, since leftA == leftB
   1485             rite = leftA = leftB = SkMin32(riteA, riteB);
   1486             alphaA = iterA.alpha();
   1487             alphaB = iterB.alpha();
   1488         }
   1489 
   1490         if (left >= bounds.fRight) {
   1491             break;
   1492         }
   1493         if (rite > bounds.fRight) {
   1494             rite = bounds.fRight;
   1495         }
   1496 
   1497         if (left >= bounds.fLeft) {
   1498             SkASSERT(rite > left);
   1499             builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
   1500             prevRite = rite;
   1501         }
   1502 
   1503         adjust_row(iterA, leftA, riteA, rite);
   1504         adjust_row(iterB, leftB, riteB, rite);
   1505     } while (!iterA.done() || !iterB.done());
   1506 
   1507     if (prevRite < bounds.fRight) {
   1508         builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
   1509     }
   1510 }
   1511 
   1512 static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
   1513     if (bot == botA) {
   1514         iter.next();
   1515         topA = botA;
   1516         SkASSERT(botA == iter.top());
   1517         botA = iter.bottom();
   1518     }
   1519 }
   1520 
   1521 static void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
   1522                      const SkAAClip& B, SkRegion::Op op) {
   1523     AlphaProc proc = find_alpha_proc(op);
   1524     const SkIRect& bounds = builder.getBounds();
   1525 
   1526     SkAAClip::Iter iterA(A);
   1527     SkAAClip::Iter iterB(B);
   1528 
   1529     SkASSERT(!iterA.done());
   1530     int topA = iterA.top();
   1531     int botA = iterA.bottom();
   1532     SkASSERT(!iterB.done());
   1533     int topB = iterB.top();
   1534     int botB = iterB.bottom();
   1535 
   1536     do {
   1537         const uint8_t* rowA = NULL;
   1538         const uint8_t* rowB = NULL;
   1539         int top, bot;
   1540 
   1541         if (topA < topB) {
   1542             top = topA;
   1543             rowA = iterA.data();
   1544             if (botA <= topB) {
   1545                 bot = botA;
   1546             } else {
   1547                 bot = topA = topB;
   1548             }
   1549 
   1550         } else if (topB < topA) {
   1551             top = topB;
   1552             rowB = iterB.data();
   1553             if (botB <= topA) {
   1554                 bot = botB;
   1555             } else {
   1556                 bot = topB = topA;
   1557             }
   1558         } else {
   1559             top = topA;   // or topB, since topA == topB
   1560             bot = topA = topB = SkMin32(botA, botB);
   1561             rowA = iterA.data();
   1562             rowB = iterB.data();
   1563         }
   1564 
   1565         if (top >= bounds.fBottom) {
   1566             break;
   1567         }
   1568 
   1569         if (bot > bounds.fBottom) {
   1570             bot = bounds.fBottom;
   1571         }
   1572         SkASSERT(top < bot);
   1573 
   1574         if (!rowA && !rowB) {
   1575             builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
   1576         } else if (top >= bounds.fTop) {
   1577             SkASSERT(bot <= bounds.fBottom);
   1578             RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
   1579             RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
   1580             operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
   1581         }
   1582 
   1583         adjust_iter(iterA, topA, botA, bot);
   1584         adjust_iter(iterB, topB, botB, bot);
   1585     } while (!iterA.done() || !iterB.done());
   1586 }
   1587 
   1588 bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
   1589                   SkRegion::Op op) {
   1590     AUTO_AACLIP_VALIDATE(*this);
   1591 
   1592     if (SkRegion::kReplace_Op == op) {
   1593         return this->set(clipBOrig);
   1594     }
   1595 
   1596     const SkAAClip* clipA = &clipAOrig;
   1597     const SkAAClip* clipB = &clipBOrig;
   1598 
   1599     if (SkRegion::kReverseDifference_Op == op) {
   1600         SkTSwap(clipA, clipB);
   1601         op = SkRegion::kDifference_Op;
   1602     }
   1603 
   1604     bool a_empty = clipA->isEmpty();
   1605     bool b_empty = clipB->isEmpty();
   1606 
   1607     SkIRect bounds;
   1608     switch (op) {
   1609         case SkRegion::kDifference_Op:
   1610             if (a_empty) {
   1611                 return this->setEmpty();
   1612             }
   1613             if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
   1614                 return this->set(*clipA);
   1615             }
   1616             bounds = clipA->fBounds;
   1617             break;
   1618 
   1619         case SkRegion::kIntersect_Op:
   1620             if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
   1621                                                          clipB->fBounds)) {
   1622                 return this->setEmpty();
   1623             }
   1624             break;
   1625 
   1626         case SkRegion::kUnion_Op:
   1627         case SkRegion::kXOR_Op:
   1628             if (a_empty) {
   1629                 return this->set(*clipB);
   1630             }
   1631             if (b_empty) {
   1632                 return this->set(*clipA);
   1633             }
   1634             bounds = clipA->fBounds;
   1635             bounds.join(clipB->fBounds);
   1636             break;
   1637 
   1638         default:
   1639             SkDEBUGFAIL("unknown region op");
   1640             return !this->isEmpty();
   1641     }
   1642 
   1643     SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
   1644     SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
   1645 
   1646     Builder builder(bounds);
   1647     operateY(builder, *clipA, *clipB, op);
   1648 
   1649     return builder.finish(this);
   1650 }
   1651 
   1652 /*
   1653  *  It can be expensive to build a local aaclip before applying the op, so
   1654  *  we first see if we can restrict the bounds of new rect to our current
   1655  *  bounds, or note that the new rect subsumes our current clip.
   1656  */
   1657 
   1658 bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) {
   1659     SkIRect        rStorage;
   1660     const SkIRect* r = &rOrig;
   1661 
   1662     switch (op) {
   1663         case SkRegion::kIntersect_Op:
   1664             if (!rStorage.intersect(rOrig, fBounds)) {
   1665                 // no overlap, so we're empty
   1666                 return this->setEmpty();
   1667             }
   1668             if (rStorage == fBounds) {
   1669                 // we were wholly inside the rect, no change
   1670                 return !this->isEmpty();
   1671             }
   1672             if (this->quickContains(rStorage)) {
   1673                 // the intersection is wholly inside us, we're a rect
   1674                 return this->setRect(rStorage);
   1675             }
   1676             r = &rStorage;   // use the intersected bounds
   1677             break;
   1678         case SkRegion::kDifference_Op:
   1679             break;
   1680         case SkRegion::kUnion_Op:
   1681             if (rOrig.contains(fBounds)) {
   1682                 return this->setRect(rOrig);
   1683             }
   1684             break;
   1685         default:
   1686             break;
   1687     }
   1688 
   1689     SkAAClip clip;
   1690     clip.setRect(*r);
   1691     return this->op(*this, clip, op);
   1692 }
   1693 
   1694 bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) {
   1695     SkRect        rStorage, boundsStorage;
   1696     const SkRect* r = &rOrig;
   1697 
   1698     boundsStorage.set(fBounds);
   1699     switch (op) {
   1700         case SkRegion::kIntersect_Op:
   1701         case SkRegion::kDifference_Op:
   1702             if (!rStorage.intersect(rOrig, boundsStorage)) {
   1703                 return this->setEmpty();
   1704             }
   1705             r = &rStorage;   // use the intersected bounds
   1706             break;
   1707         case SkRegion::kUnion_Op:
   1708             if (rOrig.contains(boundsStorage)) {
   1709                 return this->setRect(rOrig);
   1710             }
   1711             break;
   1712         default:
   1713             break;
   1714     }
   1715 
   1716     SkAAClip clip;
   1717     clip.setRect(*r, doAA);
   1718     return this->op(*this, clip, op);
   1719 }
   1720 
   1721 bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
   1722     return this->op(*this, clip, op);
   1723 }
   1724 
   1725 ///////////////////////////////////////////////////////////////////////////////
   1726 
   1727 bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
   1728     if (NULL == dst) {
   1729         return !this->isEmpty();
   1730     }
   1731 
   1732     if (this->isEmpty()) {
   1733         return dst->setEmpty();
   1734     }
   1735 
   1736     if (this != dst) {
   1737         sk_atomic_inc(&fRunHead->fRefCnt);
   1738         dst->fRunHead = fRunHead;
   1739         dst->fBounds = fBounds;
   1740     }
   1741     dst->fBounds.offset(dx, dy);
   1742     return true;
   1743 }
   1744 
   1745 static void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
   1746                                const uint8_t* SK_RESTRICT row,
   1747                                int width) {
   1748     while (width > 0) {
   1749         int n = row[0];
   1750         SkASSERT(width >= n);
   1751         memset(mask, row[1], n);
   1752         mask += n;
   1753         row += 2;
   1754         width -= n;
   1755     }
   1756     SkASSERT(0 == width);
   1757 }
   1758 
   1759 void SkAAClip::copyToMask(SkMask* mask) const {
   1760     mask->fFormat = SkMask::kA8_Format;
   1761     if (this->isEmpty()) {
   1762         mask->fBounds.setEmpty();
   1763         mask->fImage = NULL;
   1764         mask->fRowBytes = 0;
   1765         return;
   1766     }
   1767 
   1768     mask->fBounds = fBounds;
   1769     mask->fRowBytes = fBounds.width();
   1770     size_t size = mask->computeImageSize();
   1771     mask->fImage = SkMask::AllocImage(size);
   1772 
   1773     Iter iter(*this);
   1774     uint8_t* dst = mask->fImage;
   1775     const int width = fBounds.width();
   1776 
   1777     int y = fBounds.fTop;
   1778     while (!iter.done()) {
   1779         do {
   1780             expand_row_to_mask(dst, iter.data(), width);
   1781             dst += mask->fRowBytes;
   1782         } while (++y < iter.bottom());
   1783         iter.next();
   1784     }
   1785 }
   1786 
   1787 ///////////////////////////////////////////////////////////////////////////////
   1788 ///////////////////////////////////////////////////////////////////////////////
   1789 
   1790 static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
   1791                          int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
   1792     // we don't read our initial n from data, since the caller may have had to
   1793     // clip it, hence the initialCount parameter.
   1794     int n = initialCount;
   1795     for (;;) {
   1796         if (n > width) {
   1797             n = width;
   1798         }
   1799         SkASSERT(n > 0);
   1800         runs[0] = n;
   1801         runs += n;
   1802 
   1803         aa[0] = data[1];
   1804         aa += n;
   1805 
   1806         data += 2;
   1807         width -= n;
   1808         if (0 == width) {
   1809             break;
   1810         }
   1811         // load the next count
   1812         n = data[0];
   1813     }
   1814     runs[0] = 0;    // sentinel
   1815 }
   1816 
   1817 SkAAClipBlitter::~SkAAClipBlitter() {
   1818     sk_free(fScanlineScratch);
   1819 }
   1820 
   1821 void SkAAClipBlitter::ensureRunsAndAA() {
   1822     if (NULL == fScanlineScratch) {
   1823         // add 1 so we can store the terminating run count of 0
   1824         int count = fAAClipBounds.width() + 1;
   1825         // we use this either for fRuns + fAA, or a scaline of a mask
   1826         // which may be as deep as 32bits
   1827         fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
   1828         fRuns = (int16_t*)fScanlineScratch;
   1829         fAA = (SkAlpha*)(fRuns + count);
   1830     }
   1831 }
   1832 
   1833 void SkAAClipBlitter::blitH(int x, int y, int width) {
   1834     SkASSERT(width > 0);
   1835     SkASSERT(fAAClipBounds.contains(x, y));
   1836     SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
   1837 
   1838     int lastY;
   1839     const uint8_t* row = fAAClip->findRow(y, &lastY);
   1840     int initialCount;
   1841     row = fAAClip->findX(row, x, &initialCount);
   1842 
   1843     if (initialCount >= width) {
   1844         SkAlpha alpha = row[1];
   1845         if (0 == alpha) {
   1846             return;
   1847         }
   1848         if (0xFF == alpha) {
   1849             fBlitter->blitH(x, y, width);
   1850             return;
   1851         }
   1852     }
   1853 
   1854     this->ensureRunsAndAA();
   1855     expandToRuns(row, initialCount, width, fRuns, fAA);
   1856 
   1857     fBlitter->blitAntiH(x, y, fAA, fRuns);
   1858 }
   1859 
   1860 static void merge(const uint8_t* SK_RESTRICT row, int rowN,
   1861                   const SkAlpha* SK_RESTRICT srcAA,
   1862                   const int16_t* SK_RESTRICT srcRuns,
   1863                   SkAlpha* SK_RESTRICT dstAA,
   1864                   int16_t* SK_RESTRICT dstRuns,
   1865                   int width) {
   1866     SkDEBUGCODE(int accumulated = 0;)
   1867     int srcN = srcRuns[0];
   1868     // do we need this check?
   1869     if (0 == srcN) {
   1870         return;
   1871     }
   1872 
   1873     for (;;) {
   1874         SkASSERT(rowN > 0);
   1875         SkASSERT(srcN > 0);
   1876 
   1877         unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
   1878         int minN = SkMin32(srcN, rowN);
   1879         dstRuns[0] = minN;
   1880         dstRuns += minN;
   1881         dstAA[0] = newAlpha;
   1882         dstAA += minN;
   1883 
   1884         if (0 == (srcN -= minN)) {
   1885             srcN = srcRuns[0];  // refresh
   1886             srcRuns += srcN;
   1887             srcAA += srcN;
   1888             srcN = srcRuns[0];  // reload
   1889             if (0 == srcN) {
   1890                 break;
   1891             }
   1892         }
   1893         if (0 == (rowN -= minN)) {
   1894             row += 2;
   1895             rowN = row[0];  // reload
   1896         }
   1897 
   1898         SkDEBUGCODE(accumulated += minN;)
   1899         SkASSERT(accumulated <= width);
   1900     }
   1901     dstRuns[0] = 0;
   1902 }
   1903 
   1904 void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
   1905                                 const int16_t runs[]) {
   1906     int lastY;
   1907     const uint8_t* row = fAAClip->findRow(y, &lastY);
   1908     int initialCount;
   1909     row = fAAClip->findX(row, x, &initialCount);
   1910 
   1911     this->ensureRunsAndAA();
   1912 
   1913     merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
   1914     fBlitter->blitAntiH(x, y, fAA, fRuns);
   1915 }
   1916 
   1917 void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
   1918     if (fAAClip->quickContains(x, y, x + 1, y + height)) {
   1919         fBlitter->blitV(x, y, height, alpha);
   1920         return;
   1921     }
   1922 
   1923     for (;;) {
   1924         int lastY;
   1925         const uint8_t* row = fAAClip->findRow(y, &lastY);
   1926         int dy = lastY - y + 1;
   1927         if (dy > height) {
   1928             dy = height;
   1929         }
   1930         height -= dy;
   1931 
   1932         int initialCount;
   1933         row = fAAClip->findX(row, x, &initialCount);
   1934         SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
   1935         if (newAlpha) {
   1936             fBlitter->blitV(x, y, dy, newAlpha);
   1937         }
   1938         SkASSERT(height >= 0);
   1939         if (height <= 0) {
   1940             break;
   1941         }
   1942         y = lastY + 1;
   1943     }
   1944 }
   1945 
   1946 void SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
   1947     if (fAAClip->quickContains(x, y, x + width, y + height)) {
   1948         fBlitter->blitRect(x, y, width, height);
   1949         return;
   1950     }
   1951 
   1952     while (--height >= 0) {
   1953         this->blitH(x, y, width);
   1954         y += 1;
   1955     }
   1956 }
   1957 
   1958 typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
   1959                             int initialRowCount, void* dst);
   1960 
   1961 static void small_memcpy(void* dst, const void* src, size_t n) {
   1962     memcpy(dst, src, n);
   1963 }
   1964 
   1965 static void small_bzero(void* dst, size_t n) {
   1966     sk_bzero(dst, n);
   1967 }
   1968 
   1969 static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
   1970     return SkMulDiv255Round(value, alpha);
   1971 }
   1972 static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
   1973     unsigned r = SkGetPackedR16(value);
   1974     unsigned g = SkGetPackedG16(value);
   1975     unsigned b = SkGetPackedB16(value);
   1976     return SkPackRGB16(SkMulDiv255Round(r, alpha),
   1977                        SkMulDiv255Round(r, alpha),
   1978                        SkMulDiv255Round(r, alpha));
   1979 }
   1980 static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
   1981     unsigned a = SkGetPackedA32(value);
   1982     unsigned r = SkGetPackedR32(value);
   1983     unsigned g = SkGetPackedG32(value);
   1984     unsigned b = SkGetPackedB32(value);
   1985     return SkPackARGB32(SkMulDiv255Round(a, alpha),
   1986                         SkMulDiv255Round(r, alpha),
   1987                         SkMulDiv255Round(g, alpha),
   1988                         SkMulDiv255Round(b, alpha));
   1989 }
   1990 
   1991 template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
   1992                                  const uint8_t* SK_RESTRICT row, int rowN,
   1993                                  T* SK_RESTRICT dst) {
   1994     SkDEBUGCODE(int accumulated = 0;)
   1995     for (;;) {
   1996         SkASSERT(rowN > 0);
   1997         SkASSERT(srcN > 0);
   1998 
   1999         int n = SkMin32(rowN, srcN);
   2000         unsigned rowA = row[1];
   2001         if (0xFF == rowA) {
   2002             small_memcpy(dst, src, n * sizeof(T));
   2003         } else if (0 == rowA) {
   2004             small_bzero(dst, n * sizeof(T));
   2005         } else {
   2006             for (int i = 0; i < n; ++i) {
   2007                 dst[i] = mergeOne(src[i], rowA);
   2008             }
   2009         }
   2010 
   2011         if (0 == (srcN -= n)) {
   2012             break;
   2013         }
   2014 
   2015         src += n;
   2016         dst += n;
   2017 
   2018         SkASSERT(rowN == n);
   2019         row += 2;
   2020         rowN = row[0];
   2021     }
   2022 }
   2023 
   2024 static MergeAAProc find_merge_aa_proc(SkMask::Format format) {
   2025     switch (format) {
   2026         case SkMask::kBW_Format:
   2027             SkDEBUGFAIL("unsupported");
   2028             return NULL;
   2029         case SkMask::kA8_Format:
   2030         case SkMask::k3D_Format: {
   2031             void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT;
   2032             return (MergeAAProc)proc8;
   2033         }
   2034         case SkMask::kLCD16_Format: {
   2035             void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT;
   2036             return (MergeAAProc)proc16;
   2037         }
   2038         case SkMask::kLCD32_Format: {
   2039             void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT;
   2040             return (MergeAAProc)proc32;
   2041         }
   2042         default:
   2043             SkDEBUGFAIL("unsupported");
   2044             return NULL;
   2045     }
   2046 }
   2047 
   2048 static U8CPU bit2byte(int bitInAByte) {
   2049     SkASSERT(bitInAByte <= 0xFF);
   2050     // negation turns any non-zero into 0xFFFFFF??, so we just shift down
   2051     // some value >= 8 to get a full FF value
   2052     return -bitInAByte >> 8;
   2053 }
   2054 
   2055 static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
   2056     SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
   2057     SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
   2058 
   2059     const int width = srcMask.fBounds.width();
   2060     const int height = srcMask.fBounds.height();
   2061 
   2062     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
   2063     const size_t srcRB = srcMask.fRowBytes;
   2064     uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage;
   2065     const size_t dstRB = dstMask->fRowBytes;
   2066 
   2067     const int wholeBytes = width >> 3;
   2068     const int leftOverBits = width & 7;
   2069 
   2070     for (int y = 0; y < height; ++y) {
   2071         uint8_t* SK_RESTRICT d = dst;
   2072         for (int i = 0; i < wholeBytes; ++i) {
   2073             int srcByte = src[i];
   2074             d[0] = bit2byte(srcByte & (1 << 7));
   2075             d[1] = bit2byte(srcByte & (1 << 6));
   2076             d[2] = bit2byte(srcByte & (1 << 5));
   2077             d[3] = bit2byte(srcByte & (1 << 4));
   2078             d[4] = bit2byte(srcByte & (1 << 3));
   2079             d[5] = bit2byte(srcByte & (1 << 2));
   2080             d[6] = bit2byte(srcByte & (1 << 1));
   2081             d[7] = bit2byte(srcByte & (1 << 0));
   2082             d += 8;
   2083         }
   2084         if (leftOverBits) {
   2085             int srcByte = src[wholeBytes];
   2086             for (int x = 0; x < leftOverBits; ++x) {
   2087                 *d++ = bit2byte(srcByte & 0x80);
   2088                 srcByte <<= 1;
   2089             }
   2090         }
   2091         src += srcRB;
   2092         dst += dstRB;
   2093     }
   2094 }
   2095 
   2096 void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
   2097     SkASSERT(fAAClip->getBounds().contains(clip));
   2098 
   2099     if (fAAClip->quickContains(clip)) {
   2100         fBlitter->blitMask(origMask, clip);
   2101         return;
   2102     }
   2103 
   2104     const SkMask* mask = &origMask;
   2105 
   2106     // if we're BW, we need to upscale to A8 (ugh)
   2107     SkMask  grayMask;
   2108     grayMask.fImage = NULL;
   2109     if (SkMask::kBW_Format == origMask.fFormat) {
   2110         grayMask.fFormat = SkMask::kA8_Format;
   2111         grayMask.fBounds = origMask.fBounds;
   2112         grayMask.fRowBytes = origMask.fBounds.width();
   2113         size_t size = grayMask.computeImageSize();
   2114         grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size,
   2115                                                SkAutoMalloc::kReuse_OnShrink);
   2116 
   2117         upscaleBW2A8(&grayMask, origMask);
   2118         mask = &grayMask;
   2119     }
   2120 
   2121     this->ensureRunsAndAA();
   2122 
   2123     // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
   2124     // data into a temp block to support it better (ugh)
   2125 
   2126     const void* src = mask->getAddr(clip.fLeft, clip.fTop);
   2127     const size_t srcRB = mask->fRowBytes;
   2128     const int width = clip.width();
   2129     MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
   2130 
   2131     SkMask rowMask;
   2132     rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
   2133     rowMask.fBounds.fLeft = clip.fLeft;
   2134     rowMask.fBounds.fRight = clip.fRight;
   2135     rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1
   2136     rowMask.fImage = (uint8_t*)fScanlineScratch;
   2137 
   2138     int y = clip.fTop;
   2139     const int stopY = y + clip.height();
   2140 
   2141     do {
   2142         int localStopY;
   2143         const uint8_t* row = fAAClip->findRow(y, &localStopY);
   2144         // findRow returns last Y, not stop, so we add 1
   2145         localStopY = SkMin32(localStopY + 1, stopY);
   2146 
   2147         int initialCount;
   2148         row = fAAClip->findX(row, clip.fLeft, &initialCount);
   2149         do {
   2150             mergeProc(src, width, row, initialCount, rowMask.fImage);
   2151             rowMask.fBounds.fTop = y;
   2152             rowMask.fBounds.fBottom = y + 1;
   2153             fBlitter->blitMask(rowMask, rowMask.fBounds);
   2154             src = (const void*)((const char*)src + srcRB);
   2155         } while (++y < localStopY);
   2156     } while (y < stopY);
   2157 }
   2158 
   2159 const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
   2160     return NULL;
   2161 }
   2162 
   2163