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