1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*
3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2006 The Android Open Source Project
4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *
5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file.
7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkRegionPriv.h"
11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkBlitter.h"
12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkScan.h"
13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkTDArray.h"
14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkPath.h"
15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkRgnBuilder : public SkBlitter {
17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual ~SkRgnBuilder();
19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // returns true if it could allocate the working storage needed
21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    bool init(int maxHeight, int maxTransitions);
22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    void done() {
24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (fCurrScanline != NULL) {
25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurrScanline->firstX()));
26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (!this->collapsWithPrev()) { // flush the last line
27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fCurrScanline = fCurrScanline->nextScanline();
28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int     computeRunCount() const;
33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    void    copyToRect(SkIRect*) const;
34f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    void    copyToRgn(SkRegion::RunType runs[]) const;
35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
36f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void blitH(int x, int y, int width);
37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DEBUG
39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    void dump() const {
40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkDebugf("SkRgnBuilder: Top = %d\n", fTop);
41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        const Scanline* line = (Scanline*)fStorage;
42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        while (line < fCurrScanline) {
43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkDebugf("SkRgnBuilder::Scanline: LastY=%d, fXCount=%d", line->fLastY, line->fXCount);
44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = 0; i < line->fXCount; i++) {
45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkDebugf(" %d", line->firstX()[i]);
46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkDebugf("\n");
48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            line = line->nextScanline();
50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    struct Scanline {
55f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkRegion::RunType fLastY;
56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkRegion::RunType fXCount;
57f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkRegion::RunType* firstX() const { return (SkRegion::RunType*)(this + 1); }
59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        Scanline* nextScanline() const {
60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return (Scanline*)((SkRegion::RunType*)(this + 1) + fXCount);
61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    };
63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::RunType*  fStorage;
64f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Scanline*           fCurrScanline;
65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Scanline*           fPrevScanline;
66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    //  points at next avialable x[] in fCurrScanline
67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::RunType*  fCurrXPtr;
68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::RunType   fTop;           // first Y value
69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int fStorageCount;
71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    bool collapsWithPrev() {
73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (fPrevScanline != NULL &&
74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fPrevScanline->fLastY + 1 == fCurrScanline->fLastY &&
75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fPrevScanline->fXCount == fCurrScanline->fXCount &&
76f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            !memcmp(fPrevScanline->firstX(),
77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    fCurrScanline->firstX(),
78f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    fCurrScanline->fXCount * sizeof(SkRegion::RunType)))
79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        {
80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // update the height of fPrevScanline
81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fPrevScanline->fLastY = fCurrScanline->fLastY;
82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return true;
83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
88f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkRgnBuilder::~SkRgnBuilder() {
89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    sk_free(fStorage);
90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkRgnBuilder::init(int maxHeight, int maxTransitions) {
93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((maxHeight | maxTransitions) < 0) {
94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Sk64 count, size;
98f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // compute the count with +1 and +3 slop for the working buffer
100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    count.setMul(maxHeight + 1, 3 + maxTransitions);
101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!count.is32() || count.isNeg()) {
102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fStorageCount = count.get32();
105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    size.setMul(fStorageCount, sizeof(SkRegion::RunType));
107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!size.is32() || size.isNeg()) {
108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == fStorage) {
113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fCurrScanline = NULL;    // signal empty collection
117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fPrevScanline = NULL;    // signal first scanline
118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkRgnBuilder::blitH(int x, int y, int width) {
122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (fCurrScanline == NULL) {  // first time
123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fTop = (SkRegion::RunType)(y);
124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrScanline = (Scanline*)fStorage;
125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrScanline->fLastY = (SkRegion::RunType)(y);
126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrXPtr = fCurrScanline->firstX();
127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(y >= fCurrScanline->fLastY);
129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (y > fCurrScanline->fLastY) {
131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // if we get here, we're done with fCurrScanline
132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurrScanline->firstX()));
133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            int prevLastY = fCurrScanline->fLastY;
135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (!this->collapsWithPrev()) {
136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fPrevScanline = fCurrScanline;
137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fCurrScanline = fCurrScanline->nextScanline();
138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (y - 1 > prevLastY) {  // insert empty run
141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fCurrScanline->fLastY = (SkRegion::RunType)(y - 1);
142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fCurrScanline->fXCount = 0;
143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                fCurrScanline = fCurrScanline->nextScanline();
144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // setup for the new curr line
146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fCurrScanline->fLastY = (SkRegion::RunType)(y);
147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fCurrXPtr = fCurrScanline->firstX();
148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    //  check if we should extend the current run, or add a new one
151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (fCurrXPtr > fCurrScanline->firstX() && fCurrXPtr[-1] == x) {
152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrXPtr[-1] = (SkRegion::RunType)(x + width);
153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrXPtr[0] = (SkRegion::RunType)(x);
155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrXPtr[1] = (SkRegion::RunType)(x + width);
156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCurrXPtr += 2;
157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(fCurrXPtr - fStorage < fStorageCount);
159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerint SkRgnBuilder::computeRunCount() const {
162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (fCurrScanline == NULL) {
163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const SkRegion::RunType*  line = fStorage;
167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const SkRegion::RunType*  stop = (const SkRegion::RunType*)fCurrScanline;
168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return 2 + (int)(stop - line);
170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkRgnBuilder::copyToRect(SkIRect* r) const {
173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(fCurrScanline != NULL);
174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage == 4);
175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const Scanline* line = (const Scanline*)fStorage;
177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(line->fXCount == 2);
178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    r->set(line->firstX()[0], fTop, line->firstX()[1], line->fLastY + 1);
180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkRgnBuilder::copyToRgn(SkRegion::RunType runs[]) const {
183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(fCurrScanline != NULL);
184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage > 4);
185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const Scanline* line = (const Scanline*)fStorage;
187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const Scanline* stop = fCurrScanline;
188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    *runs++ = fTop;
190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    do {
191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *runs++ = (SkRegion::RunType)(line->fLastY + 1);
192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int count = line->fXCount;
193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (count) {
194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            memcpy(runs, line->firstX(), count * sizeof(SkRegion::RunType));
195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            runs += count;
196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *runs++ = SkRegion::kRunTypeSentinel;
198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        line = line->nextScanline();
199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } while (line < stop);
200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(line == stop);
201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    *runs = SkRegion::kRunTypeSentinel;
202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) {
205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static const uint8_t gPathVerbToInitialLastIndex[] = {
206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0,  //  kMove_Verb
207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        1,  //  kLine_Verb
208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        2,  //  kQuad_Verb
209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        3,  //  kCubic_Verb
210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0,  //  kClose_Verb
211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0   //  kDone_Verb
212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    };
213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static const uint8_t gPathVerbToMaxEdges[] = {
215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0,  //  kMove_Verb
216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        1,  //  kLine_Verb
217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        2,  //  kQuad_VerbB
218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        3,  //  kCubic_Verb
219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0,  //  kClose_Verb
220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        0   //  kDone_Verb
221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    };
222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkPath::Iter    iter(path, true);
224f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkPoint         pts[4];
225f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkPath::Verb    verb;
226f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
227f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int maxEdges = 0;
228f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar    top = SkIntToScalar(SK_MaxS16);
229f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar    bot = SkIntToScalar(SK_MinS16);
230f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
231f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
232f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        maxEdges += gPathVerbToMaxEdges[verb];
233f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
234f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int lastIndex = gPathVerbToInitialLastIndex[verb];
235f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (lastIndex > 0) {
236f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = 1; i <= lastIndex; i++) {
237f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (top > pts[i].fY) {
238f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    top = pts[i].fY;
239f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                } else if (bot < pts[i].fY) {
240f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    bot = pts[i].fY;
241f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
242f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
243f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else if (SkPath::kMove_Verb == verb) {
244f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (top > pts[0].fY) {
245f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                top = pts[0].fY;
246f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            } else if (bot < pts[0].fY) {
247f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                bot = pts[0].fY;
248f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
249f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
250f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
251f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(top <= bot);
252f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
253f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    *itop = SkScalarRound(top);
254f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    *ibot = SkScalarRound(bot);
255f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return maxEdges;
256f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
257f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
258f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkRegion::setPath(const SkPath& path, const SkRegion& clip) {
259f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDEBUGCODE(this->validate();)
260f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
261f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (clip.isEmpty()) {
262f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->setEmpty();
263f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
264f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
265f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (path.isEmpty()) {
266f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (path.isInverseFillType()) {
267f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return this->set(clip);
268f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
269f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return this->setEmpty();
270f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
271f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
272f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
273f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    //  compute worst-case rgn-size for the path
274f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int pathTop, pathBot;
275f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot);
276f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int clipTop, clipBot;
277f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int clipTransitions;
278f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
279f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    clipTransitions = clip.count_runtype_values(&clipTop, &clipBot);
280f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
281f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int top = SkMax32(pathTop, clipTop);
282f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int bot = SkMin32(pathBot, clipBot);
283f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
284f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (top >= bot)
285f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->setEmpty();
286f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
287f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRgnBuilder builder;
288f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
289f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!builder.init(bot - top, SkMax32(pathTransitions, clipTransitions))) {
290f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // can't allocate working space, so return false
291f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->setEmpty();
292f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
293f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
294f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScan::FillPath(path, clip, &builder);
295f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    builder.done();
296f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
297f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int count = builder.computeRunCount();
298f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (count == 0) {
299f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->setEmpty();
300f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else if (count == kRectRegionRuns) {
301f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        builder.copyToRect(&fBounds);
302f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        this->setRect(fBounds);
303f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
304f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkRegion    tmp;
305f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
306f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        tmp.fRunHead = RunHead::Alloc(count);
307f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        builder.copyToRgn(tmp.fRunHead->writable_runs());
308f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        ComputeRunBounds(tmp.fRunHead->readonly_runs(), count, &tmp.fBounds);
309f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        this->swap(tmp);
310f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
311f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDEBUGCODE(this->validate();)
312f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
313f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
314f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
315f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////////////////////////
316f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////////////////////////
317f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
318f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct Edge {
319f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    enum {
320f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        kY0Link = 0x01,
321f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        kY1Link = 0x02,
322f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
323f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        kCompleteLink = (kY0Link | kY1Link)
324f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    };
325f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
326f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::RunType fX;
327f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::RunType fY0, fY1;
328f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint8_t fFlags;
329f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge*   fNext;
330f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
331f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    void set(int x, int y0, int y1) {
332f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(y0 != y1);
333f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
334f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fX = (SkRegion::RunType)(x);
335f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fY0 = (SkRegion::RunType)(y0);
336f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fY1 = (SkRegion::RunType)(y1);
337f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fFlags = 0;
338f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkDEBUGCODE(fNext = NULL;)
339f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
340f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
341f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int top() const {
342f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkFastMin32(fY0, fY1);
343f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
344f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
345f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
346f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic void find_link(Edge* base, Edge* stop) {
347f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(base < stop);
348f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
349f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (base->fFlags == Edge::kCompleteLink) {
350f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(base->fNext);
351f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return;
352f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
353f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
354f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(base + 1 < stop);
355f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
356f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int y0 = base->fY0;
357f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int y1 = base->fY1;
358f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
359f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* e = base;
360f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((base->fFlags & Edge::kY0Link) == 0) {
361f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (;;) {
362f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            e += 1;
363f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if ((e->fFlags & Edge::kY1Link) == 0 && y0 == e->fY1) {
364f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkASSERT(NULL == e->fNext);
365f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                e->fNext = base;
366f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                e->fFlags = SkToU8(e->fFlags | Edge::kY1Link);
367f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                break;
368f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
369f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
370f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
371f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
372f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    e = base;
373f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((base->fFlags & Edge::kY1Link) == 0) {
374f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (;;) {
375f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            e += 1;
376f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if ((e->fFlags & Edge::kY0Link) == 0 && y1 == e->fY0) {
377f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkASSERT(NULL == base->fNext);
378f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                base->fNext = e;
379f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                e->fFlags = SkToU8(e->fFlags | Edge::kY0Link);
380f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                break;
381f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
382f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
383f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
384f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
385f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    base->fFlags = Edge::kCompleteLink;
386f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
387f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
388f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic int extract_path(Edge* edge, Edge* stop, SkPath* path) {
389f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    while (0 == edge->fFlags) {
390f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        edge++; // skip over "used" edges
391f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
392f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
393f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(edge < stop);
394f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
395f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* base = edge;
396f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* prev = edge;
397f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    edge = edge->fNext;
398f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(edge != base);
399f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
400f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int count = 1;
401f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    path->moveTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY0));
402f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    prev->fFlags = 0;
403f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    do {
404f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (prev->fX != edge->fX || prev->fY1 != edge->fY0) { // skip collinear
405f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            path->lineTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY1));    // V
406f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            path->lineTo(SkIntToScalar(edge->fX), SkIntToScalar(edge->fY0));    // H
407f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
408f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prev = edge;
409f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        edge = edge->fNext;
410f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        count += 1;
411f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prev->fFlags = 0;
412f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } while (edge != base);
413f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    path->lineTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY1));    // V
414f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    path->close();
415f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return count;
416f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
417f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
418f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkTSearch.h"
419f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
420f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic int EdgeProc(const Edge* a, const Edge* b) {
421f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return (a->fX == b->fX) ? a->top() - b->top() : a->fX - b->fX;
422f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
423f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
424f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkRegion::getBoundaryPath(SkPath* path) const {
425f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // path could safely be NULL if we're empty, but the caller shouldn't
426f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // *know* that
427f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(path);
428f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
429f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (this->isEmpty()) {
430f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
431f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
432f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
433f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const SkIRect& bounds = this->getBounds();
434f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
435f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (this->isRect()) {
436f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkRect  r;
437f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        r.set(bounds);      // this converts the ints to scalars
438f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        path->addRect(r);
439f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return true;
440f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
441f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
442f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkRegion::Iterator  iter(*this);
443f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkTDArray<Edge>     edges;
444f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
445f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (const SkIRect& r = iter.rect(); !iter.done(); iter.next()) {
446f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        Edge* edge = edges.append(2);
447f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        edge[0].set(r.fLeft, r.fBottom, r.fTop);
448f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        edge[1].set(r.fRight, r.fTop, r.fBottom);
449f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
450f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkQSort(edges.begin(), edges.count(), sizeof(Edge),
451f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            (SkQSortCompareProc)EdgeProc);
452f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
453f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int count = edges.count();
454f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* start = edges.begin();
455f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* stop = start + count;
456f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Edge* e;
457f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
458f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (e = start; e != stop; e++) {
459f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        find_link(e, stop);
460f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
461f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
462f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DEBUG
463f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (e = start; e != stop; e++) {
464f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(e->fNext != NULL);
465f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(e->fFlags == Edge::kCompleteLink);
466f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
467f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
468f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
469f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    path->incReserve(count << 1);
470f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    do {
471f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkASSERT(count > 1);
472f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        count -= extract_path(start, stop, path);
473f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } while (count > 0);
474f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
475f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
476f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
477f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
478