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