SkAAClip.cpp revision 820e80ad6390e120d4991a5280d0452ec87beaeb
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
482public:
483    Builder(const SkIRect& bounds) : fBounds(bounds) {
484        fPrevY = -1;
485        fWidth = bounds.width();
486        fCurrRow = NULL;
487    }
488
489    ~Builder() {
490        Row* row = fRows.begin();
491        Row* stop = fRows.end();
492        while (row < stop) {
493            delete row->fData;
494            row += 1;
495        }
496    }
497
498    const SkIRect& getBounds() const { return fBounds; }
499
500    void addRun(int x, int y, U8CPU alpha, int count) {
501        SkASSERT(count > 0);
502        SkASSERT(fBounds.contains(x, y));
503        SkASSERT(fBounds.contains(x + count - 1, y));
504
505        x -= fBounds.left();
506        y -= fBounds.top();
507
508        Row* row = fCurrRow;
509        if (y != fPrevY) {
510            SkASSERT(y > fPrevY);
511            fPrevY = y;
512            row = this->flushRow(true);
513            row->fY = y;
514            row->fWidth = 0;
515            SkASSERT(row->fData);
516            SkASSERT(0 == row->fData->count());
517            fCurrRow = row;
518        }
519
520        SkASSERT(row->fWidth <= x);
521        SkASSERT(row->fWidth < fBounds.width());
522
523        SkTDArray<uint8_t>& data = *row->fData;
524
525        int gap = x - row->fWidth;
526        if (gap) {
527            AppendRun(data, 0, gap);
528            row->fWidth += gap;
529            SkASSERT(row->fWidth < fBounds.width());
530        }
531
532        AppendRun(data, alpha, count);
533        row->fWidth += count;
534        SkASSERT(row->fWidth <= fBounds.width());
535    }
536
537    bool finish(SkAAClip* target) {
538        this->flushRow(false);
539
540        const Row* row = fRows.begin();
541        const Row* stop = fRows.end();
542
543        size_t dataSize = 0;
544        while (row < stop) {
545            dataSize += row->fData->count();
546            row += 1;
547        }
548
549        if (0 == dataSize) {
550            return target->setEmpty();
551        }
552
553        RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
554        YOffset* yoffset = head->yoffsets();
555        uint8_t* data = head->data();
556        uint8_t* baseData = data;
557
558        row = fRows.begin();
559        while (row < stop) {
560            yoffset->fY = row->fY;
561            yoffset->fOffset = data - baseData;
562            yoffset += 1;
563
564            size_t n = row->fData->count();
565            memcpy(data, row->fData->begin(), n);
566            data += n;
567
568            row += 1;
569        }
570
571        target->freeRuns();
572        target->fBounds = fBounds;
573        target->fRunHead = head;
574        return target->trimBounds();
575    }
576
577    void dump() {
578        this->validate();
579        int y;
580        for (y = 0; y < fRows.count(); ++y) {
581            const Row& row = fRows[y];
582            SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
583            const SkTDArray<uint8_t>& data = *row.fData;
584            int count = data.count();
585            SkASSERT(!(count & 1));
586            const uint8_t* ptr = data.begin();
587            for (int x = 0; x < count; x += 2) {
588                SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
589                ptr += 2;
590            }
591            SkDebugf("\n");
592        }
593    }
594
595    void validate() {
596#ifdef SK_DEBUG
597        int prevY = -1;
598        for (int i = 0; i < fRows.count(); ++i) {
599            const Row& row = fRows[i];
600            SkASSERT(prevY < row.fY);
601            SkASSERT(fWidth == row.fWidth);
602            int count = row.fData->count();
603            const uint8_t* ptr = row.fData->begin();
604            SkASSERT(!(count & 1));
605            int w = 0;
606            for (int x = 0; x < count; x += 2) {
607                w += ptr[0];
608                SkASSERT(w <= fWidth);
609                ptr += 2;
610            }
611            SkASSERT(w == fWidth);
612            prevY = row.fY;
613        }
614#endif
615    }
616
617private:
618    Row* flushRow(bool readyForAnother) {
619        Row* next = NULL;
620        int count = fRows.count();
621        if (count > 0) {
622            // flush current row if needed
623            Row* curr = &fRows[count - 1];
624            if (curr->fWidth < fWidth) {
625                AppendRun(*curr->fData, 0, fWidth - curr->fWidth);
626                curr->fWidth = fWidth;
627            }
628        }
629        if (count > 1) {
630            // are our last two runs the same?
631            Row* prev = &fRows[count - 2];
632            Row* curr = &fRows[count - 1];
633            SkASSERT(prev->fWidth == fWidth);
634            SkASSERT(curr->fWidth == fWidth);
635            if (*prev->fData == *curr->fData) {
636                prev->fY = curr->fY;
637                if (readyForAnother) {
638                    curr->fData->rewind();
639                    next = curr;
640                } else {
641                    delete curr->fData;
642                    fRows.removeShuffle(count - 1);
643                }
644            } else {
645                if (readyForAnother) {
646                    next = fRows.append();
647                    next->fData = new SkTDArray<uint8_t>;
648                }
649            }
650        } else {
651            if (readyForAnother) {
652                next = fRows.append();
653                next->fData = new SkTDArray<uint8_t>;
654            }
655        }
656        return next;
657    }
658
659    static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
660        do {
661            int n = count;
662            if (n > 255) {
663                n = 255;
664            }
665            uint8_t* ptr = data.append(2);
666            ptr[0] = n;
667            ptr[1] = alpha;
668            count -= n;
669        } while (count > 0);
670    }
671};
672
673class SkAAClip::BuilderBlitter : public SkBlitter {
674public:
675    BuilderBlitter(Builder* builder) {
676        fBuilder = builder;
677        fLeft = builder->getBounds().fLeft;
678        fRight = builder->getBounds().fRight;
679    }
680
681    virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE
682        { unexpected(); }
683
684    //  let the default impl call blitH
685//    virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE
686
687    virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
688        { unexpected(); }
689
690    virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE {
691        return NULL;
692    }
693
694    virtual void blitH(int x, int y, int width) SK_OVERRIDE {
695        fBuilder->addRun(x, y, 0xFF, width);
696    }
697
698    virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
699                           const int16_t runs[]) SK_OVERRIDE {
700        for (;;) {
701            int count = *runs;
702            if (count <= 0) {
703                return;
704            }
705
706            // The supersampler's buffer can be the width of the device, so
707            // we may have to trim the run to our bounds. If so, we assert that
708            // the extra spans are always alpha==0
709            int localX = x;
710            int localCount = count;
711            if (x < fLeft) {
712                SkASSERT(0 == *alpha);
713                int gap = fLeft - x;
714                SkASSERT(gap <= count);
715                localX += gap;
716                localCount -= gap;
717            }
718            int right = x + count;
719            if (right > fRight) {
720                SkASSERT(0 == *alpha);
721                localCount -= right - fRight;
722                SkASSERT(localCount >= 0);
723            }
724
725            if (localCount) {
726                fBuilder->addRun(localX, y, *alpha, localCount);
727            }
728            // Next run
729            runs += count;
730            alpha += count;
731            x += count;
732        }
733    }
734
735private:
736    Builder* fBuilder;
737    int      fLeft; // cache of builder's bounds' left edge
738    int      fRight;
739
740    void unexpected() {
741        SkDebugf("---- did not expect to get called here");
742        sk_throw();
743    }
744};
745
746bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
747    AUTO_AACLIP_VALIDATE(*this);
748
749    if (clip && clip->isEmpty()) {
750        return this->setEmpty();
751    }
752
753    SkIRect ibounds;
754    path.getBounds().roundOut(&ibounds);
755
756    SkRegion tmpClip;
757    if (NULL == clip) {
758        tmpClip.setRect(ibounds);
759        clip = &tmpClip;
760    }
761
762    if (path.isInverseFillType()) {
763        ibounds = clip->getBounds();
764    } else {
765        if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
766            return this->setEmpty();
767        }
768    }
769
770    Builder        builder(ibounds);
771    BuilderBlitter blitter(&builder);
772
773    if (doAA) {
774        SkScan::AntiFillPath(path, *clip, &blitter, true);
775    } else {
776        SkScan::FillPath(path, *clip, &blitter);
777    }
778
779    return builder.finish(this);
780}
781
782///////////////////////////////////////////////////////////////////////////////
783
784typedef void (*RowProc)(SkAAClip::Builder&, int bottom,
785                        const uint8_t* rowA, const SkIRect& rectA,
786                        const uint8_t* rowB, const SkIRect& rectB);
787
788static void sectRowProc(SkAAClip::Builder& builder, int bottom,
789                        const uint8_t* rowA, const SkIRect& rectA,
790                        const uint8_t* rowB, const SkIRect& rectB) {
791
792}
793
794typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
795
796static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
797    // Multiply
798    return SkMulDiv255Round(alphaA, alphaB);
799}
800
801static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
802    // SrcOver
803    return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
804}
805
806static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
807    // SrcOut
808    return SkMulDiv255Round(alphaA, 0xFF - alphaB);
809}
810
811static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
812    // XOR
813    return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
814}
815
816static AlphaProc find_alpha_proc(SkRegion::Op op) {
817    switch (op) {
818        case SkRegion::kIntersect_Op:
819            return sectAlphaProc;
820        case SkRegion::kDifference_Op:
821            return diffAlphaProc;
822        case SkRegion::kUnion_Op:
823            return unionAlphaProc;
824        case SkRegion::kXOR_Op:
825            return xorAlphaProc;
826        default:
827            SkASSERT(!"unexpected region op");
828            return sectAlphaProc;
829    }
830}
831
832static const uint8_t gEmptyRow[] = {
833    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
834    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
835    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
836    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
837    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
838    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
839    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
840    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
841};
842
843class RowIter {
844public:
845    RowIter(const uint8_t* row, const SkIRect& bounds) {
846        fRow = row;
847        fLeft = bounds.fLeft;
848        fBoundsRight = bounds.fRight;
849        if (row) {
850            fRight = bounds.fLeft + row[0];
851            SkASSERT(fRight <= fBoundsRight);
852            fAlpha = row[1];
853            fDone = false;
854        } else {
855            fDone = true;
856            fRight = kMaxInt32;
857            fAlpha = 0;
858        }
859    }
860
861    bool done() const { return fDone; }
862    int left() const { return fLeft; }
863    int right() const { return fRight; }
864    U8CPU alpha() const { return fAlpha; }
865    void next() {
866        if (!fDone) {
867            fLeft = fRight;
868            if (fRight == fBoundsRight) {
869                fDone = true;
870                fRight = kMaxInt32;
871                fAlpha = 0;
872            } else {
873                fRow += 2;
874                fRight += fRow[0];
875                fAlpha = fRow[1];
876                SkASSERT(fRight <= fBoundsRight);
877            }
878        }
879    }
880
881private:
882    const uint8_t*  fRow;
883    int             fLeft;
884    int             fRight;
885    int             fBoundsRight;
886    bool            fDone;
887    uint8_t         fAlpha;
888};
889
890static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
891    if (rite == riteA) {
892        iter.next();
893        leftA = iter.left();
894        riteA = iter.right();
895    }
896}
897
898static bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
899    SkASSERT(min < max);
900    SkASSERT(boundsMin < boundsMax);
901    if (min >= boundsMax || max <= boundsMin) {
902        return false;
903    }
904    if (min < boundsMin) {
905        min = boundsMin;
906    }
907    if (max > boundsMax) {
908        max = boundsMax;
909    }
910    return true;
911}
912
913static void operatorX(SkAAClip::Builder& builder, int lastY,
914                      RowIter& iterA, RowIter& iterB,
915                      AlphaProc proc, const SkIRect& bounds) {
916    int leftA = iterA.left();
917    int riteA = iterA.right();
918    int leftB = iterB.left();
919    int riteB = iterB.right();
920
921    int prevRite = bounds.fLeft;
922
923    do {
924        U8CPU alphaA = 0;
925        U8CPU alphaB = 0;
926        int left, rite;
927
928        if (leftA < leftB) {
929            left = leftA;
930            alphaA = iterA.alpha();
931            if (riteA <= leftB) {
932                rite = riteA;
933            } else {
934                rite = leftA = leftB;
935            }
936        } else if (leftB < leftA) {
937            left = leftB;
938            alphaB = iterB.alpha();
939            if (riteB <= leftA) {
940                rite = riteB;
941            } else {
942                rite = leftB = leftA;
943            }
944        } else {
945            left = leftA;   // or leftB, since leftA == leftB
946            rite = leftA = leftB = SkMin32(riteA, riteB);
947            alphaA = iterA.alpha();
948            alphaB = iterB.alpha();
949        }
950
951        if (left >= bounds.fRight) {
952            break;
953        }
954        if (rite > bounds.fRight) {
955            rite = bounds.fRight;
956        }
957
958        if (left >= bounds.fLeft) {
959            SkASSERT(rite > left);
960            builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
961            prevRite = rite;
962        }
963
964        adjust_row(iterA, leftA, riteA, rite);
965        adjust_row(iterB, leftB, riteB, rite);
966    } while (!iterA.done() || !iterB.done());
967
968    if (prevRite < bounds.fRight) {
969        builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
970    }
971}
972
973static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
974    if (bot == botA) {
975        iter.next();
976        topA = botA;
977        SkASSERT(botA == iter.top());
978        botA = iter.bottom();
979    }
980}
981
982static void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
983                     const SkAAClip& B, SkRegion::Op op) {
984    AlphaProc proc = find_alpha_proc(op);
985    const SkIRect& bounds = builder.getBounds();
986
987    SkAAClip::Iter iterA(A);
988    SkAAClip::Iter iterB(B);
989
990    SkASSERT(!iterA.done());
991    int topA = iterA.top();
992    int botA = iterA.bottom();
993    SkASSERT(!iterB.done());
994    int topB = iterB.top();
995    int botB = iterB.bottom();
996
997    do {
998        const uint8_t* rowA = NULL;
999        const uint8_t* rowB = NULL;
1000        int top, bot;
1001
1002        if (topA < topB) {
1003            top = topA;
1004            rowA = iterA.data();
1005            if (botA <= topB) {
1006                bot = botA;
1007            } else {
1008                bot = topA = topB;
1009            }
1010
1011        } else if (topB < topA) {
1012            top = topB;
1013            rowB = iterB.data();
1014            if (botB <= topA) {
1015                bot = botB;
1016            } else {
1017                bot = topB = topA;
1018            }
1019        } else {
1020            top = topA;   // or topB, since topA == topB
1021            bot = topA = topB = SkMin32(botA, botB);
1022            rowA = iterA.data();
1023            rowB = iterB.data();
1024        }
1025
1026        if (top >= bounds.fBottom) {
1027            break;
1028        }
1029
1030        if (bot > bounds.fBottom) {
1031            bot = bounds.fBottom;
1032        }
1033        SkASSERT(top < bot);
1034
1035        if (!rowA && !rowB) {
1036            builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
1037        } else if (top >= bounds.fTop) {
1038            SkASSERT(bot <= bounds.fBottom);
1039            RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
1040            RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
1041            operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
1042        }
1043
1044        adjust_iter(iterA, topA, botA, bot);
1045        adjust_iter(iterB, topB, botB, bot);
1046    } while (!iterA.done() || !iterB.done());
1047}
1048
1049bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
1050                  SkRegion::Op op) {
1051    AUTO_AACLIP_VALIDATE(*this);
1052
1053    if (SkRegion::kReplace_Op == op) {
1054        return this->set(clipBOrig);
1055    }
1056
1057    const SkAAClip* clipA = &clipAOrig;
1058    const SkAAClip* clipB = &clipBOrig;
1059
1060    if (SkRegion::kReverseDifference_Op == op) {
1061        SkTSwap(clipA, clipB);
1062        op = SkRegion::kDifference_Op;
1063    }
1064
1065    bool a_empty = clipA->isEmpty();
1066    bool b_empty = clipB->isEmpty();
1067
1068    SkIRect bounds;
1069    switch (op) {
1070        case SkRegion::kDifference_Op:
1071            if (a_empty) {
1072                return this->setEmpty();
1073            }
1074            if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
1075                return this->set(*clipA);
1076            }
1077            bounds = clipA->fBounds;
1078            break;
1079
1080        case SkRegion::kIntersect_Op:
1081            if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
1082                                                         clipB->fBounds)) {
1083                return this->setEmpty();
1084            }
1085            break;
1086
1087        case SkRegion::kUnion_Op:
1088        case SkRegion::kXOR_Op:
1089            if (a_empty) {
1090                return this->set(*clipB);
1091            }
1092            if (b_empty) {
1093                return this->set(*clipA);
1094            }
1095            bounds = clipA->fBounds;
1096            bounds.join(clipB->fBounds);
1097            break;
1098
1099        default:
1100            SkASSERT(!"unknown region op");
1101            return !this->isEmpty();
1102    }
1103
1104    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1105    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1106
1107    Builder builder(bounds);
1108    operateY(builder, *clipA, *clipB, op);
1109
1110    return builder.finish(this);
1111}
1112
1113/*
1114 *  It can be expensive to build a local aaclip before applying the op, so
1115 *  we first see if we can restrict the bounds of new rect to our current
1116 *  bounds, or note that the new rect subsumes our current clip.
1117 */
1118
1119bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) {
1120    SkIRect        rStorage;
1121    const SkIRect* r = &rOrig;
1122
1123    switch (op) {
1124        case SkRegion::kIntersect_Op:
1125            if (!rStorage.intersect(rOrig, fBounds)) {
1126                // no overlap, so we're empty
1127                return this->setEmpty();
1128            }
1129            if (rStorage == fBounds) {
1130                // we were wholly inside the rect, no change
1131                return !this->isEmpty();
1132            }
1133            if (this->quickContains(rStorage)) {
1134                // the intersection is wholly inside us, we're a rect
1135                return this->setRect(rStorage);
1136            }
1137            r = &rStorage;   // use the intersected bounds
1138            break;
1139        case SkRegion::kDifference_Op:
1140            break;
1141        case SkRegion::kUnion_Op:
1142            if (rOrig.contains(fBounds)) {
1143                return this->setRect(rOrig);
1144            }
1145            break;
1146        default:
1147            break;
1148    }
1149
1150    SkAAClip clip;
1151    clip.setRect(*r);
1152    return this->op(*this, clip, op);
1153}
1154
1155bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) {
1156    SkRect        rStorage, boundsStorage;
1157    const SkRect* r = &rOrig;
1158
1159    boundsStorage.set(fBounds);
1160    switch (op) {
1161        case SkRegion::kIntersect_Op:
1162        case SkRegion::kDifference_Op:
1163            if (!rStorage.intersect(rOrig, boundsStorage)) {
1164                return this->setEmpty();
1165            }
1166            r = &rStorage;   // use the intersected bounds
1167            break;
1168        case SkRegion::kUnion_Op:
1169            if (rOrig.contains(boundsStorage)) {
1170                return this->setRect(rOrig);
1171            }
1172            break;
1173        default:
1174            break;
1175    }
1176
1177    SkAAClip clip;
1178    clip.setRect(*r, doAA);
1179    return this->op(*this, clip, op);
1180}
1181
1182bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
1183    return this->op(*this, clip, op);
1184}
1185
1186///////////////////////////////////////////////////////////////////////////////
1187
1188bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
1189    if (NULL == dst) {
1190        return !this->isEmpty();
1191    }
1192
1193    if (this->isEmpty()) {
1194        return dst->setEmpty();
1195    }
1196
1197    if (this != dst) {
1198        sk_atomic_inc(&fRunHead->fRefCnt);
1199        dst->fRunHead = fRunHead;
1200        dst->fBounds = fBounds;
1201    }
1202    dst->fBounds.offset(dx, dy);
1203    return true;
1204}
1205
1206static void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
1207                               const uint8_t* SK_RESTRICT row,
1208                               int width) {
1209    while (width > 0) {
1210        int n = row[0];
1211        SkASSERT(width >= n);
1212        memset(mask, row[1], n);
1213        mask += n;
1214        row += 2;
1215        width -= n;
1216    }
1217}
1218
1219void SkAAClip::copyToMask(SkMask* mask) const {
1220    mask->fFormat = SkMask::kA8_Format;
1221    if (this->isEmpty()) {
1222        mask->fBounds.setEmpty();
1223        mask->fImage = NULL;
1224        mask->fRowBytes = 0;
1225        return;
1226    }
1227
1228    mask->fBounds = fBounds;
1229    mask->fRowBytes = fBounds.width();
1230    size_t size = mask->computeImageSize();
1231    mask->fImage = SkMask::AllocImage(size);
1232
1233    Iter iter(*this);
1234    uint8_t* dst = mask->fImage;
1235    const int width = fBounds.width();
1236
1237    int y = fBounds.fTop;
1238    while (!iter.done()) {
1239        do {
1240            expand_row_to_mask(dst, iter.data(), width);
1241            dst += mask->fRowBytes;
1242        } while (++y < iter.bottom());
1243        iter.next();
1244    }
1245}
1246
1247///////////////////////////////////////////////////////////////////////////////
1248///////////////////////////////////////////////////////////////////////////////
1249
1250static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
1251                         int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
1252    // we don't read our initial n from data, since the caller may have had to
1253    // clip it, hence the initialCount parameter.
1254    int n = initialCount;
1255    for (;;) {
1256        if (n > width) {
1257            n = width;
1258        }
1259        SkASSERT(n > 0);
1260        runs[0] = n;
1261        runs += n;
1262
1263        aa[0] = data[1];
1264        aa += n;
1265
1266        data += 2;
1267        width -= n;
1268        if (0 == width) {
1269            break;
1270        }
1271        // load the next count
1272        n = data[0];
1273    }
1274    runs[0] = 0;    // sentinel
1275}
1276
1277SkAAClipBlitter::~SkAAClipBlitter() {
1278    sk_free(fScanlineScratch);
1279}
1280
1281void SkAAClipBlitter::ensureRunsAndAA() {
1282    if (NULL == fScanlineScratch) {
1283        // add 1 so we can store the terminating run count of 0
1284        int count = fAAClipBounds.width() + 1;
1285        // we use this either for fRuns + fAA, or a scaline of a mask
1286        // which may be as deep as 32bits
1287        fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
1288        fRuns = (int16_t*)fScanlineScratch;
1289        fAA = (SkAlpha*)(fRuns + count);
1290    }
1291}
1292
1293void SkAAClipBlitter::blitH(int x, int y, int width) {
1294    SkASSERT(width > 0);
1295    SkASSERT(fAAClipBounds.contains(x, y));
1296    SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1297
1298    int lastY;
1299    const uint8_t* row = fAAClip->findRow(y, &lastY);
1300    int initialCount;
1301    row = fAAClip->findX(row, x, &initialCount);
1302
1303    if (initialCount >= width) {
1304        SkAlpha alpha = row[1];
1305        if (0 == alpha) {
1306            return;
1307        }
1308        if (0xFF == alpha) {
1309            fBlitter->blitH(x, y, width);
1310            return;
1311        }
1312    }
1313
1314    this->ensureRunsAndAA();
1315    expandToRuns(row, initialCount, width, fRuns, fAA);
1316
1317    fBlitter->blitAntiH(x, y, fAA, fRuns);
1318}
1319
1320static void merge(const uint8_t* SK_RESTRICT row, int rowN,
1321                  const SkAlpha* SK_RESTRICT srcAA,
1322                  const int16_t* SK_RESTRICT srcRuns,
1323                  SkAlpha* SK_RESTRICT dstAA,
1324                  int16_t* SK_RESTRICT dstRuns,
1325                  int width) {
1326    SkDEBUGCODE(int accumulated = 0;)
1327    int srcN = srcRuns[0];
1328    // do we need this check?
1329    if (0 == srcN) {
1330        return;
1331    }
1332
1333    for (;;) {
1334        SkASSERT(rowN > 0);
1335        SkASSERT(srcN > 0);
1336
1337        unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1338        int minN = SkMin32(srcN, rowN);
1339        dstRuns[0] = minN;
1340        dstRuns += minN;
1341        dstAA[0] = newAlpha;
1342        dstAA += minN;
1343
1344        if (0 == (srcN -= minN)) {
1345            srcN = srcRuns[0];  // refresh
1346            srcRuns += srcN;
1347            srcAA += srcN;
1348            srcN = srcRuns[0];  // reload
1349            if (0 == srcN) {
1350                break;
1351            }
1352        }
1353        if (0 == (rowN -= minN)) {
1354            row += 2;
1355            rowN = row[0];  // reload
1356        }
1357
1358        SkDEBUGCODE(accumulated += minN;)
1359        SkASSERT(accumulated <= width);
1360    }
1361    dstRuns[0] = 0;
1362}
1363
1364void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
1365                                const int16_t runs[]) {
1366    int lastY;
1367    const uint8_t* row = fAAClip->findRow(y, &lastY);
1368    int initialCount;
1369    row = fAAClip->findX(row, x, &initialCount);
1370
1371    this->ensureRunsAndAA();
1372
1373    merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1374    fBlitter->blitAntiH(x, y, fAA, fRuns);
1375}
1376
1377void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1378    if (fAAClip->quickContains(x, y, x + 1, y + height)) {
1379        fBlitter->blitV(x, y, height, alpha);
1380        return;
1381    }
1382
1383    for (;;) {
1384        int lastY;
1385        const uint8_t* row = fAAClip->findRow(y, &lastY);
1386        int dy = lastY - y + 1;
1387        if (dy > height) {
1388            dy = height;
1389        }
1390        height -= dy;
1391
1392        int initialCount;
1393        row = fAAClip->findX(row, x, &initialCount);
1394        SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
1395        if (newAlpha) {
1396            fBlitter->blitV(x, y, dy, newAlpha);
1397        }
1398        SkASSERT(height >= 0);
1399        if (height <= 0) {
1400            break;
1401        }
1402        y = lastY + 1;
1403    }
1404}
1405
1406void SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
1407    if (fAAClip->quickContains(x, y, x + width, y + height)) {
1408        fBlitter->blitRect(x, y, width, height);
1409        return;
1410    }
1411
1412    while (--height >= 0) {
1413        this->blitH(x, y, width);
1414        y += 1;
1415    }
1416}
1417
1418typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
1419                            int initialRowCount, void* dst);
1420
1421static void small_memcpy(void* dst, const void* src, size_t n) {
1422    memcpy(dst, src, n);
1423}
1424
1425static void small_bzero(void* dst, size_t n) {
1426    sk_bzero(dst, n);
1427}
1428
1429static inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
1430    return SkMulDiv255Round(value, alpha);
1431}
1432static inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
1433    unsigned r = SkGetPackedR16(value);
1434    unsigned g = SkGetPackedG16(value);
1435    unsigned b = SkGetPackedB16(value);
1436    return SkPackRGB16(SkMulDiv255Round(r, alpha),
1437                       SkMulDiv255Round(r, alpha),
1438                       SkMulDiv255Round(r, alpha));
1439}
1440static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
1441    unsigned a = SkGetPackedA32(value);
1442    unsigned r = SkGetPackedR32(value);
1443    unsigned g = SkGetPackedG32(value);
1444    unsigned b = SkGetPackedB32(value);
1445    return SkPackARGB32(SkMulDiv255Round(a, alpha),
1446                        SkMulDiv255Round(r, alpha),
1447                        SkMulDiv255Round(g, alpha),
1448                        SkMulDiv255Round(b, alpha));
1449}
1450
1451template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
1452                                 const uint8_t* SK_RESTRICT row, int rowN,
1453                                 T* SK_RESTRICT dst) {
1454    SkDEBUGCODE(int accumulated = 0;)
1455    for (;;) {
1456        SkASSERT(rowN > 0);
1457        SkASSERT(srcN > 0);
1458
1459        int n = SkMin32(rowN, srcN);
1460        unsigned rowA = row[1];
1461        if (0xFF == rowA) {
1462            small_memcpy(dst, src, n * sizeof(T));
1463        } else if (0 == rowA) {
1464            small_bzero(dst, n * sizeof(T));
1465        } else {
1466            for (int i = 0; i < n; ++i) {
1467                dst[i] = mergeOne(src[i], rowA);
1468            }
1469        }
1470
1471        if (0 == (srcN -= n)) {
1472            break;
1473        }
1474
1475        src += n;
1476        dst += n;
1477
1478        SkASSERT(rowN == n);
1479        row += 2;
1480        rowN = row[0];
1481    }
1482}
1483
1484static MergeAAProc find_merge_aa_proc(SkMask::Format format) {
1485    switch (format) {
1486        case SkMask::kBW_Format:
1487            SkASSERT(!"unsupported");
1488            return NULL;
1489        case SkMask::kA8_Format:
1490        case SkMask::k3D_Format: {
1491            void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT;
1492            return (MergeAAProc)proc8;
1493        }
1494        case SkMask::kLCD16_Format: {
1495            void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT;
1496            return (MergeAAProc)proc16;
1497        }
1498        case SkMask::kLCD32_Format: {
1499            void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT;
1500            return (MergeAAProc)proc32;
1501        }
1502        default:
1503            SkASSERT(!"unsupported");
1504            return NULL;
1505    }
1506}
1507
1508static U8CPU bit2byte(int bitInAByte) {
1509    SkASSERT(bitInAByte <= 0xFF);
1510    // negation turns any non-zero into 0xFFFFFF??, so we just shift down
1511    // some value >= 8 to get a full FF value
1512    return -bitInAByte >> 8;
1513}
1514
1515static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
1516    SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
1517    SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
1518
1519    const int width = srcMask.fBounds.width();
1520    const int height = srcMask.fBounds.height();
1521
1522    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
1523    const size_t srcRB = srcMask.fRowBytes;
1524    uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage;
1525    const size_t dstRB = dstMask->fRowBytes;
1526
1527    const int wholeBytes = width >> 3;
1528    const int leftOverBits = width & 7;
1529
1530    for (int y = 0; y < height; ++y) {
1531        uint8_t* SK_RESTRICT d = dst;
1532        for (int i = 0; i < wholeBytes; ++i) {
1533            int srcByte = src[i];
1534            d[0] = bit2byte(srcByte & (1 << 7));
1535            d[1] = bit2byte(srcByte & (1 << 6));
1536            d[2] = bit2byte(srcByte & (1 << 5));
1537            d[3] = bit2byte(srcByte & (1 << 4));
1538            d[4] = bit2byte(srcByte & (1 << 3));
1539            d[5] = bit2byte(srcByte & (1 << 2));
1540            d[6] = bit2byte(srcByte & (1 << 1));
1541            d[7] = bit2byte(srcByte & (1 << 0));
1542            d += 8;
1543        }
1544        if (leftOverBits) {
1545            int srcByte = src[wholeBytes];
1546            for (int x = 0; x < leftOverBits; ++x) {
1547                *d++ = bit2byte(srcByte & 0x80);
1548                srcByte <<= 1;
1549            }
1550        }
1551        src += srcRB;
1552        dst += dstRB;
1553    }
1554}
1555
1556void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
1557    SkASSERT(fAAClip->getBounds().contains(clip));
1558
1559    if (fAAClip->quickContains(clip)) {
1560        fBlitter->blitMask(origMask, clip);
1561        return;
1562    }
1563
1564    const SkMask* mask = &origMask;
1565
1566    // if we're BW, we need to upscale to A8 (ugh)
1567    SkMask  grayMask;
1568    grayMask.fImage = NULL;
1569    if (SkMask::kBW_Format == origMask.fFormat) {
1570        grayMask.fFormat = SkMask::kA8_Format;
1571        grayMask.fBounds = origMask.fBounds;
1572        grayMask.fRowBytes = origMask.fBounds.width();
1573        size_t size = grayMask.computeImageSize();
1574        grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size,
1575                                               SkAutoMalloc::kReuse_OnShrink);
1576
1577        upscaleBW2A8(&grayMask, origMask);
1578        mask = &grayMask;
1579    }
1580
1581    this->ensureRunsAndAA();
1582
1583    // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
1584    // data into a temp block to support it better (ugh)
1585
1586    const void* src = mask->getAddr(clip.fLeft, clip.fTop);
1587    const size_t srcRB = mask->fRowBytes;
1588    const int width = clip.width();
1589    MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
1590
1591    SkMask rowMask;
1592    rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
1593    rowMask.fBounds.fLeft = clip.fLeft;
1594    rowMask.fBounds.fRight = clip.fRight;
1595    rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1
1596    rowMask.fImage = (uint8_t*)fScanlineScratch;
1597
1598    int y = clip.fTop;
1599    const int stopY = y + clip.height();
1600
1601    do {
1602        int localStopY;
1603        const uint8_t* row = fAAClip->findRow(y, &localStopY);
1604        // findRow returns last Y, not stop, so we add 1
1605        localStopY = SkMin32(localStopY + 1, stopY);
1606
1607        int initialCount;
1608        row = fAAClip->findX(row, clip.fLeft, &initialCount);
1609        do {
1610            mergeProc(src, width, row, initialCount, rowMask.fImage);
1611            rowMask.fBounds.fTop = y;
1612            rowMask.fBounds.fBottom = y + 1;
1613            fBlitter->blitMask(rowMask, rowMask.fBounds);
1614            src = (const void*)((const char*)src + srcRB);
1615        } while (++y < localStopY);
1616    } while (y < stopY);
1617}
1618
1619const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
1620    return NULL;
1621}
1622
1623