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