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