1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc.
3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *
4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be
5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file.
6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h"
9b906daf112416c1698a79cf51aa70fe11aa19d0aherb#include "SkAtomics.h"
10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h"
11a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h"
129fc53624a09f6d3378b0a540832571dc1c31fbcdMike Reed#include "SkRectPriv.h"
13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h"
14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.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
394b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG
40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
434b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif
44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *  Data runs are packed [count, alpha]
51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset {
54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t  fY;
55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint32_t fOffset;
56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead {
59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRefCnt;
60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int32_t fRowCount;
61493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com    size_t  fDataSize;
62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    YOffset* yoffsets() {
64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (YOffset*)((char*)this + sizeof(RunHead));
65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoffsets() const {
67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const YOffset*)((const char*)this + sizeof(RunHead));
68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    uint8_t* data() {
70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (uint8_t*)(this->yoffsets() + fRowCount);
71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* data() const {
73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return (const uint8_t*)(this->yoffsets() + fRowCount);
74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static RunHead* Alloc(int rowCount, size_t dataSize) {
77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize;
78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = (RunHead*)sk_malloc_throw(size);
79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRefCnt = 1;
80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fRowCount = rowCount;
81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        head->fDataSize = dataSize;
82e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return head;
83e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    static int ComputeRowSizeForWidth(int width) {
86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // 2 bytes per segment, where each segment can store up to 255 for count
87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int segments = 0;
88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        while (width > 0) {
89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            segments += 1;
90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int n = SkMin32(width, 255);
91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            width -= n;
92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return segments * 2;    // each segment is row[0] + row[1] (n + alpha)
94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    static RunHead* AllocRect(const SkIRect& bounds) {
97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(!bounds.isEmpty());
98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int width = bounds.width();
99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t rowSize = ComputeRowSizeForWidth(width);
100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        RunHead* head = RunHead::Alloc(1, rowSize);
101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        YOffset* yoff = head->yoffsets();
102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        yoff->fY = bounds.height() - 1;
103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        yoff->fOffset = 0;
104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        uint8_t* row = head->data();
105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        while (width > 0) {
106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int n = SkMin32(width, 255);
107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row[0] = n;
108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row[1] = 0xFF;
109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            width -= n;
110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            row += 2;
111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return head;
113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter {
117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Iter(const SkAAClip&);
119322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
120322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int top() const { return fTop; }
1221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int bottom() const { return fBottom; }
1231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    const uint8_t* data() const { return fData; }
124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next();
125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fCurrYOff;
128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const YOffset* fStopYOff;
129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t* fData;
130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int fTop, fBottom;
132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool fDone;
133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) {
136322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip.isEmpty()) {
137322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fDone = true;
1381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        fTop = fBottom = clip.fBounds.fBottom;
13996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fData = nullptr;
14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fCurrYOff = nullptr;
14196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fStopYOff = nullptr;
142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const RunHead* head = clip.fRunHead;
146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fCurrYOff = head->yoffsets();
147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fStopYOff = fCurrYOff + head->fRowCount;
148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fData     = head->data() + fCurrYOff->fOffset;
149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // setup first value
151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fTop = clip.fBounds.fTop;
152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1;
153322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    fDone = false;
154322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
155322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
156322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() {
1571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (!fDone) {
1581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* prev = fCurrYOff;
1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        const YOffset* curr = prev + 1;
1601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(curr <= fStopYOff);
161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fTop = fBottom;
1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (curr >= fStopYOff) {
1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
1651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom = kMaxInt32;
16696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fData = nullptr;
1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
1681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fBottom += curr->fY - prev->fY;
1691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fData += curr->fOffset - prev->fOffset;
1701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fCurrYOff = curr;
1711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG
176c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used
177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) {
178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const uint8_t* origRow = row;
179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (width > 0) {
180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = row[0];
181c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(n <= width);
183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        width -= n;
185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(0 == width);
187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return row - origRow;
188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const {
19196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fRunHead) {
192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(fBounds.isEmpty());
193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
195d7ec12e41cce090ec0b2e68e995ea511d33c9967reed    SkASSERT(!fBounds.isEmpty());
196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const RunHead* head = fRunHead;
198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRefCnt > 0);
199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRowCount > 0);
200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
201045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* yoff = head->yoffsets();
202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* ystop = yoff + head->fRowCount;
203c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int lastY = fBounds.height() - 1;
204c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
205c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // Y and offset must be monotonic
206c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int prevY = -1;
207c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int32_t prevOffset = -1;
208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (yoff < ystop) {
209c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(prevY < yoff->fY);
210c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(yoff->fY <= lastY);
211c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        prevY = yoff->fY;
212c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(prevOffset < (int32_t)yoff->fOffset);
213c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        prevOffset = yoff->fOffset;
214c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* row = head->data() + yoff->fOffset;
215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t rowLength = compute_row_length(row, fBounds.width());
216493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com        SkASSERT(yoff->fOffset + rowLength <= head->fDataSize);
217c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // check the last entry;
220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    --yoff;
221c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(yoff->fY == lastY);
222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
2236d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper
2246d42d9c7ff1c3d7ab4de032d5451aed02f746c43humperstatic void dump_one_row(const uint8_t* SK_RESTRICT row,
2256d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper                         int width, int leading_num) {
2266d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    if (leading_num) {
2276d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        SkDebugf( "%03d ", leading_num );
2286d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    }
2296d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    while (width > 0) {
2306d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        int n = row[0];
2316d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        int val = row[1];
2326d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        char out = '.';
2336d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        if (val == 0xff) {
2346d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            out = '*';
2356d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        } else if (val > 0) {
2366d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            out = '+';
2376d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        }
2386d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        for (int i = 0 ; i < n ; i++) {
2396d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            SkDebugf( "%c", out );
2406d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        }
2416d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        row += 2;
2426d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        width -= n;
2436d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    }
2446d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    SkDebugf( "\n" );
2456d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper}
2466d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper
2476d42d9c7ff1c3d7ab4de032d5451aed02f746c43humpervoid SkAAClip::debug(bool compress_y) const {
2486d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    Iter iter(*this);
2496d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    const int width = fBounds.width();
2506d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper
2516d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    int y = fBounds.fTop;
2526d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    while (!iter.done()) {
2536d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        if (compress_y) {
2546d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            dump_one_row(iter.data(), width, iter.bottom() - iter.top() + 1);
2556d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        } else {
2566d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            do {
2576d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper                dump_one_row(iter.data(), width, 0);
2586d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper            } while (++y < iter.bottom());
2596d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        }
2606d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper        iter.next();
2616d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    }
2626d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper}
263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
265045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
266045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
267768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// Count the number of zeros on the left and right edges of the passed in
268768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// RLE row. If 'row' is all zeros return 'width' in both variables.
269c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width,
270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                                   int* leftZ, int* riteZ) {
271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int zeros = 0;
272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (row[1]) {
274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
278c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        zeros += n;
280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (width > 0);
283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    *leftZ = zeros;
284c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
285768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    if (0 == width) {
286768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com        // this line is completely empty return 'width' in both variables
287768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com        *riteZ = *leftZ;
288768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com        return;
289768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    }
290768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com
291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    zeros = 0;
292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (width > 0) {
293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (0 == row[1]) {
296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            zeros += n;
297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        } else {
298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            zeros = 0;
299c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    *riteZ = zeros;
304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
306c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
307c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() {
308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    static bool gOnce;
309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (gOnce) {
310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return;
311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    gOnce = true;
313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data0[] = {  0, 0,     10, 0xFF };
315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data1[] = {  0, 0,     5, 0xFF, 2, 0, 3, 0xFF };
316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data2[] = {  7, 0,     5, 0, 2, 0, 3, 0xFF };
317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data3[] = {  0, 5,     5, 0xFF, 2, 0, 3, 0 };
318c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data4[] = {  2, 3,     2, 0, 5, 0xFF, 3, 0 };
319768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    const uint8_t data5[] = { 10, 10,    10, 0 };
320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t data6[] = {  2, 2,     2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t* array[] = {
323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data0, data1, data2, data3, data4, data5, data6
324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    };
325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* data = array[i];
328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedL = *data++;
329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedR = *data++;
330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int L = 12345, R = 12345;
331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        count_left_right_zeros(data, 10, &L, &R);
332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedL == L);
333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedR == R);
334c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides.
339c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left
340c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) {
341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int trim = 0;
342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (leftZ > 0) {
343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(0 == row[1]);
344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
345c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (n > leftZ) {
350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row[-2] = n - leftZ;
351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        trim += 2;
354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        leftZ -= n;
355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(leftZ >= 0);
356c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (riteZ) {
359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // walk row to the end, and then we'll back up to trim riteZ
360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        while (width > 0) {
361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            int n = row[0];
362c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(n <= width);
363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            width -= n;
364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row += 2;
365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // now skip whole runs of zeros
367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        do {
368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            row -= 2;
369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(0 == row[1]);
370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            int n = row[0];
371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(n > 0);
372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            if (n > riteZ) {
373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                row[0] = n - riteZ;
374c90419199525141a5b98091f856e359bf9daf5b1reed@google.com                break;
375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            }
376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            riteZ -= n;
377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(riteZ >= 0);
378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        } while (riteZ > 0);
379c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
380fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return trim;
382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
385c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width
386c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) {
387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (width > 0) {
388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n > 0);
390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(0 == width);
395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
396c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
397c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() {
398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    static bool gOnce;
399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (gOnce) {
400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return;
401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
402c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    gOnce = true;
403fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data0[] = {  0, 0, 0,   10,    10, 0xFF };
405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data1[] = {  2, 0, 0,   10,    5, 0, 2, 0, 3, 0xFF };
406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data2[] = {  5, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data3[] = {  6, 0, 2,   10,    5, 0, 2, 0, 3, 0xFF };
408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data4[] = {  0, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data5[] = {  1, 0, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data6[] = {  0, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
411c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data7[] = {  1, 1, 0,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
412c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data8[] = {  2, 2, 2,   10,    2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 };
413c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data9[] = {  5, 2, 4,   10,    2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 };
414c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t data10[] ={  74, 0, 4, 150,    9, 0, 65, 0, 76, 0xFF };
415fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t* array[] = {
417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data0, data1, data2, data3, data4,
418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data5, data6, data7, data8, data9,
419c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        data10
420c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    };
421fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) {
423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        uint8_t* data = array[i];
424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int trimL = *data++;
425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int trimR = *data++;
426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int expectedSkip = *data++;
427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const int origWidth = *data++;
428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        assert_row_width(data, origWidth);
429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int skip = trim_row_left_right(data, origWidth, trimL, trimR);
430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(expectedSkip == skip);
431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int expectedWidth = origWidth - trimL - trimR;
432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        assert_row_width(data + skip, expectedWidth);
433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
434c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
435c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
436c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
437c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() {
438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkDEBUGCODE(test_trim_row_left_right();)
439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (this->isEmpty()) {
441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return false;
442c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
443fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    AUTO_AACLIP_VALIDATE(*this);
445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int width = fBounds.width();
447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    RunHead* head = fRunHead;
448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* yoff = head->yoffsets();
449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* stop = yoff + head->fRowCount;
450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    uint8_t* base = head->data();
451c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
452768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum
453768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    // number of zeros on the left and right of the clip. This information
454768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    // can be used to shrink the bounding box.
455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int leftZeros = width;
456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int riteZeros = width;
457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
458c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int L, R;
459c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        count_left_right_zeros(base + yoff->fOffset, width, &L, &R);
460768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com        SkASSERT(L + R < width || (L == width && R == width));
461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (L < leftZeros) {
462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            leftZeros = L;
463c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
464c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (R < riteZeros) {
465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            riteZeros = R;
466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (0 == (leftZeros | riteZeros)) {
468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            // no trimming to do
469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            return true;
470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
474c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(leftZeros || riteZeros);
475768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com    if (width == leftZeros) {
476768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com        SkASSERT(width == riteZeros);
477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return this->setEmpty();
478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
479c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
480c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    this->validate();
481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    fBounds.fLeft += leftZeros;
483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    fBounds.fRight -= riteZeros;
484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(!fBounds.isEmpty());
485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // For now we don't realloc the storage (for time), we just shrink in place
487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // This means we don't have to do any memmoves either, since we can just
488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    // play tricks with the yoff->fOffset for each row
489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    yoff = head->yoffsets();
490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        uint8_t* row = base + yoff->fOffset;
492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE((void)compute_row_length(row, width);)
493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros);
494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);)
495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
499c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
500c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) {
501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(width > 0);
502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
503c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (row[1]) {
504c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            return false;
505c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
506c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int n = row[0];
507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(n <= width);
508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        width -= n;
509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        row += 2;
510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (width > 0);
511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(0 == width);
512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
514c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
515c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() {
516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (this->isEmpty()) {
517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return false;
518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
519c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
520d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com    this->validate();
521d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com
522c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const int width = fBounds.width();
523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    RunHead* head = fRunHead;
524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* yoff = head->yoffsets();
525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    YOffset* stop = yoff + head->fRowCount;
526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    const uint8_t* base = head->data();
527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  Look to trim away empty rows from the top.
529c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //
530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    int skip = 0;
531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    while (yoff < stop) {
532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        const uint8_t* data = base + yoff->fOffset;
533c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        if (!row_is_all_zeros(data, width)) {
534c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            break;
535c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
536c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        skip += 1;
537c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff += 1;
538c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
539c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(skip <= head->fRowCount);
540c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip == head->fRowCount) {
541c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        return this->setEmpty();
542c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
543c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip > 0) {
544c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // adjust fRowCount and fBounds.fTop, and slide all the data up
545c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // as we remove [skip] number of YOffset entries
546c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff = head->yoffsets();
547c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        int dy = yoff[skip - 1].fY + 1;
548c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        for (int i = skip; i < head->fRowCount; ++i) {
549c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(yoff[i].fY >= dy);
550c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            yoff[i].fY -= dy;
551c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        }
552c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        YOffset* dst = head->yoffsets();
553c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize;
554c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        memmove(dst, dst + skip, size - skip * sizeof(YOffset));
555c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
556c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        fBounds.fTop += dy;
557c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(!fBounds.isEmpty());
558c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        head->fRowCount -= skip;
559c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(head->fRowCount > 0);
560fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
561d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        this->validate();
562d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        // need to reset this after the memmove
563d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com        base = head->data();
564c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
565c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
566c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  Look to trim away empty rows from the bottom.
567c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  We know that we have at least one non-zero row, so we can just walk
568c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //  backwards without checking for running past the start.
569c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    //
570c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    stop = yoff = head->yoffsets() + head->fRowCount;
571c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    do {
572c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        yoff -= 1;
573c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    } while (row_is_all_zeros(base + yoff->fOffset, width));
574a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org    skip = SkToInt(stop - yoff - 1);
575c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(skip >= 0 && skip < head->fRowCount);
576c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    if (skip > 0) {
577c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // removing from the bottom is easier than from the top, as we don't
578c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        // have to adjust any of the Y values, we just have to trim the array
579c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        memmove(stop - skip, stop, head->fDataSize);
580c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
581c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        fBounds.fBottom = fBounds.fTop + yoff->fY + 1;
582c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(!fBounds.isEmpty());
583c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        head->fRowCount -= skip;
584c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkASSERT(head->fRowCount > 0);
585c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    }
586d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com    this->validate();
587c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
588c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return true;
589c90419199525141a5b98091f856e359bf9daf5b1reed@google.com}
590c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of
592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its
593045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so
594045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up.
595045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com//
596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data
597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com//
598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() {
599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return false;
601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const RunHead* head = fRunHead;
604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset* yoff = head->yoffsets();
605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(head->fRowCount > 0);
607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const YOffset& lastY = yoff[head->fRowCount - 1];
608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(lastY.fY + 1 <= fBounds.height());
609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBounds.fBottom = fBounds.fTop + lastY.fY + 1;
610045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(lastY.fY + 1 == fBounds.height());
611c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    SkASSERT(!fBounds.isEmpty());
612c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
613c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    return this->trimTopBottom() && this->trimLeftRight();
614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
615045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
617e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
618e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() {
61947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (fRunHead) {
620e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fRunHead->fRefCnt >= 1);
621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) {
622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_free(fRunHead);
623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() {
628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
62996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fRunHead = nullptr;
630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
632e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) {
633045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkDEBUGCODE(fBounds.setEmpty();)    // need this for validate
63496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fRunHead = nullptr;
635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    *this = src;
636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() {
639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) {
643045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
644045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    src.validate();
645045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this != &src) {
647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->freeRuns();
648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBounds = src.fBounds;
649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fRunHead = src.fRunHead;
65047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com        if (fRunHead) {
651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            sk_atomic_inc(&fRunHead->fRefCnt);
652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
653e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
654e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return *this;
655e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
657e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) {
658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    a.validate();
659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    b.validate();
660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
661e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (&a == &b) {
662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (a.fBounds != b.fBounds) {
665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
666e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
667fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* ah = a.fRunHead;
669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip::RunHead* bh = b.fRunHead;
670fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
671e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // this catches empties and rects being equal
672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (ah == bh) {
673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
676e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now we insist that both are complex (but different ptrs)
67747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    if (!a.fRunHead || !b.fRunHead) {
678e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
679e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return  ah->fRowCount == bh->fRowCount &&
682e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ah->fDataSize == bh->fDataSize &&
683e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            !memcmp(ah->data(), bh->data(), ah->fDataSize);
684e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
686e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) {
687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
688045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    other.validate();
689045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fBounds, other.fBounds);
691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTSwap(fRunHead, other.fRunHead);
692e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
693e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) {
695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    *this = src;
696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return !this->isEmpty();
697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
699e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() {
700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->freeRuns();
701e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBounds.setEmpty();
70296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fRunHead = nullptr;
703e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return false;
704e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
705e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) {
707a766ca9af12e1175cfb01f4b516802da9197ba78Mike Reed    if (bounds.isEmpty()) {
708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
71047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
711045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
71247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
713045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0
71447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkRect r;
71547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    r.set(bounds);
71647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkPath path;
71747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    path.addRect(r);
71847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->setPath(path);
719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
720045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    this->freeRuns();
721045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBounds = bounds;
722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fRunHead = RunHead::AllocRect(bounds);
723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(!this->isEmpty());
724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return true;
725045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
728202ab2a5cabaf25a1e6ec47c0003da3213a79864reedbool SkAAClip::isRect() const {
729202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    if (this->isEmpty()) {
730202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        return false;
731202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    }
732202ab2a5cabaf25a1e6ec47c0003da3213a79864reed
733202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    const RunHead* head = fRunHead;
734202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    if (head->fRowCount != 1) {
735202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        return false;
736202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    }
737202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    const YOffset* yoff = head->yoffsets();
738202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    if (yoff->fY != fBounds.fBottom - 1) {
739202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        return false;
740202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    }
741202ab2a5cabaf25a1e6ec47c0003da3213a79864reed
742202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    const uint8_t* row = head->data() + yoff->fOffset;
743202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    int width = fBounds.width();
744202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    do {
745202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        if (row[1] != 0xFF) {
746202ab2a5cabaf25a1e6ec47c0003da3213a79864reed            return false;
747202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        }
748202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        int n = row[0];
749202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        SkASSERT(n <= width);
750202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        width -= n;
751202ab2a5cabaf25a1e6ec47c0003da3213a79864reed        row += 2;
752202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    } while (width > 0);
753202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    return true;
754202ab2a5cabaf25a1e6ec47c0003da3213a79864reed}
755202ab2a5cabaf25a1e6ec47c0003da3213a79864reed
756f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) {
757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (r.isEmpty()) {
758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
759e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
760e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // TODO: special case this
764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
765e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkPath path;
766e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    path.addRect(r);
76796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return this->setPath(path, nullptr, doAA);
768f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com}
769f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com
770a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.comstatic void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) {
771a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    SkASSERT(count >= 0);
772a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    while (count > 0) {
773a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        int n = count;
774a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        if (n > 255) {
775a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            n = 255;
776a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        }
777a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        uint8_t* data = array.append(2);
778a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        data[0] = n;
779a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        data[1] = value;
780a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        count -= n;
781a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    }
782a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com}
783a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
784f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) {
785f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isEmpty()) {
786f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setEmpty();
787f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
788f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (rgn.isRect()) {
789f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        return this->setRect(rgn.getBounds());
790f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
791a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
792a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#if 0
793f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkAAClip clip;
794f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    SkRegion::Iterator iter(rgn);
795f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    for (; !iter.done(); iter.next()) {
796f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com        clip.op(iter.rect(), SkRegion::kUnion_Op);
797f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
798f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    this->swap(clip);
7993771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com    return !this->isEmpty();
800fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#else
801a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    const SkIRect& bounds = rgn.getBounds();
802a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    const int offsetX = bounds.fLeft;
803a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    const int offsetY = bounds.fTop;
804a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
805a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    SkTDArray<YOffset> yArray;
806a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    SkTDArray<uint8_t> xArray;
807a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
808a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    yArray.setReserve(SkMin32(bounds.height(), 1024));
809e06739531b5067564c2ce90c35522c6590162e29Mike Reed    xArray.setReserve(SkMin32(bounds.width(), 512) * 128);
810a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
811a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    SkRegion::Iterator iter(rgn);
812a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    int prevRight = 0;
813a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    int prevBot = 0;
81496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    YOffset* currY = nullptr;
815a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
816a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    for (; !iter.done(); iter.next()) {
817a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        const SkIRect& r = iter.rect();
818a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        SkASSERT(bounds.contains(r));
819a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
820a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        int bot = r.fBottom - offsetY;
821a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        SkASSERT(bot >= prevBot);
822a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        if (bot > prevBot) {
823a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            if (currY) {
824a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                // flush current row
825a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                append_run(xArray, 0, bounds.width() - prevRight);
826a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            }
827a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            // did we introduce an empty-gap from the prev row?
828a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            int top = r.fTop - offsetY;
829a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            if (top > prevBot) {
830a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                currY = yArray.append();
831a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                currY->fY = top - 1;
832a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                currY->fOffset = xArray.count();
833a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com                append_run(xArray, 0, bounds.width());
834a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            }
835a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            // create a new record for this Y value
836a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            currY = yArray.append();
837a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            currY->fY = bot - 1;
838a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            currY->fOffset = xArray.count();
839a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            prevRight = 0;
840a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com            prevBot = bot;
841a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        }
842a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
843a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        int x = r.fLeft - offsetX;
844a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        append_run(xArray, 0, x - prevRight);
845a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
846a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        int w = r.fRight - r.fLeft;
847a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        append_run(xArray, 0xFF, w);
848a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        prevRight = x + w;
849a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com        SkASSERT(prevRight <= bounds.width());
850a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    }
851a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    // flush last row
852a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    append_run(xArray, 0, bounds.width() - prevRight);
853a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
854a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    // now pack everything into a RunHead
855a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes());
856a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    memcpy(head->yoffsets(), yArray.begin(), yArray.bytes());
857a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    memcpy(head->data(), xArray.begin(), xArray.bytes());
858a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com
859a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    this->setEmpty();
860a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    fBounds = bounds;
861a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    fRunHead = head;
862a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    this->validate();
863a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    return true;
864a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#endif
865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const {
87047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkASSERT(fRunHead);
871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!y_in_rect(y, fBounds)) {
87396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    y -= fBounds.y();  // our yoffs values are relative to the top
876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const YOffset* yoff = fRunHead->yoffsets();
878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (yoff->fY < y) {
879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        yoff += 1;
880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount);
881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastYForRow) {
884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        *lastYForRow = fBounds.y() + yoff->fY;
885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return fRunHead->data() + yoff->fOffset;
887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const {
890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(x_in_rect(x, fBounds));
891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    x -= fBounds.x();
892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // first skip up to X
894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int n = data[0];
896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (x < n) {
897a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com            if (initialCount) {
898a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com                *initialCount = n - x;
899a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com            }
900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= n;
904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    return data;
906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const {
909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isEmpty()) {
910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (!fBounds.contains(left, top, right, bottom)) {
913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
915322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0
916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (this->isRect()) {
917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return true;
918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
919322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif
920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
921a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com    int lastY SK_INIT_TO_AVOID_WARNING;
922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const uint8_t* row = this->findRow(top, &lastY);
923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (lastY < bottom) {
924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return false;
925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // now just need to check in X
927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int count;
928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    row = this->findX(row, left, &count);
929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0
930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return count >= (right - left) && 0xFF == row[1];
931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int rectWidth = right - left;
933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (0xFF == row[1]) {
934045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (count >= rectWidth) {
935045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return true;
936045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        rectWidth -= count;
938045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        count = row[0];
940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return false;
942045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder {
948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect fBounds;
949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    struct Row {
950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fY;
951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int fWidth;
952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>* fData;
953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    };
954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkTDArray<Row>  fRows;
955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* fCurrRow;
956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fPrevY;
957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int fWidth;
958209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    int fMinY;
959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder(const SkIRect& bounds) : fBounds(bounds) {
962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fPrevY = -1;
963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fWidth = bounds.width();
96496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fCurrRow = nullptr;
965209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = bounds.fTop;
966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
967e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
968e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    ~Builder() {
969e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fRows.begin();
970e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* stop = fRows.end();
971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            delete row->fData;
973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
977322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& getBounds() const { return fBounds; }
978322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void addRun(int x, int y, U8CPU alpha, int count) {
980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(count > 0);
981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x, y));
982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(fBounds.contains(x + count - 1, y));
983fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        x -= fBounds.left();
985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y -= fBounds.top();
986fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        Row* row = fCurrRow;
988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (y != fPrevY) {
989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(y > fPrevY);
990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fPrevY = y;
991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row = this->flushRow(true);
992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fY = y;
993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth = 0;
994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fData);
995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(0 == row->fData->count());
996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fCurrRow = row;
997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= x);
1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth < fBounds.width());
1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkTDArray<uint8_t>& data = *row->fData;
1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int gap = x - row->fWidth;
1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (gap) {
1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            AppendRun(data, 0, gap);
1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row->fWidth += gap;
1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(row->fWidth < fBounds.width());
1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        AppendRun(data, alpha, count);
1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row->fWidth += count;
1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(row->fWidth <= fBounds.width());
1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
101649eac192faa35159752525b23345563252721c64tomhudson@google.com    void addColumn(int x, int y, U8CPU alpha, int height) {
101749eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(fBounds.contains(x, y + height - 1));
101849eac192faa35159752525b23345563252721c64tomhudson@google.com
101949eac192faa35159752525b23345563252721c64tomhudson@google.com        this->addRun(x, y, alpha, 1);
102049eac192faa35159752525b23345563252721c64tomhudson@google.com        this->flushRowH(fCurrRow);
102149eac192faa35159752525b23345563252721c64tomhudson@google.com        y -= fBounds.fTop;
102249eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(y == fCurrRow->fY);
102349eac192faa35159752525b23345563252721c64tomhudson@google.com        fCurrRow->fY = y + height - 1;
102449eac192faa35159752525b23345563252721c64tomhudson@google.com    }
1025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
10269154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    void addRectRun(int x, int y, int width, int height) {
10279154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        SkASSERT(fBounds.contains(x + width - 1, y + height - 1));
10289154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->addRun(x, y, 0xFF, width);
10299154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
1030a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com        // we assum the rect must be all we'll see for these scanlines
10319154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        // so we ensure our row goes all the way to our right
10329154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->flushRowH(fCurrRow);
10339154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
10349154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        y -= fBounds.fTop;
10359154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        SkASSERT(y == fCurrRow->fY);
10369154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        fCurrRow->fY = y + height - 1;
10379154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    }
10389154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com
103949eac192faa35159752525b23345563252721c64tomhudson@google.com    void addAntiRectRun(int x, int y, int width, int height,
104049eac192faa35159752525b23345563252721c64tomhudson@google.com                        SkAlpha leftAlpha, SkAlpha rightAlpha) {
10412add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        // According to SkBlitter.cpp, no matter whether leftAlpha is 0 or positive,
10422add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        // we should always consider [x, x+1] as the left-most column and [x+1, x+1+width]
10432add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        // as the rect with full alpha.
10442add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        SkASSERT(fBounds.contains(x + width + (rightAlpha > 0 ? 1 : 0),
104549eac192faa35159752525b23345563252721c64tomhudson@google.com                 y + height - 1));
104649eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(width >= 0);
104749eac192faa35159752525b23345563252721c64tomhudson@google.com
104849eac192faa35159752525b23345563252721c64tomhudson@google.com        // Conceptually we're always adding 3 runs, but we should
104949eac192faa35159752525b23345563252721c64tomhudson@google.com        // merge or omit them if possible.
105049eac192faa35159752525b23345563252721c64tomhudson@google.com        if (leftAlpha == 0xFF) {
105149eac192faa35159752525b23345563252721c64tomhudson@google.com            width++;
105249eac192faa35159752525b23345563252721c64tomhudson@google.com        } else if (leftAlpha > 0) {
105349eac192faa35159752525b23345563252721c64tomhudson@google.com          this->addRun(x++, y, leftAlpha, 1);
10542add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        } else {
10552add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian          // leftAlpha is 0, ignore the left column
10562add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian          x++;
105749eac192faa35159752525b23345563252721c64tomhudson@google.com        }
105849eac192faa35159752525b23345563252721c64tomhudson@google.com        if (rightAlpha == 0xFF) {
105949eac192faa35159752525b23345563252721c64tomhudson@google.com            width++;
106049eac192faa35159752525b23345563252721c64tomhudson@google.com        }
106149eac192faa35159752525b23345563252721c64tomhudson@google.com        if (width > 0) {
106249eac192faa35159752525b23345563252721c64tomhudson@google.com            this->addRun(x, y, 0xFF, width);
106349eac192faa35159752525b23345563252721c64tomhudson@google.com        }
106449eac192faa35159752525b23345563252721c64tomhudson@google.com        if (rightAlpha > 0 && rightAlpha < 255) {
106549eac192faa35159752525b23345563252721c64tomhudson@google.com            this->addRun(x + width, y, rightAlpha, 1);
106649eac192faa35159752525b23345563252721c64tomhudson@google.com        }
106749eac192faa35159752525b23345563252721c64tomhudson@google.com
106849eac192faa35159752525b23345563252721c64tomhudson@google.com        // we assume the rect must be all we'll see for these scanlines
106949eac192faa35159752525b23345563252721c64tomhudson@google.com        // so we ensure our row goes all the way to our right
107049eac192faa35159752525b23345563252721c64tomhudson@google.com        this->flushRowH(fCurrRow);
107149eac192faa35159752525b23345563252721c64tomhudson@google.com
107249eac192faa35159752525b23345563252721c64tomhudson@google.com        y -= fBounds.fTop;
107349eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(y == fCurrRow->fY);
107449eac192faa35159752525b23345563252721c64tomhudson@google.com        fCurrRow->fY = y + height - 1;
107549eac192faa35159752525b23345563252721c64tomhudson@google.com    }
107649eac192faa35159752525b23345563252721c64tomhudson@google.com
1077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    bool finish(SkAAClip* target) {
1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->flushRow(false);
1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* row = fRows.begin();
1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const Row* stop = fRows.end();
1082e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1083fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        size_t dataSize = 0;
1084e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            dataSize += row->fData->count();
1086e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
1087e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0 == dataSize) {
1090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            return target->setEmpty();
1091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
1092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1093209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        SkASSERT(fMinY >= fBounds.fTop);
1094209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        SkASSERT(fMinY < fBounds.fBottom);
1095209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        int adjustY = fMinY - fBounds.fTop;
1096209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fBounds.fTop = fMinY;
1097209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1098e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        RunHead* head = RunHead::Alloc(fRows.count(), dataSize);
1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        YOffset* yoffset = head->yoffsets();
1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* data = head->data();
1101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        uint8_t* baseData = data;
1102e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1103e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        row = fRows.begin();
1104c90419199525141a5b98091f856e359bf9daf5b1reed@google.com        SkDEBUGCODE(int prevY = row->fY - 1;)
1105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        while (row < stop) {
1106c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(prevY < row->fY);  // must be monotonic
1107c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkDEBUGCODE(prevY = row->fY);
1108c90419199525141a5b98091f856e359bf9daf5b1reed@google.com
1109209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            yoffset->fY = row->fY - adjustY;
1110a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            yoffset->fOffset = SkToU32(data - baseData);
1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            yoffset += 1;
1112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            size_t n = row->fData->count();
1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            memcpy(data, row->fData->begin(), n);
1115c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG
1116f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com            size_t bytesNeeded = compute_row_length(data, fBounds.width());
1117c90419199525141a5b98091f856e359bf9daf5b1reed@google.com            SkASSERT(bytesNeeded == n);
1118c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif
1119e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            data += n;
1120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 1;
1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->freeRuns();
1125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->fBounds = fBounds;
1126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        target->fRunHead = head;
1127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return target->trimBounds();
1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void dump() {
1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->validate();
1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int y;
1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (y = 0; y < fRows.count(); ++y) {
1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[y];
1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth);
1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const SkTDArray<uint8_t>& data = *row.fData;
1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = data.count();
1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = data.begin();
1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]);
1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkDebugf("\n");
1145e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1146e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void validate() {
1149e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG
1150803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com        if (false) { // avoid bit rot, suppress warning
1151803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com            test_count_left_right_zeros();
1152803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com        }
1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int prevY = -1;
1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (int i = 0; i < fRows.count(); ++i) {
1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const Row& row = fRows[i];
1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prevY < row.fY);
1157e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(fWidth == row.fWidth);
1158e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = row.fData->count();
1159e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            const uint8_t* ptr = row.fData->begin();
1160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(!(count & 1));
1161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int w = 0;
1162e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            for (int x = 0; x < count; x += 2) {
1163d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                int n = ptr[0];
1164d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                SkASSERT(n > 0);
1165d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com                w += n;
1166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                SkASSERT(w <= fWidth);
1167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                ptr += 2;
1168e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1169e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(w == fWidth);
1170e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            prevY = row.fY;
1171e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1172e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif
1173e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1174e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1175209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    // only called by BuilderBlitter
1176209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void setMinY(int y) {
1177209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = y;
1178209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
1179209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1180e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
11819154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    void flushRowH(Row* row) {
11829154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        // flush current row if needed
11839154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        if (row->fWidth < fWidth) {
11849154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            AppendRun(*row->fData, 0, fWidth - row->fWidth);
11859154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            row->fWidth = fWidth;
11869154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        }
11879154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com    }
1188209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1189e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Row* flushRow(bool readyForAnother) {
119096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        Row* next = nullptr;
1191e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fRows.count();
1192e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 0) {
11939154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com            this->flushRowH(&fRows[count - 1]);
1194e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1195e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (count > 1) {
1196e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            // are our last two runs the same?
1197e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* prev = &fRows[count - 2];
1198e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            Row* curr = &fRows[count - 1];
1199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(prev->fWidth == fWidth);
1200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            SkASSERT(curr->fWidth == fWidth);
1201e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (*prev->fData == *curr->fData) {
1202e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                prev->fY = curr->fY;
1203e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
1204e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    curr->fData->rewind();
1205e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = curr;
1206e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                } else {
1207e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    delete curr->fData;
1208e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    fRows.removeShuffle(count - 1);
1209e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
1210e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            } else {
1211e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                if (readyForAnother) {
1212e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next = fRows.append();
1213e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                    next->fData = new SkTDArray<uint8_t>;
1214e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                }
1215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } else {
1217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (readyForAnother) {
1218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next = fRows.append();
1219e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                next->fData = new SkTDArray<uint8_t>;
1220e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1221e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1222e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return next;
1223e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1224e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1225e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) {
1226e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        do {
1227e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int n = count;
1228e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (n > 255) {
1229e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                n = 255;
1230e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
1231e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            uint8_t* ptr = data.append(2);
1232e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[0] = n;
1233e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            ptr[1] = alpha;
1234e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            count -= n;
1235e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        } while (count > 0);
1236e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1237e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
1238e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1239e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter {
124080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com    int fLastY;
124180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com
124280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com    /*
124380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        If we see a gap of 1 or more empty scanlines while building in Y-order,
124480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        we inject an explicit empty scanline (alpha==0)
1245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
124680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        See AAClipTest.cpp : test_path_with_hole()
124780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com     */
124880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com    void checkForYGap(int y) {
124980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        SkASSERT(y >= fLastY);
125080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        if (fLastY > -SK_MaxS32) {
125180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com            int gap = y - fLastY;
125280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com            if (gap > 1) {
125380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com                fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft);
125480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com            }
125580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        }
125680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        fLastY = y;
125780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com    }
125880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com
1259e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
126080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com
1261e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter(Builder* builder) {
1262e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder = builder;
12631778564c75de5799d45126984f8faafd03523100reed@google.com        fLeft = builder->getBounds().fLeft;
12641778564c75de5799d45126984f8faafd03523100reed@google.com        fRight = builder->getBounds().fRight;
1265209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        fMinY = SK_MaxS32;
126680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        fLastY = -SK_MaxS32;    // sentinel
1267209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
1268209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1269209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void finish() {
1270209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        if (fMinY < SK_MaxS32) {
1271209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            fBuilder->setMinY(fMinY);
1272209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        }
1273e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1274e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
127549eac192faa35159752525b23345563252721c64tomhudson@google.com    /**
127649eac192faa35159752525b23345563252721c64tomhudson@google.com       Must evaluate clips in scan-line order, so don't want to allow blitV(),
127749eac192faa35159752525b23345563252721c64tomhudson@google.com       but an AAClip can be clipped down to a single pixel wide, so we
127849eac192faa35159752525b23345563252721c64tomhudson@google.com       must support it (given AntiRect semantics: minimum width is 2).
127949eac192faa35159752525b23345563252721c64tomhudson@google.com       Instead we'll rely on the runtime asserts to guarantee Y monotonicity;
128049eac192faa35159752525b23345563252721c64tomhudson@google.com       any failure cases that misses may have minor artifacts.
128149eac192faa35159752525b23345563252721c64tomhudson@google.com    */
128236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override {
12832add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        if (height == 1) {
12842add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            // We're still in scan-line order if height is 1
12852add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            // This is useful for Analytic AA
12862add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            const SkAlpha alphas[2] = {alpha, 0};
12872add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            const int16_t runs[2] = {1, 0};
12882add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            this->blitAntiH(x, y, alphas, runs);
12892add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        } else {
12902add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            this->recordMinY(y);
12912add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            fBuilder->addColumn(x, y, alpha, height);
12922add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian            fLastY = y + height - 1;
12932add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian        }
129449eac192faa35159752525b23345563252721c64tomhudson@google.com    }
1295045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
129636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override {
12979154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        this->recordMinY(y);
129880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        this->checkForYGap(y);
12999154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com        fBuilder->addRectRun(x, y, width, height);
1300302b861338a626014153cc7368c54edbc646cfe5reed@google.com        fLastY = y + height - 1;
1301562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com    }
1302045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
130349eac192faa35159752525b23345563252721c64tomhudson@google.com    virtual void blitAntiRect(int x, int y, int width, int height,
130436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                     SkAlpha leftAlpha, SkAlpha rightAlpha) override {
130549eac192faa35159752525b23345563252721c64tomhudson@google.com        this->recordMinY(y);
1306302b861338a626014153cc7368c54edbc646cfe5reed@google.com        this->checkForYGap(y);
130749eac192faa35159752525b23345563252721c64tomhudson@google.com        fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha);
1308302b861338a626014153cc7368c54edbc646cfe5reed@google.com        fLastY = y + height - 1;
130949eac192faa35159752525b23345563252721c64tomhudson@google.com    }
131049eac192faa35159752525b23345563252721c64tomhudson@google.com
131136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitMask(const SkMask&, const SkIRect& clip) override
1312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        { unexpected(); }
1313e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
131441e010cb901c0da9066c4df562030808c9ccd7f8reed    const SkPixmap* justAnOpaqueColor(uint32_t*) override {
131596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1317e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
131836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override {
1319209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        this->recordMinY(y);
132080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        this->checkForYGap(y);
1321e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBuilder->addRun(x, y, 0xFF, width);
1322e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1323e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1324e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha alpha[],
132536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t runs[]) override {
1326209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        this->recordMinY(y);
132780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com        this->checkForYGap(y);
1328e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        for (;;) {
1329e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            int count = *runs;
1330e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            if (count <= 0) {
1331e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                return;
1332e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            }
13331778564c75de5799d45126984f8faafd03523100reed@google.com
13341778564c75de5799d45126984f8faafd03523100reed@google.com            // The supersampler's buffer can be the width of the device, so
13351d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // we may have to trim the run to our bounds. Previously, we assert that
13361d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // the extra spans are always alpha==0.
13371d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // However, the analytic AA is too sensitive to precision errors
13381d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // so it may have extra spans with very tiny alpha because after several
13391d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // arithmatic operations, the edge may bleed the path boundary a little bit.
13401d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian            // Therefore, instead of always asserting alpha==0, we assert alpha < 0x10.
13411778564c75de5799d45126984f8faafd03523100reed@google.com            int localX = x;
13421778564c75de5799d45126984f8faafd03523100reed@google.com            int localCount = count;
13431778564c75de5799d45126984f8faafd03523100reed@google.com            if (x < fLeft) {
13441d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian                SkASSERT(0x10 > *alpha);
13451778564c75de5799d45126984f8faafd03523100reed@google.com                int gap = fLeft - x;
13461778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(gap <= count);
13471778564c75de5799d45126984f8faafd03523100reed@google.com                localX += gap;
13481778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= gap;
13491778564c75de5799d45126984f8faafd03523100reed@google.com            }
13501778564c75de5799d45126984f8faafd03523100reed@google.com            int right = x + count;
13511778564c75de5799d45126984f8faafd03523100reed@google.com            if (right > fRight) {
13521d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian                SkASSERT(0x10 > *alpha);
13531778564c75de5799d45126984f8faafd03523100reed@google.com                localCount -= right - fRight;
13541778564c75de5799d45126984f8faafd03523100reed@google.com                SkASSERT(localCount >= 0);
13551778564c75de5799d45126984f8faafd03523100reed@google.com            }
1356fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13571778564c75de5799d45126984f8faafd03523100reed@google.com            if (localCount) {
13581778564c75de5799d45126984f8faafd03523100reed@google.com                fBuilder->addRun(localX, y, *alpha, localCount);
13591778564c75de5799d45126984f8faafd03523100reed@google.com            }
1360820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com            // Next run
1361e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            runs += count;
1362e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            alpha += count;
1363e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            x += count;
1364e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1365e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1366e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1367e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
1368e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder* fBuilder;
13691778564c75de5799d45126984f8faafd03523100reed@google.com    int      fLeft; // cache of builder's bounds' left edge
13701778564c75de5799d45126984f8faafd03523100reed@google.com    int      fRight;
1371209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    int      fMinY;
1372209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com
1373209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    /*
1374209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  We track this, in case the scan converter skipped some number of
1375209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  scanlines at the (relative to the bounds it was given). This allows
1376209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  the builder, during its finish, to trip its bounds down to the "real"
1377209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     *  top.
1378209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com     */
1379209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    void recordMinY(int y) {
1380209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        if (y < fMinY) {
1381209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com            fMinY = y;
1382209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com        }
1383209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    }
1384e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1385e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void unexpected() {
13867ca9a74fef3296cdf1385785b5e817e963bb4c35Ben Wagner        SK_ABORT("---- did not expect to get called here");
1387e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1388e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
1389e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1390f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) {
1391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
1392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1393322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (clip && clip->isEmpty()) {
1394e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return this->setEmpty();
1395e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1396e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1397e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect ibounds;
1398322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    path.getBounds().roundOut(&ibounds);
1399e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkRegion tmpClip;
140196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == clip) {
1402322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        tmpClip.setRect(ibounds);
1403322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        clip = &tmpClip;
1404322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1405fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1406ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li    // Since we assert that the BuilderBlitter will never blit outside the intersection
1407ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li    // of clip and ibounds, we create this snugClip to be that intersection and send it
1408ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li    // to the scan-converter.
1409ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li    SkRegion snugClip(*clip);
1410ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li
1411045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (path.isInverseFillType()) {
1412045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        ibounds = clip->getBounds();
1413045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    } else {
1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) {
1415e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return this->setEmpty();
1416e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1417ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li        snugClip.op(ibounds, SkRegion::kIntersect_Op);
1418e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1419e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1420e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    Builder        builder(ibounds);
1421e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    BuilderBlitter blitter(&builder);
1422e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1423f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    if (doAA) {
14247d99dad70b97a534a6e23e9c74d914b5eb17ff1eYuqian Li        SkScan::AntiFillPath(path, snugClip, &blitter, true);
1425f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    } else {
1426ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li        SkScan::FillPath(path, snugClip, &blitter);
1427f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    }
1428e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1429209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com    blitter.finish();
1430045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return builder.finish(this);
1431e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1432e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1433e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1434e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom,
1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowA, const SkIRect& rectA,
1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                        const uint8_t* rowB, const SkIRect& rectB);
1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB);
1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // Multiply
1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, alphaB);
1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOver
1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB);
1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // SrcOut
1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return SkMulDiv255Round(alphaA, 0xFF - alphaB);
1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) {
1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    // XOR
1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB);
1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) {
1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
1466322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return diffAlphaProc;
1467322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
1468322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return unionAlphaProc;
1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return xorAlphaProc;
1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
14720c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unexpected region op");
1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return sectAlphaProc;
1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1477322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter {
1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic:
1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    RowIter(const uint8_t* row, const SkIRect& bounds) {
1480322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fRow = row;
1481322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fLeft = bounds.fLeft;
1482322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        fBoundsRight = bounds.fRight;
14831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (row) {
14841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = bounds.fLeft + row[0];
14851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(fRight <= fBoundsRight);
14861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = row[1];
14871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = false;
14881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else {
14891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fDone = true;
14901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fRight = kMaxInt32;
14911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            fAlpha = 0;
14921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        }
1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1494322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1495322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool done() const { return fDone; }
14961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int left() const { return fLeft; }
14971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int right() const { return fRight; }
14981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    U8CPU alpha() const { return fAlpha; }
1499322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void next() {
15001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!fDone) {
1501322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            fLeft = fRight;
15021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (fRight == fBoundsRight) {
15031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fDone = true;
15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight = kMaxInt32;
15051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = 0;
15061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
15071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRow += 2;
15081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fRight += fRow[0];
15091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                fAlpha = fRow[1];
15101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                SkASSERT(fRight <= fBoundsRight);
15111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1512322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1513322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1514322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1515322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
1516322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const uint8_t*  fRow;
1517322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fLeft;
1518322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fRight;
1519322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int             fBoundsRight;
1520322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool            fDone;
15211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    uint8_t         fAlpha;
1522322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com};
1523322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
15241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) {
15251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (rite == riteA) {
15261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
15271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        leftA = iter.left();
15281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        riteA = iter.right();
1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1530322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1531322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1532803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED
15331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) {
15341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(min < max);
15351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    SkASSERT(boundsMin < boundsMax);
15361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min >= boundsMax || max <= boundsMin) {
15371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        return false;
15381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
15391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (min < boundsMin) {
15401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        min = boundsMin;
15411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
15421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (max > boundsMax) {
15431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        max = boundsMax;
15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
15451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    return true;
15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
1547803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif
15481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
1549322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY,
1550322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      RowIter& iterA, RowIter& iterB,
1551322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                      AlphaProc proc, const SkIRect& bounds) {
1552322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftA = iterA.left();
1553322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteA = iterA.right();
1554322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int leftB = iterB.left();
1555322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int riteB = iterB.right();
1556322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
15571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    int prevRite = bounds.fLeft;
15581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
15591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
1560322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaA = 0;
1561322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        U8CPU alphaB = 0;
1562322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int left, rite;
1563fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (leftA < leftB) {
1565322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftA;
1566322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
15671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteA <= leftB) {
15681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteA;
15691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
15701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftA = leftB;
15711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
15721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (leftB < leftA) {
1573322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            left = leftB;
1574322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
15751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (riteB <= leftA) {
15761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = riteB;
15771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
15781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                rite = leftB = leftA;
15791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1580322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
15811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            left = leftA;   // or leftB, since leftA == leftB
15821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            rite = leftA = leftB = SkMin32(riteA, riteB);
1583322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaA = iterA.alpha();
1584322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            alphaB = iterB.alpha();
1585322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1586322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1587322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fRight) {
1588322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1589322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
159034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (rite > bounds.fRight) {
159134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            rite = bounds.fRight;
159234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
159334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (left >= bounds.fLeft) {
15951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(rite > left);
1596322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left);
15971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            prevRite = rite;
1598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
15991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
16001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterA, leftA, riteA, rite);
16011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_row(iterB, leftB, riteB, rite);
16021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
16031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
16041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (prevRite < bounds.fRight) {
16051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite);
1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1608322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
16091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) {
16101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    if (bot == botA) {
16111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        iter.next();
16121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        topA = botA;
16131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        SkASSERT(botA == iter.top());
16141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        botA = iter.bottom();
1615322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1618322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A,
1619322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                     const SkAAClip& B, SkRegion::Op op) {
1620322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    AlphaProc proc = find_alpha_proc(op);
1621322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkIRect& bounds = builder.getBounds();
1622322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1623322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterA(A);
1624322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkAAClip::Iter iterB(B);
1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterA.done());
1627322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topA = iterA.top();
1628322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botA = iterA.bottom();
1629322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(!iterB.done());
1630322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int topB = iterB.top();
1631322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    int botB = iterB.bottom();
1632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
16331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    do {
163496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        const uint8_t* rowA = nullptr;
163596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        const uint8_t* rowB = nullptr;
1636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        int top, bot;
16371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
16381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (topA < topB) {
1639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topA;
1640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
16411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botA <= topB) {
16421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botA;
16431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
16441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topA = topB;
16451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1646fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (topB < topA) {
1648322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            top = topB;
1649322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
16501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            if (botB <= topA) {
16511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = botB;
16521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            } else {
16531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com                bot = topB = topA;
16541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            }
1655322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        } else {
16561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            top = topA;   // or topB, since topA == topB
16571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            bot = topA = topB = SkMin32(botA, botB);
1658322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowA = iterA.data();
1659322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            rowB = iterB.data();
1660322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1661322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1662322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        if (top >= bounds.fBottom) {
1663322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1664322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
166534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
166634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        if (bot > bounds.fBottom) {
166734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com            bot = bounds.fBottom;
166834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        }
166934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        SkASSERT(top < bot);
167034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
16711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        if (!rowA && !rowB) {
16721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width());
16731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        } else if (top >= bounds.fTop) {
16741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            SkASSERT(bot <= bounds.fBottom);
16751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds);
16761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com            RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds);
1677322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds);
1678322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        }
1679322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
16801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterA, topA, botA, bot);
16811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com        adjust_iter(iterB, topB, botB, bot);
16821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    } while (!iterA.done() || !iterB.done());
1683322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
1684322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1685322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig,
1686322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                  SkRegion::Op op) {
1687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_AACLIP_VALIDATE(*this);
1688fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1689322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReplace_Op == op) {
1690322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return this->set(clipBOrig);
1691322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1693322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipA = &clipAOrig;
1694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    const SkAAClip* clipB = &clipBOrig;
1695fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    if (SkRegion::kReverseDifference_Op == op) {
1697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        SkTSwap(clipA, clipB);
1698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        op = SkRegion::kDifference_Op;
1699322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1700322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1701322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool a_empty = clipA->isEmpty();
1702322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool b_empty = clipB->isEmpty();
1703322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1704322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkIRect bounds;
1705322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    switch (op) {
1706322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kDifference_Op:
1707322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
1708322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
1709322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1710322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) {
1711322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
1712322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1713322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
1714322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1715fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1716322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kIntersect_Op:
1717322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds,
1718322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                                                         clipB->fBounds)) {
1719322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->setEmpty();
1720322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1721322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1722fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1723322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kUnion_Op:
1724322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        case SkRegion::kXOR_Op:
1725322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (a_empty) {
1726322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipB);
1727322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1728322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            if (b_empty) {
1729322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com                return this->set(*clipA);
1730322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            }
1731322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds = clipA->fBounds;
1732322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            bounds.join(clipB->fBounds);
1733322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            break;
1734322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1735322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        default:
17360c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown region op");
1737322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com            return !this->isEmpty();
1738322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
1739322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1740322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1741322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds));
1742322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
1743322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    Builder builder(bounds);
1744322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    operateY(builder, *clipA, *clipB, op);
1745045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1746045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return builder.finish(this);
1747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1748e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/*
1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  It can be expensive to build a local aaclip before applying the op, so
1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  we first see if we can restrict the bounds of new rect to our current
1752045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *  bounds, or note that the new rect subsumes our current clip.
1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */
1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) {
1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkIRect        rStorage;
1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkIRect* r = &rOrig;
1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (op) {
1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kIntersect_Op:
1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (!rStorage.intersect(rOrig, fBounds)) {
1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // no overlap, so we're empty
1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setEmpty();
1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rStorage == fBounds) {
1766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // we were wholly inside the rect, no change
1767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return !this->isEmpty();
1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (this->quickContains(rStorage)) {
1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                // the intersection is wholly inside us, we're a rect
1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rStorage);
1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            r = &rStorage;   // use the intersected bounds
1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kDifference_Op:
1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1777045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kUnion_Op:
1778045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rOrig.contains(fBounds)) {
1779045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rOrig);
1780045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1781045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
1783045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1784045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1785045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
178647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
1787045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    clip.setRect(*r);
178847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
178947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
179047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) {
1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRect        rStorage, boundsStorage;
1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkRect* r = &rOrig;
1794fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    boundsStorage.set(fBounds);
1796045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (op) {
1797045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kIntersect_Op:
1798045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kDifference_Op:
1799045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (!rStorage.intersect(rOrig, boundsStorage)) {
1800e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com                if (SkRegion::kIntersect_Op == op) {
1801e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com                    return this->setEmpty();
1802e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com                } else {    // kDifference
1803e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com                    return !this->isEmpty();
1804e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com                }
1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            r = &rStorage;   // use the intersected bounds
1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkRegion::kUnion_Op:
1809045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (rOrig.contains(boundsStorage)) {
1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                return this->setRect(rOrig);
1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1813045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
1815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1816fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
181747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    SkAAClip clip;
1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    clip.setRect(*r, doAA);
181947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
182047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
182147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
182247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) {
182347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    return this->op(*this, clip, op);
182447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com}
182547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
1826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1827045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const {
182996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == dst) {
1830045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return !this->isEmpty();
1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1832fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
1834045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return dst->setEmpty();
1835045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1836fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this != dst) {
1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        sk_atomic_inc(&fRunHead->fRefCnt);
183919224c3d7903921ca86c856cc42adb31fc3164a9tomhudson@google.com        dst->freeRuns();
1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst->fRunHead = fRunHead;
1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst->fBounds = fBounds;
1842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    dst->fBounds.offset(dx, dy);
1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return true;
1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask,
1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                               const uint8_t* SK_RESTRICT row,
1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                               int width) {
1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (width > 0) {
1851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = row[0];
1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(width >= n);
1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        memset(mask, row[1], n);
1854045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask += n;
1855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
1856045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        width -= n;
1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1858a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com    SkASSERT(0 == width);
1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const {
1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fFormat = SkMask::kA8_Format;
1863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (this->isEmpty()) {
1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask->fBounds.setEmpty();
186596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        mask->fImage = nullptr;
1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask->fRowBytes = 0;
1867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1869fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fBounds = fBounds;
1871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fRowBytes = fBounds.width();
1872045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    size_t size = mask->computeImageSize();
1873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    mask->fImage = SkMask::AllocImage(size);
1874fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    Iter iter(*this);
1876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    uint8_t* dst = mask->fImage;
1877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = fBounds.width();
1878fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int y = fBounds.fTop;
1880045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    while (!iter.done()) {
1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        do {
1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            expand_row_to_mask(dst, iter.data(), width);
1883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            dst += mask->fRowBytes;
1884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } while (++y < iter.bottom());
1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        iter.next();
1886045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1887045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
1888045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1889045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width,
1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                         int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) {
1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // we don't read our initial n from data, since the caller may have had to
1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // clip it, hence the initialCount parameter.
1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int n = initialCount;
1897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (n > width) {
1899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            n = width;
1900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(n > 0);
1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs[0] = n;
1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        runs += n;
1904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa[0] = data[1];
1906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        aa += n;
1907fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        data += 2;
1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        width -= n;
1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == width) {
1911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            break;
1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // load the next count
1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        n = data[0];
1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    runs[0] = 0;    // sentinel
1917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() {
1920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    sk_free(fScanlineScratch);
1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() {
192496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fScanlineScratch) {
1925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        // add 1 so we can store the terminating run count of 0
1926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int count = fAAClipBounds.width() + 1;
1927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // we use this either for fRuns + fAA, or a scaline of a mask
1928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // which may be as deep as 32bits
1929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor));
1930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fRuns = (int16_t*)fScanlineScratch;
1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fAA = (SkAlpha*)(fRuns + count);
1932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) {
1936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(width > 0);
1937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x, y));
1938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkASSERT(fAAClipBounds.contains(x + width  - 1, y));
1939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1940a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com    const uint8_t* row = fAAClip->findRow(y);
1941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
1942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (initialCount >= width) {
1945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha alpha = row[1];
1946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == alpha) {
1947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0xFF == alpha) {
1950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            fBlitter->blitH(x, y, width);
1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            return;
1952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
1954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
1956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    expandToRuns(row, initialCount, width, fRuns, fAA);
1957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN,
1962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const SkAlpha* SK_RESTRICT srcAA,
1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  const int16_t* SK_RESTRICT srcRuns,
1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  SkAlpha* SK_RESTRICT dstAA,
1965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int16_t* SK_RESTRICT dstRuns,
1966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                  int width) {
1967e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkDEBUGCODE(int accumulated = 0;)
1968e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int srcN = srcRuns[0];
1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // do we need this check?
1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (0 == srcN) {
1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return;
1972045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
1973045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
1974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    for (;;) {
1975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(rowN > 0);
1976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(srcN > 0);
1977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]);
1979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        int minN = SkMin32(srcN, rowN);
1980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns[0] = minN;
1981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstRuns += minN;
1982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA[0] = newAlpha;
1983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        dstAA += minN;
1984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
1985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (srcN -= minN)) {
1986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // refresh
1987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcRuns += srcN;
1988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcAA += srcN;
1989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            srcN = srcRuns[0];  // reload
1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            if (0 == srcN) {
1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                break;
1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
1993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (0 == (rowN -= minN)) {
1995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            row += 2;
1996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com            rowN = row[0];  // reload
1997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
1998fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkDEBUGCODE(accumulated += minN;)
2000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(accumulated <= width);
2001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
200234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    dstRuns[0] = 0;
2003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
2006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                                const int16_t runs[]) {
2007a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com
2008a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com    const uint8_t* row = fAAClip->findRow(y);
2009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int initialCount;
2010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    row = fAAClip->findX(row, x, &initialCount);
2011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    this->ensureRunsAndAA();
2013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width());
2015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    fBlitter->blitAntiH(x, y, fAA, fRuns);
2016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
2019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + 1, y + height)) {
2020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitV(x, y, height, alpha);
2021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
2022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
2023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2024045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (;;) {
2025a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com        int lastY SK_INIT_TO_AVOID_WARNING;
2026e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        const uint8_t* row = fAAClip->findRow(y, &lastY);
2027045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int dy = lastY - y + 1;
2028045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (dy > height) {
2029045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            dy = height;
2030045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2031045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        height -= dy;
2032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2033a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com        row = fAAClip->findX(row, x);
2034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]);
2035e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        if (newAlpha) {
2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fBlitter->blitV(x, y, dy, newAlpha);
2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(height >= 0);
2039045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (height <= 0) {
2040045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
2041e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        }
2042e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y = lastY + 1;
2043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
2044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) {
2047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    if (fAAClip->quickContains(x, y, x + width, y + height)) {
2048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter->blitRect(x, y, width, height);
2049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return;
2050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
2051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2052e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    while (--height >= 0) {
2053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        this->blitH(x, y, width);
2054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        y += 1;
2055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
2056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2058045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row,
2059045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                            int initialRowCount, void* dst);
2060045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2061045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) {
2062045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    memcpy(dst, src, n);
2063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2064e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2065045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) {
2066045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    sk_bzero(dst, n);
2067e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}
2068e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) {
2070045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return SkMulDiv255Round(value, alpha);
2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
2072d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed
2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) {
2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned r = SkGetPackedR16(value);
2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned g = SkGetPackedG16(value);
2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    unsigned b = SkGetPackedB16(value);
2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return SkPackRGB16(SkMulDiv255Round(r, alpha),
2078803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                       SkMulDiv255Round(g, alpha),
2079803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                       SkMulDiv255Round(b, alpha));
2080045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
2081322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
20829449616020a58043a49f0342679bf095918792a6herbtemplate <typename T>
20839449616020a58043a49f0342679bf095918792a6herbvoid mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) {
20849449616020a58043a49f0342679bf095918792a6herb    const T* SK_RESTRICT src = static_cast<const T*>(inSrc);
20859449616020a58043a49f0342679bf095918792a6herb    T* SK_RESTRICT       dst = static_cast<T*>(inDst);
2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (;;) {
2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(rowN > 0);
2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(srcN > 0);
2089fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int n = SkMin32(rowN, srcN);
2091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        unsigned rowA = row[1];
2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0xFF == rowA) {
2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            small_memcpy(dst, src, n * sizeof(T));
2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } else if (0 == rowA) {
2095045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            small_bzero(dst, n * sizeof(T));
2096045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } else {
2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            for (int i = 0; i < n; ++i) {
2098045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                dst[i] = mergeOne(src[i], rowA);
2099045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
2100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (0 == (srcN -= n)) {
2103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            break;
2104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        src += n;
2107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst += n;
2108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(rowN == n);
2110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row += 2;
2111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        rowN = row[0];
21121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
2113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
21141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
2115045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) {
2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    switch (format) {
2117045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kBW_Format:
21180c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unsupported");
211996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
2120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        case SkMask::kA8_Format:
21219449616020a58043a49f0342679bf095918792a6herb        case SkMask::k3D_Format:
21229449616020a58043a49f0342679bf095918792a6herb            return mergeT<uint8_t> ;
21239449616020a58043a49f0342679bf095918792a6herb        case SkMask::kLCD16_Format:
21249449616020a58043a49f0342679bf095918792a6herb            return mergeT<uint16_t>;
2125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        default:
21260c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unsupported");
212796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
21281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com    }
2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
21301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) {
2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(bitInAByte <= 0xFF);
2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // negation turns any non-zero into 0xFFFFFF??, so we just shift down
2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // some value >= 8 to get a full FF value
2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return -bitInAByte >> 8;
21361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com}
21371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) {
2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(SkMask::kBW_Format == srcMask.fFormat);
2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(SkMask::kA8_Format == dstMask->fFormat);
2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = srcMask.fBounds.width();
2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int height = srcMask.fBounds.height();
2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage;
2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t srcRB = srcMask.fRowBytes;
2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage;
2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t dstRB = dstMask->fRowBytes;
2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int wholeBytes = width >> 3;
2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int leftOverBits = width & 7;
2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2153045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    for (int y = 0; y < height; ++y) {
2154045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        uint8_t* SK_RESTRICT d = dst;
2155045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        for (int i = 0; i < wholeBytes; ++i) {
2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int srcByte = src[i];
2157045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[0] = bit2byte(srcByte & (1 << 7));
2158045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[1] = bit2byte(srcByte & (1 << 6));
2159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[2] = bit2byte(srcByte & (1 << 5));
2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[3] = bit2byte(srcByte & (1 << 4));
2161045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[4] = bit2byte(srcByte & (1 << 3));
2162045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[5] = bit2byte(srcByte & (1 << 2));
2163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[6] = bit2byte(srcByte & (1 << 1));
2164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d[7] = bit2byte(srcByte & (1 << 0));
2165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            d += 8;
2166045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        if (leftOverBits) {
2168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            int srcByte = src[wholeBytes];
2169045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            for (int x = 0; x < leftOverBits; ++x) {
2170045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                *d++ = bit2byte(srcByte & 0x80);
2171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                srcByte <<= 1;
2172045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            }
2173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        }
2174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        src += srcRB;
2175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        dst += dstRB;
2176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
2177322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
2178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
2179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) {
2180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(fAAClip->getBounds().contains(clip));
2181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (fAAClip->quickContains(clip)) {
2183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fBlitter->blitMask(origMask, clip);
2184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com        return;
2185322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
2186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
2187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const SkMask* mask = &origMask;
2188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
2189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // if we're BW, we need to upscale to A8 (ugh)
2190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkMask  grayMask;
2191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (SkMask::kBW_Format == origMask.fFormat) {
2192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fFormat = SkMask::kA8_Format;
2193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fBounds = origMask.fBounds;
2194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fRowBytes = origMask.fBounds.width();
2195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        size_t size = grayMask.computeImageSize();
2196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size,
2197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                               SkAutoMalloc::kReuse_OnShrink);
2198322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
2199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        upscaleBW2A8(&grayMask, origMask);
2200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        mask = &grayMask;
2201322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    }
2202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2203045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    this->ensureRunsAndAA();
2204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2205045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D
2206045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // data into a temp block to support it better (ugh)
2207045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const void* src = mask->getAddr(clip.fLeft, clip.fTop);
2209045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const size_t srcRB = mask->fRowBytes;
2210045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int width = clip.width();
2211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat);
2212045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2213045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkMask rowMask;
2214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat;
2215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fBounds.fLeft = clip.fLeft;
2216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fBounds.fRight = clip.fRight;
2217045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1
2218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    rowMask.fImage = (uint8_t*)fScanlineScratch;
2219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    int y = clip.fTop;
2221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    const int stopY = y + clip.height();
2222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2223045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    do {
2224a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com        int localStopY SK_INIT_TO_AVOID_WARNING;
2225045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const uint8_t* row = fAAClip->findRow(y, &localStopY);
2226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // findRow returns last Y, not stop, so we add 1
2227045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        localStopY = SkMin32(localStopY + 1, stopY);
2228045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
2229045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        int initialCount;
2230045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        row = fAAClip->findX(row, clip.fLeft, &initialCount);
2231045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        do {
2232045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            mergeProc(src, width, row, initialCount, rowMask.fImage);
2233045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            rowMask.fBounds.fTop = y;
2234045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            rowMask.fBounds.fBottom = y + 1;
2235045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fBlitter->blitMask(rowMask, rowMask.fBounds);
2236045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            src = (const void*)((const char*)src + srcRB);
2237045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        } while (++y < localStopY);
2238045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    } while (y < stopY);
2239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
2240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
224141e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) {
224296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
2243322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}
2244