SkAAClip.cpp revision 209c41511eb0d06f8c19f8fb1fc0393c502a1b18
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        return;
139    }
140
141    const RunHead* head = clip.fRunHead;
142    fCurrYOff = head->yoffsets();
143    fStopYOff = fCurrYOff + head->fRowCount;
144    fData     = head->data() + fCurrYOff->fOffset;
145
146    // setup first value
147    fTop = clip.fBounds.fTop;
148    fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1;
149    fDone = false;
150}
151
152void SkAAClip::Iter::next() {
153    if (!fDone) {
154        const YOffset* prev = fCurrYOff;
155        const YOffset* curr = prev + 1;
156        SkASSERT(curr <= fStopYOff);
157
158        fTop = fBottom;
159        if (curr >= fStopYOff) {
160            fDone = true;
161            fBottom = kMaxInt32;
162            fData = NULL;
163        } else {
164            fBottom += curr->fY - prev->fY;
165            fData += curr->fOffset - prev->fOffset;
166            fCurrYOff = curr;
167        }
168    }
169}
170
171#ifdef SK_DEBUG
172static size_t compute_row_length(const uint8_t row[], int width) {
173    const uint8_t* origRow = row;
174    while (width > 0) {
175        int n = row[0];
176        SkASSERT(n <= width);
177        row += 2;
178        width -= n;
179    }
180    SkASSERT(0 == width);
181    return row - origRow;
182}
183
184void SkAAClip::validate() const {
185    if (NULL == fRunHead) {
186        SkASSERT(fBounds.isEmpty());
187        return;
188    }
189
190    const RunHead* head = fRunHead;
191    SkASSERT(head->fRefCnt > 0);
192    SkASSERT(head->fRowCount > 0);
193    SkASSERT(head->fDataSize > 0);
194
195    const YOffset* yoff = head->yoffsets();
196    const YOffset* ystop = yoff + head->fRowCount;
197    const uint8_t* row = head->data();
198    SkASSERT(0 == yoff->fOffset);
199    // y values must be monotonic
200    int y = -1;
201    int32_t offset = -1;
202    size_t computedOffset = 0;
203    while (yoff < ystop) {
204        SkASSERT(y < yoff->fY);
205        y = yoff->fY;
206        SkASSERT(offset < (int32_t)yoff->fOffset);
207        offset = yoff->fOffset;
208        SkASSERT(yoff->fOffset == computedOffset);
209        yoff += 1;
210
211        size_t rowLength = compute_row_length(row, fBounds.width());
212        row += rowLength;
213        computedOffset += rowLength;
214    }
215    SkASSERT(head->fDataSize == computedOffset);
216    // check the last entry;
217    --yoff;
218    SkASSERT(yoff->fY == fBounds.height() - 1);
219
220}
221#endif
222
223///////////////////////////////////////////////////////////////////////////////
224
225// can't validate before we're done, since trimming is part of the process of
226// making us valid after the Builder. Since we build from top to bottom, its
227// possible our fBounds.fBottom is bigger than our last scanline of data, so
228// we trim fBounds.fBottom back up.
229//
230// TODO: look to trim our bounds on top, left, right.
231// TODO: check for duplicates in X and Y to further compress our data
232//
233bool SkAAClip::trimBounds() {
234    if (this->isEmpty()) {
235        return false;
236    }
237
238    const RunHead* head = fRunHead;
239    const YOffset* yoff = head->yoffsets();
240
241    SkASSERT(head->fRowCount > 0);
242    const YOffset& lastY = yoff[head->fRowCount - 1];
243    SkASSERT(lastY.fY + 1 <= fBounds.height());
244    fBounds.fBottom = fBounds.fTop + lastY.fY + 1;
245    SkASSERT(lastY.fY + 1 == fBounds.height());
246    return true;
247}
248
249///////////////////////////////////////////////////////////////////////////////
250
251void SkAAClip::freeRuns() {
252    if (fRunHead) {
253        SkASSERT(fRunHead->fRefCnt >= 1);
254        if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) {
255            sk_free(fRunHead);
256        }
257    }
258}
259
260SkAAClip::SkAAClip() {
261    fBounds.setEmpty();
262    fRunHead = NULL;
263}
264
265SkAAClip::SkAAClip(const SkAAClip& src) {
266    SkDEBUGCODE(fBounds.setEmpty();)    // need this for validate
267    fRunHead = NULL;
268    *this = src;
269}
270
271SkAAClip::~SkAAClip() {
272    this->freeRuns();
273}
274
275SkAAClip& SkAAClip::operator=(const SkAAClip& src) {
276    AUTO_AACLIP_VALIDATE(*this);
277    src.validate();
278
279    if (this != &src) {
280        this->freeRuns();
281        fBounds = src.fBounds;
282        fRunHead = src.fRunHead;
283        if (fRunHead) {
284            sk_atomic_inc(&fRunHead->fRefCnt);
285        }
286    }
287    return *this;
288}
289
290bool operator==(const SkAAClip& a, const SkAAClip& b) {
291    a.validate();
292    b.validate();
293
294    if (&a == &b) {
295        return true;
296    }
297    if (a.fBounds != b.fBounds) {
298        return false;
299    }
300
301    const SkAAClip::RunHead* ah = a.fRunHead;
302    const SkAAClip::RunHead* bh = b.fRunHead;
303
304    // this catches empties and rects being equal
305    if (ah == bh) {
306        return true;
307    }
308
309    // now we insist that both are complex (but different ptrs)
310    if (!a.fRunHead || !b.fRunHead) {
311        return false;
312    }
313
314    return  ah->fRowCount == bh->fRowCount &&
315            ah->fDataSize == bh->fDataSize &&
316            !memcmp(ah->data(), bh->data(), ah->fDataSize);
317}
318
319void SkAAClip::swap(SkAAClip& other) {
320    AUTO_AACLIP_VALIDATE(*this);
321    other.validate();
322
323    SkTSwap(fBounds, other.fBounds);
324    SkTSwap(fRunHead, other.fRunHead);
325}
326
327bool SkAAClip::set(const SkAAClip& src) {
328    *this = src;
329    return !this->isEmpty();
330}
331
332bool SkAAClip::setEmpty() {
333    this->freeRuns();
334    fBounds.setEmpty();
335    fRunHead = NULL;
336    return false;
337}
338
339bool SkAAClip::setRect(const SkIRect& bounds) {
340    if (bounds.isEmpty()) {
341        return this->setEmpty();
342    }
343
344    AUTO_AACLIP_VALIDATE(*this);
345
346#if 0
347    SkRect r;
348    r.set(bounds);
349    SkPath path;
350    path.addRect(r);
351    return this->setPath(path);
352#else
353    this->freeRuns();
354    fBounds = bounds;
355    fRunHead = RunHead::AllocRect(bounds);
356    SkASSERT(!this->isEmpty());
357    return true;
358#endif
359}
360
361bool SkAAClip::setRect(const SkRect& r, bool doAA) {
362    if (r.isEmpty()) {
363        return this->setEmpty();
364    }
365
366    AUTO_AACLIP_VALIDATE(*this);
367
368    // TODO: special case this
369
370    SkPath path;
371    path.addRect(r);
372    return this->setPath(path, NULL, doAA);
373}
374
375bool SkAAClip::setRegion(const SkRegion& rgn) {
376    if (rgn.isEmpty()) {
377        return this->setEmpty();
378    }
379    if (rgn.isRect()) {
380        return this->setRect(rgn.getBounds());
381    }
382
383    SkAAClip clip;
384    SkRegion::Iterator iter(rgn);
385    for (; !iter.done(); iter.next()) {
386        clip.op(iter.rect(), SkRegion::kUnion_Op);
387    }
388    this->swap(clip);
389    return !this->isEmpty();
390}
391
392///////////////////////////////////////////////////////////////////////////////
393
394const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
395    SkASSERT(fRunHead);
396
397    if (!y_in_rect(y, fBounds)) {
398        return NULL;
399    }
400    y -= fBounds.y();  // our yoffs values are relative to the top
401
402    const YOffset* yoff = fRunHead->yoffsets();
403    while (yoff->fY < y) {
404        yoff += 1;
405        SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
406    }
407
408    if (lastYForRow) {
409        *lastYForRow = fBounds.y() + yoff->fY;
410    }
411    return fRunHead->data() + yoff->fOffset;
412}
413
414const uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
415    SkASSERT(x_in_rect(x, fBounds));
416    x -= fBounds.x();
417
418    // first skip up to X
419    for (;;) {
420        int n = data[0];
421        if (x < n) {
422            *initialCount = n - x;
423            break;
424        }
425        data += 2;
426        x -= n;
427    }
428    return data;
429}
430
431bool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
432    if (this->isEmpty()) {
433        return false;
434    }
435    if (!fBounds.contains(left, top, right, bottom)) {
436        return false;
437    }
438#if 0
439    if (this->isRect()) {
440        return true;
441    }
442#endif
443
444    int lastY;
445    const uint8_t* row = this->findRow(top, &lastY);
446    if (lastY < bottom) {
447        return false;
448    }
449    // now just need to check in X
450    int count;
451    row = this->findX(row, left, &count);
452#if 0
453    return count >= (right - left) && 0xFF == row[1];
454#else
455    int rectWidth = right - left;
456    while (0xFF == row[1]) {
457        if (count >= rectWidth) {
458            return true;
459        }
460        rectWidth -= count;
461        row += 2;
462        count = row[0];
463    }
464    return false;
465#endif
466}
467
468///////////////////////////////////////////////////////////////////////////////
469
470class SkAAClip::Builder {
471    SkIRect fBounds;
472    struct Row {
473        int fY;
474        int fWidth;
475        SkTDArray<uint8_t>* fData;
476    };
477    SkTDArray<Row>  fRows;
478    Row* fCurrRow;
479    int fPrevY;
480    int fWidth;
481    int fMinY;
482
483public:
484    Builder(const SkIRect& bounds) : fBounds(bounds) {
485        fPrevY = -1;
486        fWidth = bounds.width();
487        fCurrRow = NULL;
488        fMinY = bounds.fTop;
489    }
490
491    ~Builder() {
492        Row* row = fRows.begin();
493        Row* stop = fRows.end();
494        while (row < stop) {
495            delete row->fData;
496            row += 1;
497        }
498    }
499
500    const SkIRect& getBounds() const { return fBounds; }
501
502    void addRun(int x, int y, U8CPU alpha, int count) {
503        SkASSERT(count > 0);
504        SkASSERT(fBounds.contains(x, y));
505        SkASSERT(fBounds.contains(x + count - 1, y));
506
507        x -= fBounds.left();
508        y -= fBounds.top();
509
510        Row* row = fCurrRow;
511        if (y != fPrevY) {
512            SkASSERT(y > fPrevY);
513            fPrevY = y;
514            row = this->flushRow(true);
515            row->fY = y;
516            row->fWidth = 0;
517            SkASSERT(row->fData);
518            SkASSERT(0 == row->fData->count());
519            fCurrRow = row;
520        }
521
522        SkASSERT(row->fWidth <= x);
523        SkASSERT(row->fWidth < fBounds.width());
524
525        SkTDArray<uint8_t>& data = *row->fData;
526
527        int gap = x - row->fWidth;
528        if (gap) {
529            AppendRun(data, 0, gap);
530            row->fWidth += gap;
531            SkASSERT(row->fWidth < fBounds.width());
532        }
533
534        AppendRun(data, alpha, count);
535        row->fWidth += count;
536        SkASSERT(row->fWidth <= fBounds.width());
537    }
538
539    bool finish(SkAAClip* target) {
540        this->flushRow(false);
541
542        const Row* row = fRows.begin();
543        const Row* stop = fRows.end();
544
545        size_t dataSize = 0;
546        while (row < stop) {
547            dataSize += row->fData->count();
548            row += 1;
549        }
550
551        if (0 == dataSize) {
552            return target->setEmpty();
553        }
554
555        SkASSERT(fMinY >= fBounds.fTop);
556        SkASSERT(fMinY < fBounds.fBottom);
557        int adjustY = fMinY - fBounds.fTop;
558        fBounds.fTop = fMinY;
559
560        RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
561        YOffset* yoffset = head->yoffsets();
562        uint8_t* data = head->data();
563        uint8_t* baseData = data;
564
565        row = fRows.begin();
566        while (row < stop) {
567            yoffset->fY = row->fY - adjustY;
568            yoffset->fOffset = data - baseData;
569            yoffset += 1;
570
571            size_t n = row->fData->count();
572            memcpy(data, row->fData->begin(), n);
573            data += n;
574
575            row += 1;
576        }
577
578        target->freeRuns();
579        target->fBounds = fBounds;
580        target->fRunHead = head;
581        return target->trimBounds();
582    }
583
584    void dump() {
585        this->validate();
586        int y;
587        for (y = 0; y < fRows.count(); ++y) {
588            const Row& row = fRows[y];
589            SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
590            const SkTDArray<uint8_t>& data = *row.fData;
591            int count = data.count();
592            SkASSERT(!(count & 1));
593            const uint8_t* ptr = data.begin();
594            for (int x = 0; x < count; x += 2) {
595                SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
596                ptr += 2;
597            }
598            SkDebugf("\n");
599        }
600    }
601
602    void validate() {
603#ifdef SK_DEBUG
604        int prevY = -1;
605        for (int i = 0; i < fRows.count(); ++i) {
606            const Row& row = fRows[i];
607            SkASSERT(prevY < row.fY);
608            SkASSERT(fWidth == row.fWidth);
609            int count = row.fData->count();
610            const uint8_t* ptr = row.fData->begin();
611            SkASSERT(!(count & 1));
612            int w = 0;
613            for (int x = 0; x < count; x += 2) {
614                w += ptr[0];
615                SkASSERT(w <= fWidth);
616                ptr += 2;
617            }
618            SkASSERT(w == fWidth);
619            prevY = row.fY;
620        }
621#endif
622    }
623
624    // only called by BuilderBlitter
625    void setMinY(int y) {
626        fMinY = y;
627    }
628
629private:
630
631    Row* flushRow(bool readyForAnother) {
632        Row* next = NULL;
633        int count = fRows.count();
634        if (count > 0) {
635            // flush current row if needed
636            Row* curr = &fRows[count - 1];
637            if (curr->fWidth < fWidth) {
638                AppendRun(*curr->fData, 0, fWidth - curr->fWidth);
639                curr->fWidth = fWidth;
640            }
641        }
642        if (count > 1) {
643            // are our last two runs the same?
644            Row* prev = &fRows[count - 2];
645            Row* curr = &fRows[count - 1];
646            SkASSERT(prev->fWidth == fWidth);
647            SkASSERT(curr->fWidth == fWidth);
648            if (*prev->fData == *curr->fData) {
649                prev->fY = curr->fY;
650                if (readyForAnother) {
651                    curr->fData->rewind();
652                    next = curr;
653                } else {
654                    delete curr->fData;
655                    fRows.removeShuffle(count - 1);
656                }
657            } else {
658                if (readyForAnother) {
659                    next = fRows.append();
660                    next->fData = new SkTDArray<uint8_t>;
661                }
662            }
663        } else {
664            if (readyForAnother) {
665                next = fRows.append();
666                next->fData = new SkTDArray<uint8_t>;
667            }
668        }
669        return next;
670    }
671
672    static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
673        do {
674            int n = count;
675            if (n > 255) {
676                n = 255;
677            }
678            uint8_t* ptr = data.append(2);
679            ptr[0] = n;
680            ptr[1] = alpha;
681            count -= n;
682        } while (count > 0);
683    }
684};
685
686class SkAAClip::BuilderBlitter : public SkBlitter {
687public:
688    BuilderBlitter(Builder* builder) {
689        fBuilder = builder;
690        fLeft = builder->getBounds().fLeft;
691        fRight = builder->getBounds().fRight;
692        fMinY = SK_MaxS32;
693    }
694
695    void finish() {
696        if (fMinY < SK_MaxS32) {
697            fBuilder->setMinY(fMinY);
698        }
699    }
700
701    virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE
702        { unexpected(); }
703
704    //  let the default impl call blitH
705//    virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE
706
707    virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
708        { unexpected(); }
709
710    virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE {
711        return NULL;
712    }
713
714    virtual void blitH(int x, int y, int width) SK_OVERRIDE {
715        this->recordMinY(y);
716        fBuilder->addRun(x, y, 0xFF, width);
717    }
718
719    virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
720                           const int16_t runs[]) SK_OVERRIDE {
721        this->recordMinY(y);
722        for (;;) {
723            int count = *runs;
724            if (count <= 0) {
725                return;
726            }
727
728            // The supersampler's buffer can be the width of the device, so
729            // we may have to trim the run to our bounds. If so, we assert that
730            // the extra spans are always alpha==0
731            int localX = x;
732            int localCount = count;
733            if (x < fLeft) {
734                SkASSERT(0 == *alpha);
735                int gap = fLeft - x;
736                SkASSERT(gap <= count);
737                localX += gap;
738                localCount -= gap;
739            }
740            int right = x + count;
741            if (right > fRight) {
742                SkASSERT(0 == *alpha);
743                localCount -= right - fRight;
744                SkASSERT(localCount >= 0);
745            }
746
747            if (localCount) {
748                fBuilder->addRun(localX, y, *alpha, localCount);
749            }
750            // Next run
751            runs += count;
752            alpha += count;
753            x += count;
754        }
755    }
756
757private:
758    Builder* fBuilder;
759    int      fLeft; // cache of builder's bounds' left edge
760    int      fRight;
761    int      fMinY;
762
763    /*
764     *  We track this, in case the scan converter skipped some number of
765     *  scanlines at the (relative to the bounds it was given). This allows
766     *  the builder, during its finish, to trip its bounds down to the "real"
767     *  top.
768     */
769    void recordMinY(int y) {
770        if (y < fMinY) {
771            fMinY = y;
772        }
773    }
774
775    void unexpected() {
776        SkDebugf("---- did not expect to get called here");
777        sk_throw();
778    }
779};
780
781bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
782    AUTO_AACLIP_VALIDATE(*this);
783
784    if (clip && clip->isEmpty()) {
785        return this->setEmpty();
786    }
787
788    SkIRect ibounds;
789    path.getBounds().roundOut(&ibounds);
790
791    SkRegion tmpClip;
792    if (NULL == clip) {
793        tmpClip.setRect(ibounds);
794        clip = &tmpClip;
795    }
796
797    if (path.isInverseFillType()) {
798        ibounds = clip->getBounds();
799    } else {
800        if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
801            return this->setEmpty();
802        }
803    }
804
805    Builder        builder(ibounds);
806    BuilderBlitter blitter(&builder);
807
808    if (doAA) {
809        SkScan::AntiFillPath(path, *clip, &blitter, true);
810    } else {
811        SkScan::FillPath(path, *clip, &blitter);
812    }
813
814    blitter.finish();
815    return builder.finish(this);
816}
817
818///////////////////////////////////////////////////////////////////////////////
819
820typedef void (*RowProc)(SkAAClip::Builder&, int bottom,
821                        const uint8_t* rowA, const SkIRect& rectA,
822                        const uint8_t* rowB, const SkIRect& rectB);
823
824static void sectRowProc(SkAAClip::Builder& builder, int bottom,
825                        const uint8_t* rowA, const SkIRect& rectA,
826                        const uint8_t* rowB, const SkIRect& rectB) {
827
828}
829
830typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
831
832static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
833    // Multiply
834    return SkMulDiv255Round(alphaA, alphaB);
835}
836
837static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
838    // SrcOver
839    return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
840}
841
842static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
843    // SrcOut
844    return SkMulDiv255Round(alphaA, 0xFF - alphaB);
845}
846
847static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
848    // XOR
849    return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
850}
851
852static AlphaProc find_alpha_proc(SkRegion::Op op) {
853    switch (op) {
854        case SkRegion::kIntersect_Op:
855            return sectAlphaProc;
856        case SkRegion::kDifference_Op:
857            return diffAlphaProc;
858        case SkRegion::kUnion_Op:
859            return unionAlphaProc;
860        case SkRegion::kXOR_Op:
861            return xorAlphaProc;
862        default:
863            SkASSERT(!"unexpected region op");
864            return sectAlphaProc;
865    }
866}
867
868static const uint8_t gEmptyRow[] = {
869    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
870    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
871    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
872    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
873    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
874    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
875    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
876    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
877};
878
879class RowIter {
880public:
881    RowIter(const uint8_t* row, const SkIRect& bounds) {
882        fRow = row;
883        fLeft = bounds.fLeft;
884        fBoundsRight = bounds.fRight;
885        if (row) {
886            fRight = bounds.fLeft + row[0];
887            SkASSERT(fRight <= fBoundsRight);
888            fAlpha = row[1];
889            fDone = false;
890        } else {
891            fDone = true;
892            fRight = kMaxInt32;
893            fAlpha = 0;
894        }
895    }
896
897    bool done() const { return fDone; }
898    int left() const { return fLeft; }
899    int right() const { return fRight; }
900    U8CPU alpha() const { return fAlpha; }
901    void next() {
902        if (!fDone) {
903            fLeft = fRight;
904            if (fRight == fBoundsRight) {
905                fDone = true;
906                fRight = kMaxInt32;
907                fAlpha = 0;
908            } else {
909                fRow += 2;
910                fRight += fRow[0];
911                fAlpha = fRow[1];
912                SkASSERT(fRight <= fBoundsRight);
913            }
914        }
915    }
916
917private:
918    const uint8_t*  fRow;
919    int             fLeft;
920    int             fRight;
921    int             fBoundsRight;
922    bool            fDone;
923    uint8_t         fAlpha;
924};
925
926static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
927    if (rite == riteA) {
928        iter.next();
929        leftA = iter.left();
930        riteA = iter.right();
931    }
932}
933
934static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
935    SkASSERT(min < max);
936    SkASSERT(boundsMin < boundsMax);
937    if (min >= boundsMax || max <= boundsMin) {
938        return false;
939    }
940    if (min < boundsMin) {
941        min = boundsMin;
942    }
943    if (max > boundsMax) {
944        max = boundsMax;
945    }
946    return true;
947}
948
949static void operatorX(SkAAClip::Builder& builder, int lastY,
950                      RowIter& iterA, RowIter& iterB,
951                      AlphaProc proc, const SkIRect& bounds) {
952    int leftA = iterA.left();
953    int riteA = iterA.right();
954    int leftB = iterB.left();
955    int riteB = iterB.right();
956
957    int prevRite = bounds.fLeft;
958
959    do {
960        U8CPU alphaA = 0;
961        U8CPU alphaB = 0;
962        int left, rite;
963
964        if (leftA < leftB) {
965            left = leftA;
966            alphaA = iterA.alpha();
967            if (riteA <= leftB) {
968                rite = riteA;
969            } else {
970                rite = leftA = leftB;
971            }
972        } else if (leftB < leftA) {
973            left = leftB;
974            alphaB = iterB.alpha();
975            if (riteB <= leftA) {
976                rite = riteB;
977            } else {
978                rite = leftB = leftA;
979            }
980        } else {
981            left = leftA;   // or leftB, since leftA == leftB
982            rite = leftA = leftB = SkMin32(riteA, riteB);
983            alphaA = iterA.alpha();
984            alphaB = iterB.alpha();
985        }
986
987        if (left >= bounds.fRight) {
988            break;
989        }
990        if (rite > bounds.fRight) {
991            rite = bounds.fRight;
992        }
993
994        if (left >= bounds.fLeft) {
995            SkASSERT(rite > left);
996            builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
997            prevRite = rite;
998        }
999
1000        adjust_row(iterA, leftA, riteA, rite);
1001        adjust_row(iterB, leftB, riteB, rite);
1002    } while (!iterA.done() || !iterB.done());
1003
1004    if (prevRite < bounds.fRight) {
1005        builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
1006    }
1007}
1008
1009static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
1010    if (bot == botA) {
1011        iter.next();
1012        topA = botA;
1013        SkASSERT(botA == iter.top());
1014        botA = iter.bottom();
1015    }
1016}
1017
1018static void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
1019                     const SkAAClip& B, SkRegion::Op op) {
1020    AlphaProc proc = find_alpha_proc(op);
1021    const SkIRect& bounds = builder.getBounds();
1022
1023    SkAAClip::Iter iterA(A);
1024    SkAAClip::Iter iterB(B);
1025
1026    SkASSERT(!iterA.done());
1027    int topA = iterA.top();
1028    int botA = iterA.bottom();
1029    SkASSERT(!iterB.done());
1030    int topB = iterB.top();
1031    int botB = iterB.bottom();
1032
1033    do {
1034        const uint8_t* rowA = NULL;
1035        const uint8_t* rowB = NULL;
1036        int top, bot;
1037
1038        if (topA < topB) {
1039            top = topA;
1040            rowA = iterA.data();
1041            if (botA <= topB) {
1042                bot = botA;
1043            } else {
1044                bot = topA = topB;
1045            }
1046
1047        } else if (topB < topA) {
1048            top = topB;
1049            rowB = iterB.data();
1050            if (botB <= topA) {
1051                bot = botB;
1052            } else {
1053                bot = topB = topA;
1054            }
1055        } else {
1056            top = topA;   // or topB, since topA == topB
1057            bot = topA = topB = SkMin32(botA, botB);
1058            rowA = iterA.data();
1059            rowB = iterB.data();
1060        }
1061
1062        if (top >= bounds.fBottom) {
1063            break;
1064        }
1065
1066        if (bot > bounds.fBottom) {
1067            bot = bounds.fBottom;
1068        }
1069        SkASSERT(top < bot);
1070
1071        if (!rowA && !rowB) {
1072            builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
1073        } else if (top >= bounds.fTop) {
1074            SkASSERT(bot <= bounds.fBottom);
1075            RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
1076            RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
1077            operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
1078        }
1079
1080        adjust_iter(iterA, topA, botA, bot);
1081        adjust_iter(iterB, topB, botB, bot);
1082    } while (!iterA.done() || !iterB.done());
1083}
1084
1085bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
1086                  SkRegion::Op op) {
1087    AUTO_AACLIP_VALIDATE(*this);
1088
1089    if (SkRegion::kReplace_Op == op) {
1090        return this->set(clipBOrig);
1091    }
1092
1093    const SkAAClip* clipA = &clipAOrig;
1094    const SkAAClip* clipB = &clipBOrig;
1095
1096    if (SkRegion::kReverseDifference_Op == op) {
1097        SkTSwap(clipA, clipB);
1098        op = SkRegion::kDifference_Op;
1099    }
1100
1101    bool a_empty = clipA->isEmpty();
1102    bool b_empty = clipB->isEmpty();
1103
1104    SkIRect bounds;
1105    switch (op) {
1106        case SkRegion::kDifference_Op:
1107            if (a_empty) {
1108                return this->setEmpty();
1109            }
1110            if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
1111                return this->set(*clipA);
1112            }
1113            bounds = clipA->fBounds;
1114            break;
1115
1116        case SkRegion::kIntersect_Op:
1117            if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
1118                                                         clipB->fBounds)) {
1119                return this->setEmpty();
1120            }
1121            break;
1122
1123        case SkRegion::kUnion_Op:
1124        case SkRegion::kXOR_Op:
1125            if (a_empty) {
1126                return this->set(*clipB);
1127            }
1128            if (b_empty) {
1129                return this->set(*clipA);
1130            }
1131            bounds = clipA->fBounds;
1132            bounds.join(clipB->fBounds);
1133            break;
1134
1135        default:
1136            SkASSERT(!"unknown region op");
1137            return !this->isEmpty();
1138    }
1139
1140    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1141    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1142
1143    Builder builder(bounds);
1144    operateY(builder, *clipA, *clipB, op);
1145
1146    return builder.finish(this);
1147}
1148
1149/*
1150 *  It can be expensive to build a local aaclip before applying the op, so
1151 *  we first see if we can restrict the bounds of new rect to our current
1152 *  bounds, or note that the new rect subsumes our current clip.
1153 */
1154
1155bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) {
1156    SkIRect        rStorage;
1157    const SkIRect* r = &rOrig;
1158
1159    switch (op) {
1160        case SkRegion::kIntersect_Op:
1161            if (!rStorage.intersect(rOrig, fBounds)) {
1162                // no overlap, so we're empty
1163                return this->setEmpty();
1164            }
1165            if (rStorage == fBounds) {
1166                // we were wholly inside the rect, no change
1167                return !this->isEmpty();
1168            }
1169            if (this->quickContains(rStorage)) {
1170                // the intersection is wholly inside us, we're a rect
1171                return this->setRect(rStorage);
1172            }
1173            r = &rStorage;   // use the intersected bounds
1174            break;
1175        case SkRegion::kDifference_Op:
1176            break;
1177        case SkRegion::kUnion_Op:
1178            if (rOrig.contains(fBounds)) {
1179                return this->setRect(rOrig);
1180            }
1181            break;
1182        default:
1183            break;
1184    }
1185
1186    SkAAClip clip;
1187    clip.setRect(*r);
1188    return this->op(*this, clip, op);
1189}
1190
1191bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) {
1192    SkRect        rStorage, boundsStorage;
1193    const SkRect* r = &rOrig;
1194
1195    boundsStorage.set(fBounds);
1196    switch (op) {
1197        case SkRegion::kIntersect_Op:
1198        case SkRegion::kDifference_Op:
1199            if (!rStorage.intersect(rOrig, boundsStorage)) {
1200                return this->setEmpty();
1201            }
1202            r = &rStorage;   // use the intersected bounds
1203            break;
1204        case SkRegion::kUnion_Op:
1205            if (rOrig.contains(boundsStorage)) {
1206                return this->setRect(rOrig);
1207            }
1208            break;
1209        default:
1210            break;
1211    }
1212
1213    SkAAClip clip;
1214    clip.setRect(*r, doAA);
1215    return this->op(*this, clip, op);
1216}
1217
1218bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
1219    return this->op(*this, clip, op);
1220}
1221
1222///////////////////////////////////////////////////////////////////////////////
1223
1224bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
1225    if (NULL == dst) {
1226        return !this->isEmpty();
1227    }
1228
1229    if (this->isEmpty()) {
1230        return dst->setEmpty();
1231    }
1232
1233    if (this != dst) {
1234        sk_atomic_inc(&fRunHead->fRefCnt);
1235        dst->fRunHead = fRunHead;
1236        dst->fBounds = fBounds;
1237    }
1238    dst->fBounds.offset(dx, dy);
1239    return true;
1240}
1241
1242static void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
1243                               const uint8_t* SK_RESTRICT row,
1244                               int width) {
1245    while (width > 0) {
1246        int n = row[0];
1247        SkASSERT(width >= n);
1248        memset(mask, row[1], n);
1249        mask += n;
1250        row += 2;
1251        width -= n;
1252    }
1253}
1254
1255void SkAAClip::copyToMask(SkMask* mask) const {
1256    mask->fFormat = SkMask::kA8_Format;
1257    if (this->isEmpty()) {
1258        mask->fBounds.setEmpty();
1259        mask->fImage = NULL;
1260        mask->fRowBytes = 0;
1261        return;
1262    }
1263
1264    mask->fBounds = fBounds;
1265    mask->fRowBytes = fBounds.width();
1266    size_t size = mask->computeImageSize();
1267    mask->fImage = SkMask::AllocImage(size);
1268
1269    Iter iter(*this);
1270    uint8_t* dst = mask->fImage;
1271    const int width = fBounds.width();
1272
1273    int y = fBounds.fTop;
1274    while (!iter.done()) {
1275        do {
1276            expand_row_to_mask(dst, iter.data(), width);
1277            dst += mask->fRowBytes;
1278        } while (++y < iter.bottom());
1279        iter.next();
1280    }
1281}
1282
1283///////////////////////////////////////////////////////////////////////////////
1284///////////////////////////////////////////////////////////////////////////////
1285
1286static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
1287                         int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
1288    // we don't read our initial n from data, since the caller may have had to
1289    // clip it, hence the initialCount parameter.
1290    int n = initialCount;
1291    for (;;) {
1292        if (n > width) {
1293            n = width;
1294        }
1295        SkASSERT(n > 0);
1296        runs[0] = n;
1297        runs += n;
1298
1299        aa[0] = data[1];
1300        aa += n;
1301
1302        data += 2;
1303        width -= n;
1304        if (0 == width) {
1305            break;
1306        }
1307        // load the next count
1308        n = data[0];
1309    }
1310    runs[0] = 0;    // sentinel
1311}
1312
1313SkAAClipBlitter::~SkAAClipBlitter() {
1314    sk_free(fScanlineScratch);
1315}
1316
1317void SkAAClipBlitter::ensureRunsAndAA() {
1318    if (NULL == fScanlineScratch) {
1319        // add 1 so we can store the terminating run count of 0
1320        int count = fAAClipBounds.width() + 1;
1321        // we use this either for fRuns + fAA, or a scaline of a mask
1322        // which may be as deep as 32bits
1323        fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
1324        fRuns = (int16_t*)fScanlineScratch;
1325        fAA = (SkAlpha*)(fRuns + count);
1326    }
1327}
1328
1329void SkAAClipBlitter::blitH(int x, int y, int width) {
1330    SkASSERT(width > 0);
1331    SkASSERT(fAAClipBounds.contains(x, y));
1332    SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1333
1334    int lastY;
1335    const uint8_t* row = fAAClip->findRow(y, &lastY);
1336    int initialCount;
1337    row = fAAClip->findX(row, x, &initialCount);
1338
1339    if (initialCount >= width) {
1340        SkAlpha alpha = row[1];
1341        if (0 == alpha) {
1342            return;
1343        }
1344        if (0xFF == alpha) {
1345            fBlitter->blitH(x, y, width);
1346            return;
1347        }
1348    }
1349
1350    this->ensureRunsAndAA();
1351    expandToRuns(row, initialCount, width, fRuns, fAA);
1352
1353    fBlitter->blitAntiH(x, y, fAA, fRuns);
1354}
1355
1356static void merge(const uint8_t* SK_RESTRICT row, int rowN,
1357                  const SkAlpha* SK_RESTRICT srcAA,
1358                  const int16_t* SK_RESTRICT srcRuns,
1359                  SkAlpha* SK_RESTRICT dstAA,
1360                  int16_t* SK_RESTRICT dstRuns,
1361                  int width) {
1362    SkDEBUGCODE(int accumulated = 0;)
1363    int srcN = srcRuns[0];
1364    // do we need this check?
1365    if (0 == srcN) {
1366        return;
1367    }
1368
1369    for (;;) {
1370        SkASSERT(rowN > 0);
1371        SkASSERT(srcN > 0);
1372
1373        unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1374        int minN = SkMin32(srcN, rowN);
1375        dstRuns[0] = minN;
1376        dstRuns += minN;
1377        dstAA[0] = newAlpha;
1378        dstAA += minN;
1379
1380        if (0 == (srcN -= minN)) {
1381            srcN = srcRuns[0];  // refresh
1382            srcRuns += srcN;
1383            srcAA += srcN;
1384            srcN = srcRuns[0];  // reload
1385            if (0 == srcN) {
1386                break;
1387            }
1388        }
1389        if (0 == (rowN -= minN)) {
1390            row += 2;
1391            rowN = row[0];  // reload
1392        }
1393
1394        SkDEBUGCODE(accumulated += minN;)
1395        SkASSERT(accumulated <= width);
1396    }
1397    dstRuns[0] = 0;
1398}
1399
1400void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
1401                                const int16_t runs[]) {
1402    int lastY;
1403    const uint8_t* row = fAAClip->findRow(y, &lastY);
1404    int initialCount;
1405    row = fAAClip->findX(row, x, &initialCount);
1406
1407    this->ensureRunsAndAA();
1408
1409    merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1410    fBlitter->blitAntiH(x, y, fAA, fRuns);
1411}
1412
1413void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1414    if (fAAClip->quickContains(x, y, x + 1, y + height)) {
1415        fBlitter->blitV(x, y, height, alpha);
1416        return;
1417    }
1418
1419    for (;;) {
1420        int lastY;
1421        const uint8_t* row = fAAClip->findRow(y, &lastY);
1422        int dy = lastY - y + 1;
1423        if (dy > height) {
1424            dy = height;
1425        }
1426        height -= dy;
1427
1428        int initialCount;
1429        row = fAAClip->findX(row, x, &initialCount);
1430        SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
1431        if (newAlpha) {
1432            fBlitter->blitV(x, y, dy, newAlpha);
1433        }
1434        SkASSERT(height >= 0);
1435        if (height <= 0) {
1436            break;
1437        }
1438        y = lastY + 1;
1439    }
1440}
1441
1442void SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
1443    if (fAAClip->quickContains(x, y, x + width, y + height)) {
1444        fBlitter->blitRect(x, y, width, height);
1445        return;
1446    }
1447
1448    while (--height >= 0) {
1449        this->blitH(x, y, width);
1450        y += 1;
1451    }
1452}
1453
1454typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
1455                            int initialRowCount, void* dst);
1456
1457static void small_memcpy(void* dst, const void* src, size_t n) {
1458    memcpy(dst, src, n);
1459}
1460
1461static void small_bzero(void* dst, size_t n) {
1462    sk_bzero(dst, n);
1463}
1464
1465static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
1466    return SkMulDiv255Round(value, alpha);
1467}
1468static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
1469    unsigned r = SkGetPackedR16(value);
1470    unsigned g = SkGetPackedG16(value);
1471    unsigned b = SkGetPackedB16(value);
1472    return SkPackRGB16(SkMulDiv255Round(r, alpha),
1473                       SkMulDiv255Round(r, alpha),
1474                       SkMulDiv255Round(r, alpha));
1475}
1476static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
1477    unsigned a = SkGetPackedA32(value);
1478    unsigned r = SkGetPackedR32(value);
1479    unsigned g = SkGetPackedG32(value);
1480    unsigned b = SkGetPackedB32(value);
1481    return SkPackARGB32(SkMulDiv255Round(a, alpha),
1482                        SkMulDiv255Round(r, alpha),
1483                        SkMulDiv255Round(g, alpha),
1484                        SkMulDiv255Round(b, alpha));
1485}
1486
1487template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
1488                                 const uint8_t* SK_RESTRICT row, int rowN,
1489                                 T* SK_RESTRICT dst) {
1490    SkDEBUGCODE(int accumulated = 0;)
1491    for (;;) {
1492        SkASSERT(rowN > 0);
1493        SkASSERT(srcN > 0);
1494
1495        int n = SkMin32(rowN, srcN);
1496        unsigned rowA = row[1];
1497        if (0xFF == rowA) {
1498            small_memcpy(dst, src, n * sizeof(T));
1499        } else if (0 == rowA) {
1500            small_bzero(dst, n * sizeof(T));
1501        } else {
1502            for (int i = 0; i < n; ++i) {
1503                dst[i] = mergeOne(src[i], rowA);
1504            }
1505        }
1506
1507        if (0 == (srcN -= n)) {
1508            break;
1509        }
1510
1511        src += n;
1512        dst += n;
1513
1514        SkASSERT(rowN == n);
1515        row += 2;
1516        rowN = row[0];
1517    }
1518}
1519
1520static MergeAAProc find_merge_aa_proc(SkMask::Format format) {
1521    switch (format) {
1522        case SkMask::kBW_Format:
1523            SkASSERT(!"unsupported");
1524            return NULL;
1525        case SkMask::kA8_Format:
1526        case SkMask::k3D_Format: {
1527            void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT;
1528            return (MergeAAProc)proc8;
1529        }
1530        case SkMask::kLCD16_Format: {
1531            void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT;
1532            return (MergeAAProc)proc16;
1533        }
1534        case SkMask::kLCD32_Format: {
1535            void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT;
1536            return (MergeAAProc)proc32;
1537        }
1538        default:
1539            SkASSERT(!"unsupported");
1540            return NULL;
1541    }
1542}
1543
1544static U8CPU bit2byte(int bitInAByte) {
1545    SkASSERT(bitInAByte <= 0xFF);
1546    // negation turns any non-zero into 0xFFFFFF??, so we just shift down
1547    // some value >= 8 to get a full FF value
1548    return -bitInAByte >> 8;
1549}
1550
1551static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
1552    SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
1553    SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
1554
1555    const int width = srcMask.fBounds.width();
1556    const int height = srcMask.fBounds.height();
1557
1558    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
1559    const size_t srcRB = srcMask.fRowBytes;
1560    uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage;
1561    const size_t dstRB = dstMask->fRowBytes;
1562
1563    const int wholeBytes = width >> 3;
1564    const int leftOverBits = width & 7;
1565
1566    for (int y = 0; y < height; ++y) {
1567        uint8_t* SK_RESTRICT d = dst;
1568        for (int i = 0; i < wholeBytes; ++i) {
1569            int srcByte = src[i];
1570            d[0] = bit2byte(srcByte & (1 << 7));
1571            d[1] = bit2byte(srcByte & (1 << 6));
1572            d[2] = bit2byte(srcByte & (1 << 5));
1573            d[3] = bit2byte(srcByte & (1 << 4));
1574            d[4] = bit2byte(srcByte & (1 << 3));
1575            d[5] = bit2byte(srcByte & (1 << 2));
1576            d[6] = bit2byte(srcByte & (1 << 1));
1577            d[7] = bit2byte(srcByte & (1 << 0));
1578            d += 8;
1579        }
1580        if (leftOverBits) {
1581            int srcByte = src[wholeBytes];
1582            for (int x = 0; x < leftOverBits; ++x) {
1583                *d++ = bit2byte(srcByte & 0x80);
1584                srcByte <<= 1;
1585            }
1586        }
1587        src += srcRB;
1588        dst += dstRB;
1589    }
1590}
1591
1592void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
1593    SkASSERT(fAAClip->getBounds().contains(clip));
1594
1595    if (fAAClip->quickContains(clip)) {
1596        fBlitter->blitMask(origMask, clip);
1597        return;
1598    }
1599
1600    const SkMask* mask = &origMask;
1601
1602    // if we're BW, we need to upscale to A8 (ugh)
1603    SkMask  grayMask;
1604    grayMask.fImage = NULL;
1605    if (SkMask::kBW_Format == origMask.fFormat) {
1606        grayMask.fFormat = SkMask::kA8_Format;
1607        grayMask.fBounds = origMask.fBounds;
1608        grayMask.fRowBytes = origMask.fBounds.width();
1609        size_t size = grayMask.computeImageSize();
1610        grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size,
1611                                               SkAutoMalloc::kReuse_OnShrink);
1612
1613        upscaleBW2A8(&grayMask, origMask);
1614        mask = &grayMask;
1615    }
1616
1617    this->ensureRunsAndAA();
1618
1619    // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
1620    // data into a temp block to support it better (ugh)
1621
1622    const void* src = mask->getAddr(clip.fLeft, clip.fTop);
1623    const size_t srcRB = mask->fRowBytes;
1624    const int width = clip.width();
1625    MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
1626
1627    SkMask rowMask;
1628    rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
1629    rowMask.fBounds.fLeft = clip.fLeft;
1630    rowMask.fBounds.fRight = clip.fRight;
1631    rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1
1632    rowMask.fImage = (uint8_t*)fScanlineScratch;
1633
1634    int y = clip.fTop;
1635    const int stopY = y + clip.height();
1636
1637    do {
1638        int localStopY;
1639        const uint8_t* row = fAAClip->findRow(y, &localStopY);
1640        // findRow returns last Y, not stop, so we add 1
1641        localStopY = SkMin32(localStopY + 1, stopY);
1642
1643        int initialCount;
1644        row = fAAClip->findX(row, clip.fLeft, &initialCount);
1645        do {
1646            mergeProc(src, width, row, initialCount, rowMask.fImage);
1647            rowMask.fBounds.fTop = y;
1648            rowMask.fBounds.fBottom = y + 1;
1649            fBlitter->blitMask(rowMask, rowMask.fBounds);
1650            src = (const void*)((const char*)src + srcRB);
1651        } while (++y < localStopY);
1652    } while (y < stopY);
1653}
1654
1655const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
1656    return NULL;
1657}
1658
1659