SkAAClip.cpp revision f74ad8c91aef4f328dbcbcebae9e436c00a35140
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"
11045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkColorPriv.h"
12e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h"
13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.h"
14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkThread.h"
1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h"
16e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
17045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comclass AutoAAClipValidate {
18045e62d715f5ee9b03deb5af3c750f8318096179reed@google.compublic:
19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) {
20045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.validate();
21045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    ~AutoAAClipValidate() {
23045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.validate();
24045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate:
26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkAAClip& fClip;
27045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com};
28045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
29045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG
30045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    #define AUTO_AACLIP_VALIDATE(clip)  AutoAAClipValidate acv(clip)
31045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
32045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    #define AUTO_AACLIP_VALIDATE(clip)
33045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
34045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
35045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
36045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32   0x7FFFFFFF
381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
39e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
43e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *  Data runs are packed [count, alpha]
49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset {
52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t  fY;
53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint32_t fOffset;
54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead {
57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRefCnt;
58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRowCount;
59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fDataSize;
60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
61e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    YOffset* yoffsets() {
62e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (YOffset*)((char*)this + sizeof(RunHead));
63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoffsets() const {
65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const YOffset*)((const char*)this + sizeof(RunHead));
66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint8_t* data() {
68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (uint8_t*)(this->yoffsets() + fRowCount);
69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* data() const {
71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const uint8_t*)(this->yoffsets() + fRowCount);
72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static RunHead* Alloc(int rowCount, size_t dataSize) {
75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize;
76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = (RunHead*)sk_malloc_throw(size);
77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRefCnt = 1;
78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRowCount = rowCount;
79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fDataSize = dataSize;
80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return head;
81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
82045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
83045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    static int ComputeRowSizeForWidth(int width) {
84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // 2 bytes per segment, where each segment can store up to 255 for count
85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int segments = 0;
86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        while (width > 0) {
87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            segments += 1;
88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int n = SkMin32(width, 255);
89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            width -= n;
90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return segments * 2;    // each segment is row[0] + row[1] (n + alpha)
92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    static RunHead* AllocRect(const SkIRect& bounds) {
95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(!bounds.isEmpty());
96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int width = bounds.width();
97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t rowSize = ComputeRowSizeForWidth(width);
98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        RunHead* head = RunHead::Alloc(1, rowSize);
99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        YOffset* yoff = head->yoffsets();
100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        yoff->fY = bounds.height() - 1;
101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        yoff->fOffset = 0;
102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        uint8_t* row = head->data();
103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        while (width > 0) {
104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int n = SkMin32(width, 255);
105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row[0] = n;
106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row[1] = 0xFF;
107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            width -= n;
108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row += 2;
109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return head;
111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
114322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter {
115322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Iter(const SkAAClip&);
117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
1191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int top() const { return fTop; }
1201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int bottom() const { return fBottom; }
1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    const uint8_t* data() const { return fData; }
122322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next();
123322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fCurrYOff;
126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fStopYOff;
127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t* fData;
128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int fTop, fBottom;
130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool fDone;
131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) {
134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip.isEmpty()) {
135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fDone = true;
1361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        fTop = fBottom = clip.fBounds.fBottom;
1371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        fData = NULL;
138322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
139322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
140322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
141322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const RunHead* head = clip.fRunHead;
142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fCurrYOff = head->yoffsets();
143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fStopYOff = fCurrYOff + head->fRowCount;
144322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fData     = head->data() + fCurrYOff->fOffset;
145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // setup first value
147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fTop = clip.fBounds.fTop;
148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1;
149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fDone = false;
150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() {
1531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (!fDone) {
1541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* prev = fCurrYOff;
1551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* curr = prev + 1;
1561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(curr <= fStopYOff);
157322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
158322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fTop = fBottom;
1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (curr >= fStopYOff) {
1601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
1611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom = kMaxInt32;
1621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fData = NULL;
1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom += curr->fY - prev->fY;
1651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fData += curr->fOffset - prev->fOffset;
1661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fCurrYOff = curr;
1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
168322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
170322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG
172c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used
173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) {
174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const uint8_t* origRow = row;
175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (width > 0) {
176045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = row[0];
177c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(n <= width);
179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        width -= n;
181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(0 == width);
183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return row - origRow;
184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const {
187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (NULL == fRunHead) {
188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(fBounds.isEmpty());
189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const RunHead* head = fRunHead;
193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRefCnt > 0);
194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRowCount > 0);
195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fDataSize > 0);
196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* yoff = head->yoffsets();
198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* ystop = yoff + head->fRowCount;
199c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int lastY = fBounds.height() - 1;
200c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
201c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // Y and offset must be monotonic
202c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int prevY = -1;
203c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int32_t prevOffset = -1;
204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (yoff < ystop) {
205c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(prevY < yoff->fY);
206c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(yoff->fY <= lastY);
207c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        prevY = yoff->fY;
208c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(prevOffset < (int32_t)yoff->fOffset);
209c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        prevOffset = yoff->fOffset;
210c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* row = head->data() + yoff->fOffset;
211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t rowLength = compute_row_length(row, fBounds.width());
212f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com        SkASSERT(yoff->fOffset + rowLength <= (size_t) head->fDataSize);
213c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // check the last entry;
216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    --yoff;
217c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(yoff->fY == lastY);
218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
223c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width,
224c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                                   int* leftZ, int* riteZ) {
225c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int zeros = 0;
226c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
227c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (row[1]) {
228c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
229c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
230c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
231c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
232c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
233c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        zeros += n;
234c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
235c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
236c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (width > 0);
237c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    *leftZ = zeros;
238c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
239c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    zeros = 0;
240c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (width > 0) {
241c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
242c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
243c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (0 == row[1]) {
244c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            zeros += n;
245c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        } else {
246c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            zeros = 0;
247c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
248c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
249c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
250c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
251c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    *riteZ = zeros;
252c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
253c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
254c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
255c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() {
256c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    static bool gOnce;
257c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (gOnce) {
258c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return;
259c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
260c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    gOnce = true;
261c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
262c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data0[] = {  0, 0,     10, 0xFF };
263c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data1[] = {  0, 0,     5, 0xFF, 2, 0, 3, 0xFF };
264c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data2[] = {  7, 0,     5, 0, 2, 0, 3, 0xFF };
265c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data3[] = {  0, 5,     5, 0xFF, 2, 0, 3, 0 };
266c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data4[] = {  2, 3,     2, 0, 5, 0xFF, 3, 0 };
267c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data5[] = { 10, 0,     10, 0 };
268c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data6[] = {  2, 2,     2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
269c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t* array[] = {
271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data0, data1, data2, data3, data4, data5, data6
272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    };
273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* data = array[i];
276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedL = *data++;
277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedR = *data++;
278c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int L = 12345, R = 12345;
279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        count_left_right_zeros(data, 10, &L, &R);
280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedL == L);
281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedR == R);
282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
284c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
285c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
286c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides.
287c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left
288c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) {
289c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int trim = 0;
290c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (leftZ > 0) {
291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(0 == row[1]);
292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (n > leftZ) {
298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row[-2] = n - leftZ;
299c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        trim += 2;
302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        leftZ -= n;
303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(leftZ >= 0);
304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
306c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (riteZ) {
307c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // walk row to the end, and then we'll back up to trim riteZ
308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        while (width > 0) {
309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            int n = row[0];
310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(n <= width);
311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            width -= n;
312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row += 2;
313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // now skip whole runs of zeros
315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        do {
316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row -= 2;
317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(0 == row[1]);
318c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            int n = row[0];
319c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(n > 0);
320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            if (n > riteZ) {
321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                row[0] = n - riteZ;
322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                break;
323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            }
324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            riteZ -= n;
325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(riteZ >= 0);
326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        } while (riteZ > 0);
327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return trim;
330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width
334c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) {
335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (width > 0) {
336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
339c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
340c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(0 == width);
343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
345c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() {
346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    static bool gOnce;
347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (gOnce) {
348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return;
349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    gOnce = true;
351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data0[] = {  0, 0, 0,   10,    10, 0xFF };
353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data1[] = {  2, 0, 0,   10,    5, 0, 2, 0, 3, 0xFF };
354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data2[] = {  5, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data3[] = {  6, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
356c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data4[] = {  0, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data5[] = {  1, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data6[] = {  0, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data7[] = {  1, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data8[] = {  2, 2, 2,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data9[] = {  5, 2, 4,   10,    2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 };
362c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data10[] ={  74, 0, 4, 150,    9, 0, 65, 0, 76, 0xFF };
363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t* array[] = {
365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data0, data1, data2, data3, data4,
366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data5, data6, data7, data8, data9,
367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data10
368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    };
369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        uint8_t* data = array[i];
372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int trimL = *data++;
373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int trimR = *data++;
374c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedSkip = *data++;
375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int origWidth = *data++;
376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        assert_row_width(data, origWidth);
377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int skip = trim_row_left_right(data, origWidth, trimL, trimR);
378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedSkip == skip);
379c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int expectedWidth = origWidth - trimL - trimR;
380c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        assert_row_width(data + skip, expectedWidth);
381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
385c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() {
386c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkDEBUGCODE(test_trim_row_left_right();)
387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (this->isEmpty()) {
389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return false;
390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    AUTO_AACLIP_VALIDATE(*this);
393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int width = fBounds.width();
395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    RunHead* head = fRunHead;
396c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* yoff = head->yoffsets();
397c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* stop = yoff + head->fRowCount;
398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t* base = head->data();
399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int leftZeros = width;
401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int riteZeros = width;
402c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
403c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int L, R;
404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        count_left_right_zeros(base + yoff->fOffset, width, &L, &R);
405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (L < leftZeros) {
406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            leftZeros = L;
407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (R < riteZeros) {
409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            riteZeros = R;
410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
411c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (0 == (leftZeros | riteZeros)) {
412c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            // no trimming to do
413c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            return true;
414c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
415c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(leftZeros || riteZeros);
419c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (width == (leftZeros + riteZeros)) {
420c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return this->setEmpty();
421c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    this->validate();
424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    fBounds.fLeft += leftZeros;
426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    fBounds.fRight -= riteZeros;
427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(!fBounds.isEmpty());
428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // For now we don't realloc the storage (for time), we just shrink in place
430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // This means we don't have to do any memmoves either, since we can just
431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // play tricks with the yoff->fOffset for each row
432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    yoff = head->yoffsets();
433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
434c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        uint8_t* row = base + yoff->fOffset;
435c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE((void)compute_row_length(row, width);)
436c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros);
437c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);)
438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
442c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
443c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) {
444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(width > 0);
445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (row[1]) {
447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            return false;
448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
451c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
452c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
453c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (width > 0);
454c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(0 == width);
455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
458c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() {
459c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (this->isEmpty()) {
460c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return false;
461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
463d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com    this->validate();
464d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com
465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int width = fBounds.width();
466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    RunHead* head = fRunHead;
467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* yoff = head->yoffsets();
468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* stop = yoff + head->fRowCount;
469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t* base = head->data();
470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  Look to trim away empty rows from the top.
472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //
473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int skip = 0;
474c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
475c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* data = base + yoff->fOffset;
476c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (!row_is_all_zeros(data, width)) {
477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
479c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        skip += 1;
480c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(skip <= head->fRowCount);
483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip == head->fRowCount) {
484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return this->setEmpty();
485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip > 0) {
487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // adjust fRowCount and fBounds.fTop, and slide all the data up
488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // as we remove [skip] number of YOffset entries
489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff = head->yoffsets();
490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int dy = yoff[skip - 1].fY + 1;
491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        for (int i = skip; i < head->fRowCount; ++i) {
492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(yoff[i].fY >= dy);
493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            yoff[i].fY -= dy;
494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        YOffset* dst = head->yoffsets();
496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize;
497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        memmove(dst, dst + skip, size - skip * sizeof(YOffset));
498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
499c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        fBounds.fTop += dy;
500c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(!fBounds.isEmpty());
501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        head->fRowCount -= skip;
502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(head->fRowCount > 0);
503d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com
504d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        this->validate();
505d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        // need to reset this after the memmove
506d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        base = head->data();
507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  Look to trim away empty rows from the bottom.
510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  We know that we have at least one non-zero row, so we can just walk
511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  backwards without checking for running past the start.
512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //
513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    stop = yoff = head->yoffsets() + head->fRowCount;
514c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
515c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff -= 1;
516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (row_is_all_zeros(base + yoff->fOffset, width));
517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    skip = stop - yoff - 1;
518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(skip >= 0 && skip < head->fRowCount);
519c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip > 0) {
520c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // removing from the bottom is easier than from the top, as we don't
521c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // have to adjust any of the Y values, we just have to trim the array
522c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        memmove(stop - skip, stop, head->fDataSize);
523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        fBounds.fBottom = fBounds.fTop + yoff->fY + 1;
525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(!fBounds.isEmpty());
526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        head->fRowCount -= skip;
527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(head->fRowCount > 0);
528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
529d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com    this->validate();
530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
533c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
534045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of
535045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its
536045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so
537045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up.
538045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com//
539045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data
540045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com//
541045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() {
542045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
543045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return false;
544045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
545045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
546045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const RunHead* head = fRunHead;
547045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* yoff = head->yoffsets();
548045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
549045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRowCount > 0);
550045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset& lastY = yoff[head->fRowCount - 1];
551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(lastY.fY + 1 <= fBounds.height());
552045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBounds.fBottom = fBounds.fTop + lastY.fY + 1;
553045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(lastY.fY + 1 == fBounds.height());
554c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(!fBounds.isEmpty());
555c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
556c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return this->trimTopBottom() && this->trimLeftRight();
557045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
558045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
559e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
560e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
561e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() {
56247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (fRunHead) {
563e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fRunHead->fRefCnt >= 1);
564e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) {
565e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_free(fRunHead);
566e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
567e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
568e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
569e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
570e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() {
571e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
57247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
573e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
574e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
575e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) {
576045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkDEBUGCODE(fBounds.setEmpty();)    // need this for validate
57747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
578e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    *this = src;
579e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
580e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
581e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() {
582e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
583e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
584e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
585e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) {
586045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
587045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    src.validate();
588045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
589e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this != &src) {
590e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->freeRuns();
591e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBounds = src.fBounds;
592e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fRunHead = src.fRunHead;
59347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com        if (fRunHead) {
594e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_atomic_inc(&fRunHead->fRefCnt);
595e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
596e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
597e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return *this;
598e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
599e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
600e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) {
601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    a.validate();
602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    b.validate();
603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
604e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (&a == &b) {
605e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
606e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
607e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (a.fBounds != b.fBounds) {
608e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
609e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
610e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
611e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* ah = a.fRunHead;
612e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* bh = b.fRunHead;
613e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
614e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // this catches empties and rects being equal
615e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (ah == bh) {
616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
617e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
618e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
619e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now we insist that both are complex (but different ptrs)
62047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (!a.fRunHead || !b.fRunHead) {
621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return  ah->fRowCount == bh->fRowCount &&
625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ah->fDataSize == bh->fDataSize &&
626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            !memcmp(ah->data(), bh->data(), ah->fDataSize);
627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) {
630045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
631045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    other.validate();
632045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
633e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fBounds, other.fBounds);
634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fRunHead, other.fRunHead);
635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) {
638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    *this = src;
639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return !this->isEmpty();
640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() {
643e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
644e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
64547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    fRunHead = NULL;
646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return false;
647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) {
650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (bounds.isEmpty()) {
651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
65347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
654045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
65547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
656045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0
65747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkRect r;
65847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    r.set(bounds);
65947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkPath path;
66047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    path.addRect(r);
66147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->setPath(path);
662045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
663045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    this->freeRuns();
664045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBounds = bounds;
665045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fRunHead = RunHead::AllocRect(bounds);
666045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(!this->isEmpty());
667045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return true;
668045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
670e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
671f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) {
672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (r.isEmpty()) {
673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
676045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
677045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
678045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // TODO: special case this
679045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkPath path;
681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    path.addRect(r);
682f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    return this->setPath(path, NULL, doAA);
683f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com}
684f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com
685f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) {
686f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isEmpty()) {
687f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setEmpty();
688f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
689f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isRect()) {
690f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setRect(rgn.getBounds());
691f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
692f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com
693f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkAAClip clip;
694f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkRegion::Iterator iter(rgn);
695f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    for (; !iter.done(); iter.next()) {
696f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        clip.op(iter.rect(), SkRegion::kUnion_Op);
697f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
698f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    this->swap(clip);
6993771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com    return !this->isEmpty();
700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
701e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
702e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
703e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
704e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
70547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkASSERT(fRunHead);
706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
707e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!y_in_rect(y, fBounds)) {
708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return NULL;
709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
710e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    y -= fBounds.y();  // our yoffs values are relative to the top
711e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
712e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoff = fRunHead->yoffsets();
713e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (yoff->fY < y) {
714e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        yoff += 1;
715e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
716e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
717e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
718e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastYForRow) {
719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        *lastYForRow = fBounds.y() + yoff->fY;
720e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
721e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return fRunHead->data() + yoff->fOffset;
722e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
723e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
724e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(x_in_rect(x, fBounds));
726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    x -= fBounds.x();
727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
728e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // first skip up to X
729e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
730e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int n = data[0];
731e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (x < n) {
732e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            *initialCount = n - x;
733e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
734e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
735e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
736e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= n;
737e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
738e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return data;
739e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
740e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
741e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
742e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isEmpty()) {
743e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
744e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
745e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!fBounds.contains(left, top, right, bottom)) {
746e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
748322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0
749e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isRect()) {
750e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
751e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
752322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif
753e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
754e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
755e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = this->findRow(top, &lastY);
756e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastY < bottom) {
757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
759e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now just need to check in X
760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int count;
761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    row = this->findX(row, left, &count);
762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0
763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return count >= (right - left) && 0xFF == row[1];
764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int rectWidth = right - left;
766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (0xFF == row[1]) {
767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (count >= rectWidth) {
768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return true;
769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        rectWidth -= count;
771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        count = row[0];
773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return false;
775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
776e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
777e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
778e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
779e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
780e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder {
781e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect fBounds;
782e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    struct Row {
783e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fY;
784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fWidth;
785e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>* fData;
786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    };
787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTDArray<Row>  fRows;
788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* fCurrRow;
789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fPrevY;
790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fWidth;
791209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    int fMinY;
792e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
793e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
794e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder(const SkIRect& bounds) : fBounds(bounds) {
795e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fPrevY = -1;
796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fWidth = bounds.width();
797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fCurrRow = NULL;
798209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = bounds.fTop;
799e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    ~Builder() {
802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fRows.begin();
803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* stop = fRows.end();
804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            delete row->fData;
806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
810322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& getBounds() const { return fBounds; }
811322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void addRun(int x, int y, U8CPU alpha, int count) {
813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(count > 0);
814e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x, y));
815e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x + count - 1, y));
816e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= fBounds.left();
818e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y -= fBounds.top();
819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fCurrRow;
821e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (y != fPrevY) {
822e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(y > fPrevY);
823e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fPrevY = y;
824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row = this->flushRow(true);
825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fY = y;
826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth = 0;
827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fData);
828e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(0 == row->fData->count());
829e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fCurrRow = row;
830e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
832e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= x);
833e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth < fBounds.width());
834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>& data = *row->fData;
836e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
837e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int gap = x - row->fWidth;
838e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (gap) {
839e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            AppendRun(data, 0, gap);
840e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth += gap;
841e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fWidth < fBounds.width());
842e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
843e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
844e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        AppendRun(data, alpha, count);
845e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row->fWidth += count;
846e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= fBounds.width());
847e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
848e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
8499154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    void addRectRun(int x, int y, int width, int height) {
8509154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
8519154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->addRun(x, y, 0xFF, width);
8529154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
8539154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        // we assum the rect must be all we'll see for these scanlines
8549154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        // so we ensure our row goes all the way to our right
8559154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->flushRowH(fCurrRow);
8569154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
8579154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        y -= fBounds.fTop;
8589154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        SkASSERT(y == fCurrRow->fY);
8599154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        fCurrRow->fY = y + height - 1;
8609154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    }
8619154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    bool finish(SkAAClip* target) {
863e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->flushRow(false);
864e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* row = fRows.begin();
866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* stop = fRows.end();
867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        size_t dataSize = 0;
869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            dataSize += row->fData->count();
871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
874045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0 == dataSize) {
875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return target->setEmpty();
876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
878209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        SkASSERT(fMinY >= fBounds.fTop);
879209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        SkASSERT(fMinY < fBounds.fBottom);
880209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        int adjustY = fMinY - fBounds.fTop;
881209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fBounds.fTop = fMinY;
882209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        YOffset* yoffset = head->yoffsets();
885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* data = head->data();
886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* baseData = data;
887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row = fRows.begin();
889c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE(int prevY = row->fY - 1;)
890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
891c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(prevY < row->fY);  // must be monotonic
892c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkDEBUGCODE(prevY = row->fY);
893c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
894209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            yoffset->fY = row->fY - adjustY;
895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset->fOffset = data - baseData;
896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset += 1;
897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            size_t n = row->fData->count();
899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            memcpy(data, row->fData->begin(), n);
900c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
901f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com            size_t bytesNeeded = compute_row_length(data, fBounds.width());
902c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(bytesNeeded == n);
903c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            data += n;
905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
909045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->freeRuns();
910045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->fBounds = fBounds;
911045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->fRunHead = head;
912045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return target->trimBounds();
913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void dump() {
916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->validate();
917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int y;
918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (y = 0; y < fRows.count(); ++y) {
919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[y];
920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const SkTDArray<uint8_t>& data = *row.fData;
922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = data.count();
923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = data.begin();
925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("\n");
930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void validate() {
934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG
935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int prevY = -1;
936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (int i = 0; i < fRows.count(); ++i) {
937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[i];
938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prevY < row.fY);
939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(fWidth == row.fWidth);
940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = row.fData->count();
941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = row.fData->begin();
942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int w = 0;
944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
945d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                int n = ptr[0];
946d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                SkASSERT(n > 0);
947d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                w += n;
948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkASSERT(w <= fWidth);
949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(w == fWidth);
952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            prevY = row.fY;
953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif
955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
957209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    // only called by BuilderBlitter
958209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void setMinY(int y) {
959209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = y;
960209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
961209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
9639154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    void flushRowH(Row* row) {
9649154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        // flush current row if needed
9659154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        if (row->fWidth < fWidth) {
9669154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            AppendRun(*row->fData, 0, fWidth - row->fWidth);
9679154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            row->fWidth = fWidth;
9689154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        }
9699154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    }
970209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* flushRow(bool readyForAnother) {
972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* next = NULL;
973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fRows.count();
974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 0) {
9759154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            this->flushRowH(&fRows[count - 1]);
976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 1) {
978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            // are our last two runs the same?
979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* prev = &fRows[count - 2];
980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* curr = &fRows[count - 1];
981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prev->fWidth == fWidth);
982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(curr->fWidth == fWidth);
983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (*prev->fData == *curr->fData) {
984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                prev->fY = curr->fY;
985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    curr->fData->rewind();
987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = curr;
988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                } else {
989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    delete curr->fData;
990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    fRows.removeShuffle(count - 1);
991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            } else {
993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = fRows.append();
995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next->fData = new SkTDArray<uint8_t>;
996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } else {
999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (readyForAnother) {
1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next = fRows.append();
1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next->fData = new SkTDArray<uint8_t>;
1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return next;
1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        do {
1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int n = count;
1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (n > 255) {
1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                n = 255;
1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            uint8_t* ptr = data.append(2);
1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[0] = n;
1015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[1] = alpha;
1016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            count -= n;
1017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } while (count > 0);
1018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
1020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter {
1022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
1023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter(Builder* builder) {
1024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder = builder;
10251778564c75de5799d45126984f8faafd03523100reed@google.com        fLeft = builder->getBounds().fLeft;
10261778564c75de5799d45126984f8faafd03523100reed@google.com        fRight = builder->getBounds().fRight;
1027209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = SK_MaxS32;
1028209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
1029209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1030209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void finish() {
1031209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        if (fMinY < SK_MaxS32) {
1032209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            fBuilder->setMinY(fMinY);
1033209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        }
1034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1035e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1036e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE
1037e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
1038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1039562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com    virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE {
10409154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->recordMinY(y);
10419154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        fBuilder->addRectRun(x, y, width, height);
1042562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com    }
1043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE
1045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
1046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE {
10483771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com        return NULL;
1049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitH(int x, int y, int width) SK_OVERRIDE {
1052209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        this->recordMinY(y);
1053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder->addRun(x, y, 0xFF, width);
1054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
1057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                           const int16_t runs[]) SK_OVERRIDE {
1058209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        this->recordMinY(y);
1059e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (;;) {
1060e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = *runs;
1061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (count <= 0) {
1062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                return;
1063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
10641778564c75de5799d45126984f8faafd03523100reed@google.com
10651778564c75de5799d45126984f8faafd03523100reed@google.com            // The supersampler's buffer can be the width of the device, so
10661778564c75de5799d45126984f8faafd03523100reed@google.com            // we may have to trim the run to our bounds. If so, we assert that
10671778564c75de5799d45126984f8faafd03523100reed@google.com            // the extra spans are always alpha==0
10681778564c75de5799d45126984f8faafd03523100reed@google.com            int localX = x;
10691778564c75de5799d45126984f8faafd03523100reed@google.com            int localCount = count;
10701778564c75de5799d45126984f8faafd03523100reed@google.com            if (x < fLeft) {
10711778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(0 == *alpha);
10721778564c75de5799d45126984f8faafd03523100reed@google.com                int gap = fLeft - x;
10731778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(gap <= count);
10741778564c75de5799d45126984f8faafd03523100reed@google.com                localX += gap;
10751778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= gap;
10761778564c75de5799d45126984f8faafd03523100reed@google.com            }
10771778564c75de5799d45126984f8faafd03523100reed@google.com            int right = x + count;
10781778564c75de5799d45126984f8faafd03523100reed@google.com            if (right > fRight) {
10791778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(0 == *alpha);
10801778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= right - fRight;
10811778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(localCount >= 0);
10821778564c75de5799d45126984f8faafd03523100reed@google.com            }
10831778564c75de5799d45126984f8faafd03523100reed@google.com
10841778564c75de5799d45126984f8faafd03523100reed@google.com            if (localCount) {
10851778564c75de5799d45126984f8faafd03523100reed@google.com                fBuilder->addRun(localX, y, *alpha, localCount);
10861778564c75de5799d45126984f8faafd03523100reed@google.com            }
1087820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com            // Next run
1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            runs += count;
1089e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            alpha += count;
1090e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            x += count;
1091e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1092e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1093e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder* fBuilder;
10961778564c75de5799d45126984f8faafd03523100reed@google.com    int      fLeft; // cache of builder's bounds' left edge
10971778564c75de5799d45126984f8faafd03523100reed@google.com    int      fRight;
1098209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    int      fMinY;
1099209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1100209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    /*
1101209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  We track this, in case the scan converter skipped some number of
1102209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  scanlines at the (relative to the bounds it was given). This allows
1103209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  the builder, during its finish, to trip its bounds down to the "real"
1104209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  top.
1105209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     */
1106209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void recordMinY(int y) {
1107209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        if (y < fMinY) {
1108209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            fMinY = y;
1109209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        }
1110209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void unexpected() {
1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkDebugf("---- did not expect to get called here");
1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        sk_throw();
1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1118f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
1119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
1120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1121322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip && clip->isEmpty()) {
1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect ibounds;
1126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    path.getBounds().roundOut(&ibounds);
1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkRegion tmpClip;
1129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (NULL == clip) {
1130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        tmpClip.setRect(ibounds);
1131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        clip = &tmpClip;
1132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (path.isInverseFillType()) {
1135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        ibounds = clip->getBounds();
1136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    } else {
1137322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return this->setEmpty();
1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder        builder(ibounds);
1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter blitter(&builder);
1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1145f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (doAA) {
1146f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        SkScan::AntiFillPath(path, *clip, &blitter, true);
1147f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    } else {
1148f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        SkScan::FillPath(path, *clip, &blitter);
1149f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
1150e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1151209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    blitter.finish();
1152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return builder.finish(this);
1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1157322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom,
1158322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowA, const SkIRect& rectA,
1159322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowB, const SkIRect& rectB);
1160322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void sectRowProc(SkAAClip::Builder& builder, int bottom,
1162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowA, const SkIRect& rectA,
1163322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowB, const SkIRect& rectB) {
1164322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1165322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1166322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1167322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
1168322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1170322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // Multiply
1171322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, alphaB);
1172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1175322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOver
1176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
1177322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1179322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1180322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOut
1181322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, 0xFF - alphaB);
1182322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1183322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1185322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // XOR
1186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
1187322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1189322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) {
1190322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
1191322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
1192322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
1193322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
1194322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return diffAlphaProc;
1195322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
1196322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return unionAlphaProc;
1197322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
1198322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return xorAlphaProc;
1199322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
1200322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            SkASSERT(!"unexpected region op");
1201322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
1202322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1203322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1204322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1205322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic const uint8_t gEmptyRow[] = {
1206322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1207322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1208322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1209322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1210322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1211322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1212322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1213322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0,
1214322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
1215322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1216322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter {
1217322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
1218322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    RowIter(const uint8_t* row, const SkIRect& bounds) {
1219322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fRow = row;
1220322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fLeft = bounds.fLeft;
1221322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fBoundsRight = bounds.fRight;
12221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (row) {
12231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = bounds.fLeft + row[0];
12241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(fRight <= fBoundsRight);
12251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = row[1];
12261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = false;
12271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
12281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
12291c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = kMaxInt32;
12301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = 0;
12311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
1232322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1233322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1234322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
12351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int left() const { return fLeft; }
12361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int right() const { return fRight; }
12371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    U8CPU alpha() const { return fAlpha; }
1238322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next() {
12391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!fDone) {
1240322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            fLeft = fRight;
12411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (fRight == fBoundsRight) {
12421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fDone = true;
12431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight = kMaxInt32;
12441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = 0;
12451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
12461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRow += 2;
12471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight += fRow[0];
12481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = fRow[1];
12491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                SkASSERT(fRight <= fBoundsRight);
12501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1251322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1252322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1253322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1254322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
1255322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t*  fRow;
1256322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fLeft;
1257322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fRight;
1258322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fBoundsRight;
1259322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool            fDone;
12601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    uint8_t         fAlpha;
1261322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
1262322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
12631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
12641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (rite == riteA) {
12651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
12661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        leftA = iter.left();
12671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        riteA = iter.right();
1268322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1269322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1270322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
12711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
12721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(min < max);
12731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(boundsMin < boundsMax);
12741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min >= boundsMax || max <= boundsMin) {
12751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        return false;
12761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
12771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min < boundsMin) {
12781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        min = boundsMin;
12791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
12801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (max > boundsMax) {
12811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        max = boundsMax;
12821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
12831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    return true;
12841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
12851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1286322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY,
1287322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      RowIter& iterA, RowIter& iterB,
1288322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      AlphaProc proc, const SkIRect& bounds) {
1289322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftA = iterA.left();
1290322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteA = iterA.right();
1291322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftB = iterB.left();
1292322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteB = iterB.right();
1293322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
12941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int prevRite = bounds.fLeft;
12951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
12961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
1297322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaA = 0;
1298322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaB = 0;
1299322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int left, rite;
13001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
13011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (leftA < leftB) {
1302322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftA;
1303322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
13041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteA <= leftB) {
13051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteA;
13061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
13071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftA = leftB;
13081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
13091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (leftB < leftA) {
1310322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftB;
1311322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
13121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteB <= leftA) {
13131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteB;
13141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
13151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftB = leftA;
13161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1317322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
13181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            left = leftA;   // or leftB, since leftA == leftB
13191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            rite = leftA = leftB = SkMin32(riteA, riteB);
1320322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
1321322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
1322322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1323322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1324322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fRight) {
1325322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1326322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
132734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (rite > bounds.fRight) {
132834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            rite = bounds.fRight;
132934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
133034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
1331322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fLeft) {
13321c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(rite > left);
1333322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
13341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            prevRite = rite;
1335322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
13361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
13371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterA, leftA, riteA, rite);
13381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterB, leftB, riteB, rite);
13391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
13401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
13411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (prevRite < bounds.fRight) {
13421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
1343322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1344322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1345322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
13461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
13471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (bot == botA) {
13481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
13491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        topA = botA;
13501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(botA == iter.top());
13511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        botA = iter.bottom();
1352322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1353322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1354322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1355322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
1356322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                     const SkAAClip& B, SkRegion::Op op) {
1357322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    AlphaProc proc = find_alpha_proc(op);
1358322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& bounds = builder.getBounds();
1359322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1360322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterA(A);
1361322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterB(B);
1362322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1363322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterA.done());
1364322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topA = iterA.top();
1365322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botA = iterA.bottom();
1366322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterB.done());
1367322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topB = iterB.top();
1368322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botB = iterB.bottom();
1369322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
13701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
13711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const uint8_t* rowA = NULL;
13721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const uint8_t* rowB = NULL;
1373322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int top, bot;
13741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
13751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (topA < topB) {
1376322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topA;
1377322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
13781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botA <= topB) {
13791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botA;
13801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
13811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topA = topB;
13821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
13831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
13841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (topB < topA) {
1385322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topB;
1386322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
13871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botB <= topA) {
13881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botB;
13891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
13901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topB = topA;
13911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1392322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
13931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            top = topA;   // or topB, since topA == topB
13941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            bot = topA = topB = SkMin32(botA, botB);
1395322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
1396322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
1397322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1398322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1399322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (top >= bounds.fBottom) {
1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1401322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
140234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
140334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (bot > bounds.fBottom) {
140434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            bot = bounds.fBottom;
140534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
140634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        SkASSERT(top < bot);
140734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
14081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!rowA && !rowB) {
14091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
14101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (top >= bounds.fTop) {
14111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(bot <= bounds.fBottom);
14121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
14131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
1415322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1416322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
14171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterA, topA, botA, bot);
14181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterB, topB, botB, bot);
14191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
1420322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1421322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1422322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
1423322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                  SkRegion::Op op) {
1424045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
1425045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1426322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReplace_Op == op) {
1427322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return this->set(clipBOrig);
1428322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1429322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1430322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipA = &clipAOrig;
1431322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipB = &clipBOrig;
1432322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1433322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReverseDifference_Op == op) {
1434322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        SkTSwap(clipA, clipB);
1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        op = SkRegion::kDifference_Op;
1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool a_empty = clipA->isEmpty();
1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool b_empty = clipB->isEmpty();
1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkIRect bounds;
1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                                                         clipB->fBounds)) {
1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipB);
1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty) {
1466322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
1467322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1468322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds.join(clipB->fBounds);
1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1472322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            SkASSERT(!"unknown region op");
1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return !this->isEmpty();
1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1477322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1480322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Builder builder(bounds);
1481322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    operateY(builder, *clipA, *clipB, op);
1482045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1483045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return builder.finish(this);
1484e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1485e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1486045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/*
1487045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  It can be expensive to build a local aaclip before applying the op, so
1488045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  we first see if we can restrict the bounds of new rect to our current
1489045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  bounds, or note that the new rect subsumes our current clip.
1490045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */
1491045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1492045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) {
1493045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkIRect        rStorage;
1494045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkIRect* r = &rOrig;
1495045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1496045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (op) {
1497045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kIntersect_Op:
1498045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (!rStorage.intersect(rOrig, fBounds)) {
1499045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // no overlap, so we're empty
1500045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setEmpty();
1501045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1502045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rStorage == fBounds) {
1503045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // we were wholly inside the rect, no change
1504045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return !this->isEmpty();
1505045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1506045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (this->quickContains(rStorage)) {
1507045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // the intersection is wholly inside us, we're a rect
1508045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rStorage);
1509045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1510045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            r = &rStorage;   // use the intersected bounds
1511045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1512045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kDifference_Op:
1513045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1514045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kUnion_Op:
1515045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rOrig.contains(fBounds)) {
1516045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rOrig);
1517045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1518045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1519045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
1520045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1521045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1522045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
152347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
1524045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    clip.setRect(*r);
152547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
152647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
152747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
1528045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) {
1529045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRect        rStorage, boundsStorage;
1530045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkRect* r = &rOrig;
1531045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1532045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    boundsStorage.set(fBounds);
1533045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (op) {
1534045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kIntersect_Op:
1535045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kDifference_Op:
1536045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (!rStorage.intersect(rOrig, boundsStorage)) {
1537045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setEmpty();
1538045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1539045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            r = &rStorage;   // use the intersected bounds
1540045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1541045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kUnion_Op:
1542045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rOrig.contains(boundsStorage)) {
1543045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rOrig);
1544045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1545045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1546045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
1547045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1548045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1549045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
155047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
1551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    clip.setRect(*r, doAA);
155247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
155347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
155447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
155547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
155647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
155747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
155847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
1559e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1560045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1561045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
1562045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (NULL == dst) {
1563045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return !this->isEmpty();
1564045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1565045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1566045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
1567045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return dst->setEmpty();
1568045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1569045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1570045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this != dst) {
1571045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        sk_atomic_inc(&fRunHead->fRefCnt);
1572045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst->fRunHead = fRunHead;
1573045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst->fBounds = fBounds;
1574045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1575045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    dst->fBounds.offset(dx, dy);
1576045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return true;
1577045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1578045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1579045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
1580045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                               const uint8_t* SK_RESTRICT row,
1581045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                               int width) {
1582045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (width > 0) {
1583045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = row[0];
1584045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(width >= n);
1585045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        memset(mask, row[1], n);
1586045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask += n;
1587045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
1588045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        width -= n;
1589045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1590045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const {
1593045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fFormat = SkMask::kA8_Format;
1594045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
1595045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask->fBounds.setEmpty();
1596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask->fImage = NULL;
1597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask->fRowBytes = 0;
1598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
1599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fBounds = fBounds;
1602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fRowBytes = fBounds.width();
1603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    size_t size = mask->computeImageSize();
1604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fImage = SkMask::AllocImage(size);
1605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    Iter iter(*this);
1607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    uint8_t* dst = mask->fImage;
1608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = fBounds.width();
1609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1610045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int y = fBounds.fTop;
1611045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (!iter.done()) {
1612045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        do {
1613045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            expand_row_to_mask(dst, iter.data(), width);
1614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            dst += mask->fRowBytes;
1615045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } while (++y < iter.bottom());
1616045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        iter.next();
1617045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1618045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1619045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1620045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
1621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
1624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                         int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
1625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // we don't read our initial n from data, since the caller may have had to
1626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // clip it, hence the initialCount parameter.
1627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int n = initialCount;
1628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
1629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (n > width) {
1630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            n = width;
1631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1632e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(n > 0);
1633e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs[0] = n;
1634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs += n;
1635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa[0] = data[1];
1637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa += n;
1638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
1640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        width -= n;
1641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == width) {
1642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
1643e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1644e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // load the next count
1645e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        n = data[0];
1646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    runs[0] = 0;    // sentinel
1648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() {
1651045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    sk_free(fScanlineScratch);
1652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1653e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1654e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() {
1655045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (NULL == fScanlineScratch) {
1656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // add 1 so we can store the terminating run count of 0
1657e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fAAClipBounds.width() + 1;
1658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // we use this either for fRuns + fAA, or a scaline of a mask
1659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // which may be as deep as 32bits
1660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
1661045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fRuns = (int16_t*)fScanlineScratch;
1662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fAA = (SkAlpha*)(fRuns + count);
1663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1666e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) {
1667e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(width > 0);
1668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x, y));
1669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1670e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1671e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
1672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = fAAClip->findRow(y, &lastY);
1673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
1674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
1675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1676e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (initialCount >= width) {
1677e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha alpha = row[1];
1678e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == alpha) {
1679e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0xFF == alpha) {
1682e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fBlitter->blitH(x, y, width);
1683e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1684e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1686e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1687e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
1688e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    expandToRuns(row, initialCount, width, fRuns, fAA);
1689e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
1691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1692e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1693e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN,
1694e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const SkAlpha* SK_RESTRICT srcAA,
1695e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const int16_t* SK_RESTRICT srcRuns,
1696e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  SkAlpha* SK_RESTRICT dstAA,
1697e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int16_t* SK_RESTRICT dstRuns,
1698e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int width) {
1699e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkDEBUGCODE(int accumulated = 0;)
1700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int srcN = srcRuns[0];
1701045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // do we need this check?
1702045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (0 == srcN) {
1703045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
1704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1705045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
1707e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(rowN > 0);
1708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(srcN > 0);
1709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1710e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1711e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int minN = SkMin32(srcN, rowN);
1712e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns[0] = minN;
1713e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns += minN;
1714e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA[0] = newAlpha;
1715e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA += minN;
1716e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1717e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (srcN -= minN)) {
1718e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // refresh
1719e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcRuns += srcN;
1720e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcAA += srcN;
1721e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // reload
1722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (0 == srcN) {
1723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                break;
1724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (rowN -= minN)) {
1727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 2;
1728e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            rowN = row[0];  // reload
1729e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1730e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1731e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkDEBUGCODE(accumulated += minN;)
1732e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(accumulated <= width);
1733e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
173434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    dstRuns[0] = 0;
1735e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1736e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1737e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
1738e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                                const int16_t runs[]) {
1739e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int lastY;
1740e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = fAAClip->findRow(y, &lastY);
1741e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
1742e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
1743e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1744e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
1745e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1746e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
1747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
1748e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1749e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1750e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1751e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + 1, y + height)) {
1752e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitV(x, y, height, alpha);
1753e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
1754e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1755e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (;;) {
1757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int lastY;
1758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const uint8_t* row = fAAClip->findRow(y, &lastY);
1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int dy = lastY - y + 1;
1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (dy > height) {
1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            dy = height;
1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        height -= dy;
1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1765e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int initialCount;
1766e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row = fAAClip->findX(row, x, &initialCount);
1767e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
1768e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (newAlpha) {
1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fBlitter->blitV(x, y, dy, newAlpha);
1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(height >= 0);
1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (height <= 0) {
1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1774e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1775e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y = lastY + 1;
1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1777e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1778e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1779e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
1780e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + width, y + height)) {
1781e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitRect(x, y, width, height);
1782e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
1783e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1785e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (--height >= 0) {
1786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->blitH(x, y, width);
1787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y += 1;
1788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                            int initialRowCount, void* dst);
1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1794045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) {
1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    memcpy(dst, src, n);
1796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1798045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) {
1799045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    sk_bzero(dst, n);
1800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1802045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
1803045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return SkMulDiv255Round(value, alpha);
1804045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
1806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned r = SkGetPackedR16(value);
1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned g = SkGetPackedG16(value);
1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned b = SkGetPackedB16(value);
1809045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return SkPackRGB16(SkMulDiv255Round(r, alpha),
1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                       SkMulDiv255Round(r, alpha),
1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                       SkMulDiv255Round(r, alpha));
1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1813045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) {
1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned a = SkGetPackedA32(value);
1815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned r = SkGetPackedR32(value);
1816045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned g = SkGetPackedG32(value);
1817045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned b = SkGetPackedB32(value);
1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return SkPackARGB32(SkMulDiv255Round(a, alpha),
1819045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                        SkMulDiv255Round(r, alpha),
1820045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                        SkMulDiv255Round(g, alpha),
1821045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                        SkMulDiv255Round(b, alpha));
1822045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1823322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1824045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtemplate <typename T> void mergeT(const T* SK_RESTRICT src, int srcN,
1825045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                 const uint8_t* SK_RESTRICT row, int rowN,
1826045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                 T* SK_RESTRICT dst) {
1827045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkDEBUGCODE(int accumulated = 0;)
1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (;;) {
1829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(rowN > 0);
1830045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(srcN > 0);
1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1832045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = SkMin32(rowN, srcN);
1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        unsigned rowA = row[1];
1834045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0xFF == rowA) {
1835045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            small_memcpy(dst, src, n * sizeof(T));
1836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } else if (0 == rowA) {
1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            small_bzero(dst, n * sizeof(T));
1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } else {
1839045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            for (int i = 0; i < n; ++i) {
1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                dst[i] = mergeOne(src[i], rowA);
1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0 == (srcN -= n)) {
1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        src += n;
1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst += n;
1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(rowN == n);
1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        rowN = row[0];
18541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
1855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
18561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) {
1858045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (format) {
1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kBW_Format:
1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkASSERT(!"unsupported");
1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return NULL;
1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kA8_Format:
1863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::k3D_Format: {
1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT;
1865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return (MergeAAProc)proc8;
1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kLCD16_Format: {
1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT;
1869045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return (MergeAAProc)proc16;
1870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kLCD32_Format: {
1872045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT;
1873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return (MergeAAProc)proc32;
1874045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
1876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkASSERT(!"unsupported");
1877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return NULL;
18781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
18801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) {
1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(bitInAByte <= 0xFF);
1883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // negation turns any non-zero into 0xFFFFFF??, so we just shift down
1884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // some value >= 8 to get a full FF value
1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return -bitInAByte >> 8;
18861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
18871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1888045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
1889045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
1890045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
1891045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1892045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = srcMask.fBounds.width();
1893045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int height = srcMask.fBounds.height();
1894045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1895045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
1896045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t srcRB = srcMask.fRowBytes;
1897045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage;
1898045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t dstRB = dstMask->fRowBytes;
1899045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1900045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int wholeBytes = width >> 3;
1901045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int leftOverBits = width & 7;
1902045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1903045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (int y = 0; y < height; ++y) {
1904045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        uint8_t* SK_RESTRICT d = dst;
1905045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        for (int i = 0; i < wholeBytes; ++i) {
1906045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int srcByte = src[i];
1907045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[0] = bit2byte(srcByte & (1 << 7));
1908045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[1] = bit2byte(srcByte & (1 << 6));
1909045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[2] = bit2byte(srcByte & (1 << 5));
1910045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[3] = bit2byte(srcByte & (1 << 4));
1911045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[4] = bit2byte(srcByte & (1 << 3));
1912045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[5] = bit2byte(srcByte & (1 << 2));
1913045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[6] = bit2byte(srcByte & (1 << 1));
1914045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[7] = bit2byte(srcByte & (1 << 0));
1915045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d += 8;
1916045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1917045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (leftOverBits) {
1918045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int srcByte = src[wholeBytes];
1919045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            for (int x = 0; x < leftOverBits; ++x) {
1920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                *d++ = bit2byte(srcByte & 0x80);
1921045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                srcByte <<= 1;
1922045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        src += srcRB;
1925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst += dstRB;
1926322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1927322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1928322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
1930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(fAAClip->getBounds().contains(clip));
1931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (fAAClip->quickContains(clip)) {
1933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fBlitter->blitMask(origMask, clip);
1934322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
1935322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1936322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkMask* mask = &origMask;
1938322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // if we're BW, we need to upscale to A8 (ugh)
1940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkMask  grayMask;
1941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    grayMask.fImage = NULL;
1942045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (SkMask::kBW_Format == origMask.fFormat) {
1943045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fFormat = SkMask::kA8_Format;
1944045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fBounds = origMask.fBounds;
1945045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fRowBytes = origMask.fBounds.width();
1946045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t size = grayMask.computeImageSize();
1947045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size,
1948045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                               SkAutoMalloc::kReuse_OnShrink);
1949322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1950045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        upscaleBW2A8(&grayMask, origMask);
1951045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask = &grayMask;
1952322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1953045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1954045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    this->ensureRunsAndAA();
1955045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1956045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
1957045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // data into a temp block to support it better (ugh)
1958045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1959045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const void* src = mask->getAddr(clip.fLeft, clip.fTop);
1960045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t srcRB = mask->fRowBytes;
1961045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = clip.width();
1962045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
1963045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1964045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkMask rowMask;
1965045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
1966045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fBounds.fLeft = clip.fLeft;
1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fBounds.fRight = clip.fRight;
1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1
1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fImage = (uint8_t*)fScanlineScratch;
1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int y = clip.fTop;
1972045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int stopY = y + clip.height();
1973045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1974045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    do {
1975045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int localStopY;
1976045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const uint8_t* row = fAAClip->findRow(y, &localStopY);
1977045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // findRow returns last Y, not stop, so we add 1
1978045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        localStopY = SkMin32(localStopY + 1, stopY);
1979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1980045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int initialCount;
1981045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row = fAAClip->findX(row, clip.fLeft, &initialCount);
1982045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        do {
1983045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            mergeProc(src, width, row, initialCount, rowMask.fImage);
1984045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            rowMask.fBounds.fTop = y;
1985045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            rowMask.fBounds.fBottom = y + 1;
1986045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fBlitter->blitMask(rowMask, rowMask.fBounds);
1987045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            src = (const void*)((const char*)src + srcRB);
1988045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } while (++y < localStopY);
1989045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    } while (y < stopY);
1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comconst SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
1993045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return NULL;
1994322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1995322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1996