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