LCOV - app.info - gfx/skia/src/core/SkAAClip.cpp

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