LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkAAClip.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1234 0 0.0 %
Date: 2012-06-02 Functions: 116 0 0.0 %

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

Generated by: LCOV version 1.7