SkAAClip.cpp revision 34f7e47a3593911d03307a08e5af625b218ceec3
1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc.
4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *
5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be
6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file.
7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
9e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h"
10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h"
11e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h"
12e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.h"
13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkThread.h"
1434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h"
15e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32   0x7FFFFFFF
171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
18e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
19e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
20e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
21e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
22e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
23e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
24e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
25e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
26e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
27e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *  Data runs are packed [count, alpha]
28e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
29e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
30e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset {
31e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t  fY;
32e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint32_t fOffset;
33e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
34e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
35e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead {
36e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRefCnt;
37e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRowCount;
38e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fDataSize;
39e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    YOffset* yoffsets() {
41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (YOffset*)((char*)this + sizeof(RunHead));
42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
43e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoffsets() const {
44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const YOffset*)((const char*)this + sizeof(RunHead));
45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint8_t* data() {
47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (uint8_t*)(this->yoffsets() + fRowCount);
48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* data() const {
50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const uint8_t*)(this->yoffsets() + fRowCount);
51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static RunHead* Alloc(int rowCount, size_t dataSize) {
54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize;
55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = (RunHead*)sk_malloc_throw(size);
56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRefCnt = 1;
57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRowCount = rowCount;
58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fDataSize = dataSize;
59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return head;
60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
61e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
62e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
63322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter {
64322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
65322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Iter(const SkAAClip&);
66322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
67322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int top() const { return fTop; }
691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int bottom() const { return fBottom; }
701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    const uint8_t* data() const { return fData; }
71322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next();
72322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
73322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
74322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fCurrYOff;
75322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fStopYOff;
76322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t* fData;
77322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
78322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int fTop, fBottom;
79322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool fDone;
80322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
81322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
82322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) {
83322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip.isEmpty()) {
84322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fDone = true;
851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        fTop = fBottom = clip.fBounds.fBottom;
861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        fData = NULL;
87322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
88322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
89322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
90322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const RunHead* head = clip.fRunHead;
91322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fCurrYOff = head->yoffsets();
92322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fStopYOff = fCurrYOff + head->fRowCount;
93322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fData     = head->data() + fCurrYOff->fOffset;
94322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
95322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // setup first value
96322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fTop = clip.fBounds.fTop;
97322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1;
98322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fDone = false;
99322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
100322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
101322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() {
1021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (!fDone) {
1031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* prev = fCurrYOff;
1041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* curr = prev + 1;
1051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(curr <= fStopYOff);
106322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
107322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fTop = fBottom;
1081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (curr >= fStopYOff) {
1091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
1101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom = kMaxInt32;
1111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fData = NULL;
1121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
1131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom += curr->fY - prev->fY;
1141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fData += curr->fOffset - prev->fOffset;
1151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fCurrYOff = curr;
1161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
119322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() {
12347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (fRunHead) {
124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fRunHead->fRefCnt >= 1);
125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) {
126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_free(fRunHead);
127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() {
132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
13347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) {
13747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    *this = src;
139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() {
142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
145e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) {
146e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this != &src) {
147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->freeRuns();
148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBounds = src.fBounds;
149e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fRunHead = src.fRunHead;
15047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com        if (fRunHead) {
151e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_atomic_inc(&fRunHead->fRefCnt);
152e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return *this;
155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
157e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) {
158e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (&a == &b) {
159e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (a.fBounds != b.fBounds) {
162e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
163e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
164e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
165e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* ah = a.fRunHead;
166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* bh = b.fRunHead;
167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
168e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // this catches empties and rects being equal
169e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (ah == bh) {
170e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
171e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
172e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
173e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now we insist that both are complex (but different ptrs)
17447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (!a.fRunHead || !b.fRunHead) {
175e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
176e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
177e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
178e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return  ah->fRowCount == bh->fRowCount &&
179e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ah->fDataSize == bh->fDataSize &&
180e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            !memcmp(ah->data(), bh->data(), ah->fDataSize);
181e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
182e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
183e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) {
184e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fBounds, other.fBounds);
185e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fRunHead, other.fRunHead);
186e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
187e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) {
189322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    *this = src;
190322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return !this->isEmpty();
191322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
192322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
193e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() {
194e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
195e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
19647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
197e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return false;
198e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) {
201e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (bounds.isEmpty()) {
202e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
203e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
20447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
20547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    // TODO: special case this
20647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
20747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkRect r;
20847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    r.set(bounds);
20947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkPath path;
21047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    path.addRect(r);
21147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->setPath(path);
212e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
213e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
214f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) {
215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (r.isEmpty()) {
216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
219e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkPath path;
220e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    path.addRect(r);
221f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    return this->setPath(path, NULL, doAA);
222f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com}
223f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com
224f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) {
225f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isEmpty()) {
226f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setEmpty();
227f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
228f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isRect()) {
229f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setRect(rgn.getBounds());
230f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
231f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com
232f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkAAClip clip;
233f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkRegion::Iterator iter(rgn);
234f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    for (; !iter.done(); iter.next()) {
235f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        clip.op(iter.rect(), SkRegion::kUnion_Op);
236f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
237f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    this->swap(clip);
2383771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com    return !this->isEmpty();
239e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
240e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
241e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
242e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
243e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
24447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkASSERT(fRunHead);
245e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
246e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!y_in_rect(y, fBounds)) {
247e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return NULL;
248e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
249e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    y -= fBounds.y();  // our yoffs values are relative to the top
250e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
251e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoff = fRunHead->yoffsets();
252e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (yoff->fY < y) {
253e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        yoff += 1;
254e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
255e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
256e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
257e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastYForRow) {
258e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        *lastYForRow = yoff->fY;
259e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
260e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return fRunHead->data() + yoff->fOffset;
261e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
262e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
263e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
264e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(x_in_rect(x, fBounds));
265e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    x -= fBounds.x();
266e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
267e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // first skip up to X
268e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
269e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int n = data[0];
270e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (x < n) {
271e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            *initialCount = n - x;
272e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
273e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
274e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
275e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= n;
276e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
277e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return data;
278e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
279e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
280e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
281e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isEmpty()) {
282e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
283e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
284e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!fBounds.contains(left, top, right, bottom)) {
285e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
286e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
287322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0
288e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isRect()) {
289e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
290e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
291322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif
292e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
293e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
294e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = this->findRow(top, &lastY);
295e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastY < bottom) {
296e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
297e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
298e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now just need to check in X
299e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
300e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = this->findX(row, left, &initialCount);
301e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return initialCount >= (right - left) && 0xFF == row[1];
302e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
303e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
304e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
305e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
306e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder {
307e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect fBounds;
308e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    struct Row {
309e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fY;
310e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fWidth;
311e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>* fData;
312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    };
313e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTDArray<Row>  fRows;
314e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* fCurrRow;
315e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fPrevY;
316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fWidth;
317e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
318e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
319e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder(const SkIRect& bounds) : fBounds(bounds) {
320e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fPrevY = -1;
321e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fWidth = bounds.width();
322e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fCurrRow = NULL;
323e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
324e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
325e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    ~Builder() {
326e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fRows.begin();
327e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* stop = fRows.end();
328e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
329e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            delete row->fData;
330e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
331e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
332e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
333e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
334322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& getBounds() const { return fBounds; }
335322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
336e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void addRun(int x, int y, U8CPU alpha, int count) {
337e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(count > 0);
338e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x, y));
339e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x + count - 1, y));
340e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
341e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= fBounds.left();
342e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y -= fBounds.top();
343e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
344e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fCurrRow;
345e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (y != fPrevY) {
346e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(y > fPrevY);
347e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fPrevY = y;
348e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row = this->flushRow(true);
349e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fY = y;
350e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth = 0;
351e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fData);
352e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(0 == row->fData->count());
353e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fCurrRow = row;
354e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
355e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
356e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= x);
357e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth < fBounds.width());
358e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
359e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>& data = *row->fData;
360e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
361e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int gap = x - row->fWidth;
362e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (gap) {
363e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            AppendRun(data, 0, gap);
364e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth += gap;
365e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fWidth < fBounds.width());
366e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
367e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
368e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        AppendRun(data, alpha, count);
369e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row->fWidth += count;
370e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= fBounds.width());
371e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
372e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
373e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    RunHead* finish() {
374e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->flushRow(false);
375e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
376e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* row = fRows.begin();
377e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* stop = fRows.end();
378e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
379e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        size_t dataSize = 0;
380e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
381e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            dataSize += row->fData->count();
382e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
383e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
384e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
385e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
386e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        YOffset* yoffset = head->yoffsets();
387e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* data = head->data();
388e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* baseData = data;
389e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
390e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row = fRows.begin();
391e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
392e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset->fY = row->fY;
393e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset->fOffset = data - baseData;
394e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset += 1;
395e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
396e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            size_t n = row->fData->count();
397e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            memcpy(data, row->fData->begin(), n);
398e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            data += n;
399e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
400e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
401e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
402e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
403e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return head;
404e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
405e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
406e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void dump() {
407e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->validate();
408e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int y;
409e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (y = 0; y < fRows.count(); ++y) {
410e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[y];
411e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
412e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const SkTDArray<uint8_t>& data = *row.fData;
413e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = data.count();
414e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
415e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = data.begin();
416e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
417e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
418e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
419e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
420e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("\n");
421e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
422e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
4231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#if 0
424e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int prevY = -1;
425e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (y = 0; y < fRows.count(); ++y) {
426e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[y];
427e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const SkTDArray<uint8_t>& data = *row.fData;
428e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = data.count();
429e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int n = prevY; n < row.fY; ++n) {
430e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                const uint8_t* ptr = data.begin();
431e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                for (int x = 0; x < count; x += 2) {
432e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    for (int i = 0; i < ptr[0]; ++i) {
433e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                        SkDebugf("%02X", ptr[1]);
434e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    }
435e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    ptr += 2;
436e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
437e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkDebugf("\n");
438e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
439e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            prevY = row.fY;
440e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
441e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif
442e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
443e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
444e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void validate() {
445e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG
446e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int prevY = -1;
447e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (int i = 0; i < fRows.count(); ++i) {
448e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[i];
449e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prevY < row.fY);
450e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(fWidth == row.fWidth);
451e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = row.fData->count();
452e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = row.fData->begin();
453e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
454e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int w = 0;
455e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
456e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                w += ptr[0];
457e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkASSERT(w <= fWidth);
458e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
459e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
460e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(w == fWidth);
461e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            prevY = row.fY;
462e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
463e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif
464e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
465e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
466e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
467e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* flushRow(bool readyForAnother) {
468e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* next = NULL;
469e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fRows.count();
470e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 0) {
471e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            // flush current row if needed
472e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* curr = &fRows[count - 1];
473e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (curr->fWidth < fWidth) {
474e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                AppendRun(*curr->fData, 0, fWidth - curr->fWidth);
475e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
476e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
477e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 1) {
478e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            // are our last two runs the same?
479e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* prev = &fRows[count - 2];
480e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* curr = &fRows[count - 1];
481e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prev->fWidth == fWidth);
482e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(curr->fWidth == fWidth);
483e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (*prev->fData == *curr->fData) {
484e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                prev->fY = curr->fY;
485e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
486e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    curr->fData->rewind();
487e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = curr;
488e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                } else {
489e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    delete curr->fData;
490e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    fRows.removeShuffle(count - 1);
491e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
492e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            } else {
493e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
494e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = fRows.append();
495e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next->fData = new SkTDArray<uint8_t>;
496e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
497e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
498e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } else {
499e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (readyForAnother) {
500e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next = fRows.append();
501e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next->fData = new SkTDArray<uint8_t>;
502e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
503e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
504e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return next;
505e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
506e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
507e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
508e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        do {
509e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int n = count;
510e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (n > 255) {
511e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                n = 255;
512e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
513e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            uint8_t* ptr = data.append(2);
514e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[0] = n;
515e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[1] = alpha;
516e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            count -= n;
517e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } while (count > 0);
518e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
519e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
520e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
521e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter {
522e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
523e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter(Builder* builder) {
524e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder = builder;
5251778564c75de5799d45126984f8faafd03523100reed@google.com        fLeft = builder->getBounds().fLeft;
5261778564c75de5799d45126984f8faafd03523100reed@google.com        fRight = builder->getBounds().fRight;
527e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
528e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
529e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE
530e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
531e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE
532e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
533e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
534e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
535e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
536e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE {
5373771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com        return NULL;
538e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
539e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
540e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitH(int x, int y, int width) SK_OVERRIDE {
541e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder->addRun(x, y, 0xFF, width);
542e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
543e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
544e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
545e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                           const int16_t runs[]) SK_OVERRIDE {
546e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (;;) {
547e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = *runs;
548e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (count <= 0) {
549e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                return;
550e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
5511778564c75de5799d45126984f8faafd03523100reed@google.com
5521778564c75de5799d45126984f8faafd03523100reed@google.com            // The supersampler's buffer can be the width of the device, so
5531778564c75de5799d45126984f8faafd03523100reed@google.com            // we may have to trim the run to our bounds. If so, we assert that
5541778564c75de5799d45126984f8faafd03523100reed@google.com            // the extra spans are always alpha==0
5551778564c75de5799d45126984f8faafd03523100reed@google.com            int localX = x;
5561778564c75de5799d45126984f8faafd03523100reed@google.com            int localCount = count;
5571778564c75de5799d45126984f8faafd03523100reed@google.com            if (x < fLeft) {
5581778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(0 == *alpha);
5591778564c75de5799d45126984f8faafd03523100reed@google.com                int gap = fLeft - x;
5601778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(gap <= count);
5611778564c75de5799d45126984f8faafd03523100reed@google.com                localX += gap;
5621778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= gap;
5631778564c75de5799d45126984f8faafd03523100reed@google.com            }
5641778564c75de5799d45126984f8faafd03523100reed@google.com            int right = x + count;
5651778564c75de5799d45126984f8faafd03523100reed@google.com            if (right > fRight) {
5661778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(0 == *alpha);
5671778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= right - fRight;
5681778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(localCount >= 0);
5691778564c75de5799d45126984f8faafd03523100reed@google.com            }
5701778564c75de5799d45126984f8faafd03523100reed@google.com
5711778564c75de5799d45126984f8faafd03523100reed@google.com            if (localCount) {
5721778564c75de5799d45126984f8faafd03523100reed@google.com                fBuilder->addRun(localX, y, *alpha, localCount);
5731778564c75de5799d45126984f8faafd03523100reed@google.com            }
5741778564c75de5799d45126984f8faafd03523100reed@google.com        NEXT_RUN:
575e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            runs += count;
576e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            alpha += count;
577e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            x += count;
578e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
579e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
580e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
581e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
582e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder* fBuilder;
5831778564c75de5799d45126984f8faafd03523100reed@google.com    int      fLeft; // cache of builder's bounds' left edge
5841778564c75de5799d45126984f8faafd03523100reed@google.com    int      fRight;
585e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
586e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void unexpected() {
587e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkDebugf("---- did not expect to get called here");
588e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        sk_throw();
589e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
590e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
591e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
592f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
593322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip && clip->isEmpty()) {
594e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
595e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
596e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
597e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect ibounds;
598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    path.getBounds().roundOut(&ibounds);
599e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
600322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkRegion tmpClip;
601322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (NULL == clip) {
602322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        tmpClip.setRect(ibounds);
603322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        clip = &tmpClip;
604322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
605322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
606e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!path.isInverseFillType()) {
607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
608e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return this->setEmpty();
609e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
610e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
611e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
612e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder        builder(ibounds);
613e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter blitter(&builder);
614e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
615f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (doAA) {
616f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        SkScan::AntiFillPath(path, *clip, &blitter, true);
617f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    } else {
618f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        SkScan::FillPath(path, *clip, &blitter);
619f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
620e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds = ibounds;
623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fRunHead = builder.finish();
624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
6253771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com    //builder.dump();
6263771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com    return !this->isEmpty();
627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
631322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom,
632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowA, const SkIRect& rectA,
633322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowB, const SkIRect& rectB);
634322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
635322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void sectRowProc(SkAAClip::Builder& builder, int bottom,
636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowA, const SkIRect& rectA,
637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowB, const SkIRect& rectB) {
638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
642322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
643322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
644322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // Multiply
645322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, alphaB);
646322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
647322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
648322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
649322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOver
650322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
651322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
652322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
653322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
654322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOut
655322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, 0xFF - alphaB);
656322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
657322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
658322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
659322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // XOR
660322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
661322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
662322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
663322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) {
664322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
665322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
666322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
667322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
668322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return diffAlphaProc;
669322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
670322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return unionAlphaProc;
671322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
672322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return xorAlphaProc;
673322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
674322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            SkASSERT(!"unexpected region op");
675322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
676322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
677322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
678322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
679322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic const uint8_t gEmptyRow[] = {
680322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
681322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
682322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
683322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
684322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
685322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
686322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
687322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
688322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
689322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
690322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter {
691322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
692322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    RowIter(const uint8_t* row, const SkIRect& bounds) {
693322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fRow = row;
694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fLeft = bounds.fLeft;
695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fBoundsRight = bounds.fRight;
6961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (row) {
6971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = bounds.fLeft + row[0];
6981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(fRight <= fBoundsRight);
6991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = row[1];
7001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = false;
7011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
7021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
7031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = kMaxInt32;
7041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = 0;
7051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
706322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
707322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
708322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
7091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int left() const { return fLeft; }
7101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int right() const { return fRight; }
7111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    U8CPU alpha() const { return fAlpha; }
712322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next() {
7131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!fDone) {
714322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            fLeft = fRight;
7151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (fRight == fBoundsRight) {
7161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fDone = true;
7171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight = kMaxInt32;
7181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = 0;
7191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
7201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRow += 2;
7211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight += fRow[0];
7221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = fRow[1];
7231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                SkASSERT(fRight <= fBoundsRight);
7241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
725322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
726322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
727322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
728322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
729322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t*  fRow;
730322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fLeft;
731322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fRight;
732322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fBoundsRight;
733322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool            fDone;
7341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    uint8_t         fAlpha;
735322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
736322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
7371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
7381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (rite == riteA) {
7391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
7401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        leftA = iter.left();
7411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        riteA = iter.right();
742322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
743322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
744322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
7451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
7461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(min < max);
7471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(boundsMin < boundsMax);
7481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min >= boundsMax || max <= boundsMin) {
7491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        return false;
7501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
7511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min < boundsMin) {
7521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        min = boundsMin;
7531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
7541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (max > boundsMax) {
7551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        max = boundsMax;
7561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
7571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    return true;
7581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
7591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
760322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY,
761322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      RowIter& iterA, RowIter& iterB,
762322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      AlphaProc proc, const SkIRect& bounds) {
763322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftA = iterA.left();
764322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteA = iterA.right();
765322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftB = iterB.left();
766322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteB = iterB.right();
767322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
7681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int prevRite = bounds.fLeft;
7691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
7701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
771322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaA = 0;
772322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaB = 0;
773322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int left, rite;
7741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
7751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (leftA < leftB) {
776322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftA;
777322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
7781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteA <= leftB) {
7791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteA;
7801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
7811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftA = leftB;
7821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
7831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (leftB < leftA) {
784322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftB;
785322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
7861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteB <= leftA) {
7871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteB;
7881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
7891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftB = leftA;
7901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
791322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
7921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            left = leftA;   // or leftB, since leftA == leftB
7931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            rite = leftA = leftB = SkMin32(riteA, riteB);
794322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
795322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
796322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
797322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
798322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fRight) {
799322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
800322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
80134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (rite > bounds.fRight) {
80234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            rite = bounds.fRight;
80334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
80434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
805322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fLeft) {
8061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(rite > left);
807322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
8081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            prevRite = rite;
809322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
8101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
8111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterA, leftA, riteA, rite);
8121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterB, leftB, riteB, rite);
8131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
8141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
8151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (prevRite < bounds.fRight) {
8161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
817322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
818322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
819322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
8201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
8211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (bot == botA) {
8221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
8231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        topA = botA;
8241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(botA == iter.top());
8251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        botA = iter.bottom();
826322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
827322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
828322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
829322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
830322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                     const SkAAClip& B, SkRegion::Op op) {
831322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    AlphaProc proc = find_alpha_proc(op);
832322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& bounds = builder.getBounds();
833322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
834322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterA(A);
835322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterB(B);
836322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
837322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterA.done());
838322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topA = iterA.top();
839322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botA = iterA.bottom();
840322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterB.done());
841322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topB = iterB.top();
842322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botB = iterB.bottom();
843322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
8441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
8451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const uint8_t* rowA = NULL;
8461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const uint8_t* rowB = NULL;
847322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int top, bot;
8481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
8491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (topA < topB) {
850322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topA;
851322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
8521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botA <= topB) {
8531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botA;
8541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
8551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topA = topB;
8561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
8571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
8581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (topB < topA) {
859322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topB;
860322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
8611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botB <= topA) {
8621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botB;
8631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
8641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topB = topA;
8651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
866322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
8671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            top = topA;   // or topB, since topA == topB
8681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            bot = topA = topB = SkMin32(botA, botB);
869322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
870322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
871322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
872322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
873322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (top >= bounds.fBottom) {
874322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
875322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
87634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
87734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (bot > bounds.fBottom) {
87834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            bot = bounds.fBottom;
87934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
88034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        SkASSERT(top < bot);
88134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
8821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!rowA && !rowB) {
8831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
8841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (top >= bounds.fTop) {
8851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(bot <= bounds.fBottom);
8861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
8871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
888322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
889322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
890322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
8911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterA, topA, botA, bot);
8921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterB, topB, botB, bot);
8931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
894322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
895322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
896322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
897322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                  SkRegion::Op op) {
898322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReplace_Op == op) {
899322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return this->set(clipBOrig);
900322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
901322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
902322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipA = &clipAOrig;
903322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipB = &clipBOrig;
904322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
905322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReverseDifference_Op == op) {
906322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        SkTSwap(clipA, clipB);
907322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        op = SkRegion::kDifference_Op;
908322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
909322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
910322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool a_empty = clipA->isEmpty();
911322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool b_empty = clipB->isEmpty();
912322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
913322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkIRect bounds;
914322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
915322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
916322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
917322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
918322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
919322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
920322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
921322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
922322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
923322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
924322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
925322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
926322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
927322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                                                         clipB->fBounds)) {
928322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
929322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
930322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
931322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
932322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
933322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
934322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
935322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipB);
936322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
937322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty) {
938322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
939322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
940322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
941322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds.join(clipB->fBounds);
942322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
943322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
944322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
945322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            SkASSERT(!"unknown region op");
946322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return !this->isEmpty();
947322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
948322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
949322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
950322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
951322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
952322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Builder builder(bounds);
953322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    operateY(builder, *clipA, *clipB, op);
954322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // don't free us until now, since we might be clipA or clipB
955322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    this->freeRuns();
956322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fBounds = bounds;
957322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fRunHead = builder.finish();
958322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
959322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return !this->isEmpty();
960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
96247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkIRect& r, SkRegion::Op op) {
96347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
96447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    clip.setRect(r);
96547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
96647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
96747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
9680017708a5bcb6d0fbff0fac565085bef65de7433reed@google.combool SkAAClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
96947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
9700017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    clip.setRect(r, doAA);
97147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
97247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
97347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
97447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
97547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
97647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
97747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                         int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // we don't read our initial n from data, since the caller may have had to
984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // clip it, hence the initialCount parameter.
985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int n = initialCount;
986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (n > width) {
988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            n = width;
989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(n > 0);
991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs[0] = n;
992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs += n;
993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa[0] = data[1];
995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa += n;
996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        width -= n;
999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == width) {
1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // load the next count
1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        n = data[0];
1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    runs[0] = 0;    // sentinel
1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() {
1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    sk_free(fRuns);
1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() {
1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (NULL == fRuns) {
1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // add 1 so we can store the terminating run count of 0
1015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fAAClipBounds.width() + 1;
1016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fRuns = (int16_t*)sk_malloc_throw(count * sizeof(int16_t) +
1017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                                          count * sizeof(SkAlpha));
1018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fAA = (SkAlpha*)(fRuns + count);
1019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
102034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    SkDEBUGCODE(sk_memset16((uint16_t*)fRuns, 0xFFFF, fAAClipBounds.width() + 1);)
1021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) {
1024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(width > 0);
1025e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x, y));
1026e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1027e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1028e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
1029e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = fAAClip->findRow(y, &lastY);
1030e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
1031e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
1032e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1033e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (initialCount >= width) {
1034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha alpha = row[1];
1035e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == alpha) {
1036e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1037e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1038e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0xFF == alpha) {
1039e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fBlitter->blitH(x, y, width);
1040e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1041e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1042e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1043e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
1045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    expandToRuns(row, initialCount, width, fRuns, fAA);
1046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
1048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN,
1051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const SkAlpha* SK_RESTRICT srcAA,
1052e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const int16_t* SK_RESTRICT srcRuns,
1053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  SkAlpha* SK_RESTRICT dstAA,
1054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int16_t* SK_RESTRICT dstRuns,
1055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int width) {
1056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkDEBUGCODE(int accumulated = 0;)
1057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int srcN = srcRuns[0];
1058e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
1059e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == srcN) {
1060e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
1061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(rowN > 0);
1063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(srcN > 0);
1064e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1065e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1066e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int minN = SkMin32(srcN, rowN);
1067e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns[0] = minN;
1068e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns += minN;
1069e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA[0] = newAlpha;
1070e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA += minN;
1071e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1072e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (srcN -= minN)) {
1073e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // refresh
1074e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcRuns += srcN;
1075e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcAA += srcN;
1076e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // reload
1077e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (rowN -= minN)) {
1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 2;
1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            rowN = row[0];  // reload
1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1082e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1083e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkDEBUGCODE(accumulated += minN;)
1084e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(accumulated <= width);
1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
108634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    dstRuns[0] = 0;
1087e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1089e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
1090e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                                const int16_t runs[]) {
1091e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
1092e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = fAAClip->findRow(y, &lastY);
1093e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1096e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
1097e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1098e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1102e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1103e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + 1, y + height)) {
1104e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitV(x, y, height, alpha);
1105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
1106e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1107e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1108e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int stopY = y + height;
1109e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    do {
1110e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int lastY;
1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const uint8_t* row = fAAClip->findRow(y, &lastY);
1112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int initialCount;
1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row = fAAClip->findX(row, x, &initialCount);
1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (newAlpha) {
1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fBlitter->blitV(x, y, lastY - y + 1, newAlpha);
1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1118e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y = lastY + 1;
1119e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    } while (y < stopY);
1120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + width, y + height)) {
1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitRect(x, y, width, height);
1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
1126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (--height >= 0) {
1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->blitH(x, y, width);
1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y += 1;
1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitMask(mask, clip);
1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return NULL;
1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com///////////////////////////////////////////////////////////////////////////////
1143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
114434f7e47a3593911d03307a08e5af625b218ceec3reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
114534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (NULL == dst) {
114634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return !this->isEmpty();
11471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
11481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
11491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (this->isEmpty()) {
115034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return dst->setEmpty();
11511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
11521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
115334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (this != dst) {
115434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        sk_atomic_inc(&fRunHead->fRefCnt);
115534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        dst->fRunHead = fRunHead;
115634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        dst->fBounds = fBounds;
115734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
11581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    dst->fBounds.offset(dx, dy);
11591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    return true;
11601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
11611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
1163322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                               const uint8_t* SK_RESTRICT row,
1164322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                               int width) {
1165322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    while (width > 0) {
1166322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int n = row[0];
1167322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        SkASSERT(width >= n);
1168322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        memset(mask, row[1], n);
1169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        mask += n;
1170322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        row += 2;
1171322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        width -= n;
1172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1175322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const {
1176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    mask->fFormat = SkMask::kA8_Format;
1177322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (this->isEmpty()) {
1178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        mask->fBounds.setEmpty();
1179322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        mask->fImage = NULL;
1180322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        mask->fRowBytes = 0;
1181322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
1182322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1183322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    mask->fBounds = fBounds;
1185322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    mask->fRowBytes = fBounds.width();
1186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    size_t size = mask->computeImageSize();
1187322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    mask->fImage = SkMask::AllocImage(size);
1188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1189322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Iter iter(*this);
1190322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    uint8_t* dst = mask->fImage;
1191322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const int width = fBounds.width();
1192322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1193322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int y = fBounds.fTop;
1194322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    while (!iter.done()) {
1195322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        do {
1196322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            expand_row_to_mask(dst, iter.data(), width);
1197322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            dst += mask->fRowBytes;
1198322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } while (++y < iter.bottom());
1199322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        iter.next();
1200322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1201322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1202322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1203