1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkScanPriv.h"
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitter.h"
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkEdge.h"
11dc9be913d13b7e44e9fe02426f79cec624f1dc6bmike@reedtribe.org#include "SkEdgeBuilder.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkGeometry.h"
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPath.h"
14b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com#include "SkQuadClipper.h"
1526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com#include "SkRasterClip.h"
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRegion.h"
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplates.h"
18bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#include "SkTSort.h"
19bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com
20c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com#ifdef SK_USE_LEGACY_AA_COVERAGE
21c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com    #define SK_USE_STD_SORT_FOR_EDGES
22c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com#endif
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kEDGE_HEAD_Y    SK_MinS32
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kEDGE_TAIL_Y    SK_MaxS32
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG
28b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    static void validate_sort(const SkEdge* edge) {
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int y = kEDGE_HEAD_Y;
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
31b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        while (edge->fFirstY != SK_MaxS32) {
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            edge->validate();
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(y <= edge->fFirstY);
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            y = edge->fFirstY;
36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            edge = edge->fNext;
37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    #define validate_sort(edge)
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
43b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic inline void remove_edge(SkEdge* edge) {
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    edge->fPrev->fNext = edge->fNext;
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    edge->fNext->fPrev = edge->fPrev;
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
48b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic inline void swap_edges(SkEdge* prev, SkEdge* next) {
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(prev->fNext == next && next->fPrev == prev);
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // remove prev from the list
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    prev->fPrev->fNext = next;
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    next->fPrev = prev->fPrev;
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // insert prev after next
56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    prev->fNext = next->fNext;
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    next->fNext->fPrev = prev;
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    next->fNext = prev;
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    prev->fPrev = next;
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
62b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) {
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixed x = edge->fX;
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
65b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    for (;;) {
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkEdge* prev = edge->fPrev;
67434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // add 1 to curr_y since we may have added new edges (built from curves)
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // that start on the next scanline
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(prev && prev->fFirstY <= curr_y + 1);
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
72b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        if (prev->fX <= x) {
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            break;
74b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        }
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        swap_edges(prev, edge);
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
79b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void insert_new_edges(SkEdge* newEdge, int curr_y) {
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(newEdge->fFirstY >= curr_y);
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
82b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    while (newEdge->fFirstY == curr_y) {
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkEdge* next = newEdge->fNext;
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        backward_insert_edge_based_on_x(newEdge  SkPARAM(curr_y));
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        newEdge = next;
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG
90b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void validate_edges_for_y(const SkEdge* edge, int curr_y) {
91b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    while (edge->fFirstY <= curr_y) {
92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(edge->fPrev && edge->fNext);
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(edge->fPrev->fNext == edge);
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(edge->fNext->fPrev == edge);
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(edge->fFirstY <= edge->fLastY);
96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(edge->fPrev->fX <= edge->fX);
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        edge = edge->fNext;
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    #define validate_edges_for_y(edge, curr_y)
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( push )
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( disable : 4701 )
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comtypedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline);
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define PREPOST_START   true
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define PREPOST_END     false
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void walk_edges(SkEdge* prevHead, SkPath::FillType fillType,
115c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com                       SkBlitter* blitter, int start_y, int stop_y,
116b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                       PrePostProc proc) {
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validate_sort(prevHead->fNext);
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
119c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    int curr_y = start_y;
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int windingMask = (fillType & 1) ? 1 : -1;
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
123b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    for (;;) {
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int     w = 0;
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int     left SK_INIT_TO_AVOID_WARNING;
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        bool    in_interval = false;
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkEdge* currE = prevHead->fNext;
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkFixed prevX = prevHead->fX;
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        validate_edges_for_y(currE, curr_y);
131434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (proc) {
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            proc(blitter, curr_y, PREPOST_START);    // pre-proc
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
135434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
136b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        while (currE->fFirstY <= curr_y) {
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(currE->fLastY >= curr_y);
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com            int x = SkFixedRoundToInt(currE->fX);
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w += currE->fWinding;
141b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            if ((w & windingMask) == 0) { // we finished an interval
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkASSERT(in_interval);
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                int width = x - left;
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkASSERT(width >= 0);
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                if (width)
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    blitter->blitH(left, curr_y, width);
147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                in_interval = false;
148b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            } else if (!in_interval) {
149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                left = x;
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                in_interval = true;
151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkEdge* next = currE->fNext;
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkFixed newX;
155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
156b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            if (currE->fLastY == curr_y) {    // are we done with this edge?
157b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                if (currE->fCurveCount < 0) {
158b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                    if (((SkCubicEdge*)currE)->updateCubic()) {
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        SkASSERT(currE->fFirstY == curr_y + 1);
160434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        newX = currE->fX;
162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        goto NEXT_X;
163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    }
164b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                } else if (currE->fCurveCount > 0) {
165b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                    if (((SkQuadraticEdge*)currE)->updateQuadratic()) {
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        newX = currE->fX;
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        goto NEXT_X;
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    }
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                remove_edge(currE);
171b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            } else {
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkASSERT(currE->fLastY > curr_y);
173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                newX = currE->fX + currE->fDX;
174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                currE->fX = newX;
175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            NEXT_X:
176b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                if (newX < prevX) { // ripple currE backwards until it is x-sorted
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    backward_insert_edge_based_on_x(currE  SkPARAM(curr_y));
178b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                } else {
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    prevX = newX;
180b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                }
181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            currE = next;
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(currE);
184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
185434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (proc) {
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            proc(blitter, curr_y, PREPOST_END);    // post-proc
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        curr_y += 1;
191b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        if (curr_y >= stop_y) {
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            break;
193b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        }
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // now currE points to the first edge with a Yint larger than curr_y
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        insert_new_edges(currE, curr_y);
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
199e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com// return true if we're done with this edge
200e85a548b33e0471d64a68b246e640770a89ef51dreed@google.comstatic bool update_edge(SkEdge* edge, int last_y) {
201e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkASSERT(edge->fLastY >= last_y);
202e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    if (last_y == edge->fLastY) {
203e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        if (edge->fCurveCount < 0) {
204e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            if (((SkCubicEdge*)edge)->updateCubic()) {
205e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                SkASSERT(edge->fFirstY == last_y + 1);
206e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                return false;
207e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            }
208e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        } else if (edge->fCurveCount > 0) {
209e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            if (((SkQuadraticEdge*)edge)->updateQuadratic()) {
210e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                SkASSERT(edge->fFirstY == last_y + 1);
211e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                return false;
212e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            }
213e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        }
214e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        return true;
215e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    }
216e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    return false;
217e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com}
218e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com
219e85a548b33e0471d64a68b246e640770a89ef51dreed@google.comstatic void walk_convex_edges(SkEdge* prevHead, SkPath::FillType,
220e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                              SkBlitter* blitter, int start_y, int stop_y,
221e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                              PrePostProc proc) {
222e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    validate_sort(prevHead->fNext);
223935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
224e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkEdge* leftE = prevHead->fNext;
225e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkEdge* riteE = leftE->fNext;
226e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkEdge* currE = riteE->fNext;
227e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org
228e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#if 0
229e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    int local_top = leftE->fFirstY;
230e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkASSERT(local_top == riteE->fFirstY);
231e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#else
232e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org    // our edge choppers for curves can result in the initial edges
233e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org    // not lining up, so we take the max.
234e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org    int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY);
235e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#endif
236e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    SkASSERT(local_top >= start_y);
237935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
238e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    for (;;) {
239e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(leftE->fFirstY <= stop_y);
240e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(riteE->fFirstY <= stop_y);
241e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com
242e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX &&
243e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                                      leftE->fDX > riteE->fDX)) {
244e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            SkTSwap(leftE, riteE);
245e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        }
246935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
247e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        int local_bot = SkMin32(leftE->fLastY, riteE->fLastY);
248018395ca1906954a256b072777f4d67387a9c853reed@google.com        local_bot = SkMin32(local_bot, stop_y - 1);
249e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(local_top <= local_bot);
250935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
251e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkFixed left = leftE->fX;
252e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkFixed dLeft = leftE->fDX;
253e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkFixed rite = riteE->fX;
254e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkFixed dRite = riteE->fDX;
255e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        int count = local_bot - local_top;
256e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(count >= 0);
257a87977ce51bdb353d85629facb293e634ae39983reed@google.com        if (0 == (dLeft | dRite)) {
25866c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com            int L = SkFixedRoundToInt(left);
25966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com            int R = SkFixedRoundToInt(rite);
260e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            if (L < R) {
261e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                count += 1;
262e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                blitter->blitRect(L, local_top, R - L, count);
263e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                left += count * dLeft;
264e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                rite += count * dRite;
265e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            }
266e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org            local_top = local_bot + 1;
267e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        } else {
268e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            do {
26966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com                int L = SkFixedRoundToInt(left);
27066c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com                int R = SkFixedRoundToInt(rite);
271e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                if (L < R) {
272e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                    blitter->blitH(L, local_top, R - L);
273e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                }
274e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                left += dLeft;
275e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                rite += dRite;
276e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                local_top += 1;
277e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            } while (--count >= 0);
278e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        }
279e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com
280e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        leftE->fX = left;
281e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        riteE->fX = rite;
282e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com
283e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        if (update_edge(leftE, local_bot)) {
284e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            if (currE->fFirstY >= stop_y) {
285e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                break;
286e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            }
287e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            leftE = currE;
288e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            currE = currE->fNext;
289e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        }
290e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        if (update_edge(riteE, local_bot)) {
291e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            if (currE->fFirstY >= stop_y) {
292e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com                break;
293e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            }
294e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            riteE = currE;
295e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com            currE = currE->fNext;
296e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        }
297935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
298e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(leftE);
299e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        SkASSERT(riteE);
300018395ca1906954a256b072777f4d67387a9c853reed@google.com
301018395ca1906954a256b072777f4d67387a9c853reed@google.com        // check our bottom clip
302018395ca1906954a256b072777f4d67387a9c853reed@google.com        SkASSERT(local_top == local_bot + 1);
303018395ca1906954a256b072777f4d67387a9c853reed@google.com        if (local_top >= stop_y) {
304018395ca1906954a256b072777f4d67387a9c853reed@google.com            break;
305018395ca1906954a256b072777f4d67387a9c853reed@google.com        }
306e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    }
307e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com}
308e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// this guy overrides blitH, and will call its proxy blitter with the inverse
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// of the spans it is given (clipped to the left/right of the cliprect)
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// used to implement inverse filltypes on paths
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass InverseBlitter : public SkBlitter {
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic:
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) {
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter = blitter;
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fFirstX = clip.fLeft << shift;
321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fLastX = clip.fRight << shift;
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void prepost(int y, bool isStart) {
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (isStart) {
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fPrevX = fFirstX;
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        } else {
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int invWidth = fLastX - fPrevX;
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (invWidth > 0) {
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fBlitter->blitH(fPrevX, y, invWidth);
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // overrides
335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual void blitH(int x, int y, int width) {
336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int invWidth = x - fPrevX;
337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (invWidth > 0) {
338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fBlitter->blitH(fPrevX, y, invWidth);
339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fPrevX = x + width;
341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
342434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // we do not expect to get called with these entrypoints
344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) {
3452d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("blitAntiH unexpected");
346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) {
3482d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("blitV unexpected");
349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual void blitRect(int x, int y, int width, int height) {
3512d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("blitRect unexpected");
352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual void blitMask(const SkMask&, const SkIRect& clip) {
3542d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("blitMask unexpected");
355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) {
3572d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com        SkDEBUGFAIL("justAnOpaqueColor unexpected");
358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return NULL;
359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
360434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate:
362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkBlitter*  fBlitter;
363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int         fFirstX, fLastX, fPrevX;
364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) {
367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    ((InverseBlitter*)blitter)->prepost(y, isStart);
368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300
373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( pop )
374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
376bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES
377f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.comextern "C" {
378f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    static int edge_compare(const void* a, const void* b) {
379f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        const SkEdge* edgea = *(const SkEdge**)a;
380f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        const SkEdge* edgeb = *(const SkEdge**)b;
381434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
382f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        int valuea = edgea->fFirstY;
383f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        int valueb = edgeb->fFirstY;
384434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
385f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        if (valuea == valueb) {
386f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com            valuea = edgea->fX;
387f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com            valueb = edgeb->fX;
388f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        }
389434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
390f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        // this overflows if valuea >>> valueb or vice-versa
391f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        //     return valuea - valueb;
392f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        // do perform the slower but safe compares
393f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        return (valuea < valueb) ? -1 : (valuea > valueb);
394f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
395f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com}
396bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#else
397bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.comstatic bool operator<(const SkEdge& a, const SkEdge& b) {
398bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    int valuea = a.fFirstY;
399bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    int valueb = b.fFirstY;
400935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
401bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    if (valuea == valueb) {
402bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com        valuea = a.fX;
403bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com        valueb = b.fX;
404bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    }
405935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
406bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    return valuea < valueb;
407bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com}
408bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#endif
409f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
410f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.comstatic SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) {
411bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES
412f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    qsort(list, count, sizeof(SkEdge*), edge_compare);
413bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#else
414bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com    SkTQSort(list, list + count - 1);
415bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#endif
416434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
417f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    // now make the edges linked in sorted order
418f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    for (int i = 1; i < count; i++) {
419f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        list[i - 1]->fNext = list[i];
420f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com        list[i]->fPrev = list[i - 1];
421f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    }
422434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
423f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    *last = list[count - 1];
424f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com    return list[0];
425f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com}
426f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com
427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// clipRect may be null, even though we always have a clip. This indicates that
428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// the path is contained in the clip, and so we can ignore it during the blit
429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//
430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// clipRect (if no null) has already been shifted up
431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//
432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter,
433b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                  int start_y, int stop_y, int shiftEdgesUp,
434b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                  const SkRegion& clipRgn) {
435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(&path && blitter);
436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
437cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    SkEdgeBuilder   builder;
438434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
439cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    int count = builder.build(path, clipRect, shiftEdgesUp);
440cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    SkEdge**    list = builder.edgeList();
441cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com
442b44d151b082d859c467808a843dc01a7118ce5cfreed@android.com    if (count < 2) {
4437d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        if (path.isInverseFillType()) {
44401ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            /*
44501ec0596b2116253ec0d623e2b83efda131fffabreed@google.com             *  Since we are in inverse-fill, our caller has already drawn above
44601ec0596b2116253ec0d623e2b83efda131fffabreed@google.com             *  our top (start_y) and will draw below our bottom (stop_y). Thus
44701ec0596b2116253ec0d623e2b83efda131fffabreed@google.com             *  we need to restrict our drawing to the intersection of the clip
44801ec0596b2116253ec0d623e2b83efda131fffabreed@google.com             *  and those two limits.
44901ec0596b2116253ec0d623e2b83efda131fffabreed@google.com             */
45001ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            SkIRect rect = clipRgn.getBounds();
45101ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            if (rect.fTop < start_y) {
45201ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                rect.fTop = start_y;
45301ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            }
45401ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            if (rect.fBottom > stop_y) {
45501ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                rect.fBottom = stop_y;
45601ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            }
45701ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            if (!rect.isEmpty()) {
45801ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                blitter->blitRect(rect.fLeft << shiftEdgesUp,
45901ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                                  rect.fTop << shiftEdgesUp,
46001ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                                  rect.width() << shiftEdgesUp,
46101ec0596b2116253ec0d623e2b83efda131fffabreed@google.com                                  rect.height() << shiftEdgesUp);
46201ec0596b2116253ec0d623e2b83efda131fffabreed@google.com            }
4637d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org        }
4647d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org
465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
468cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    SkEdge headEdge, tailEdge, *last;
469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // this returns the first and last edge after they're sorted into a dlink list
470cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com    SkEdge* edge = sort_edges(list, count, &last);
471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fPrev = NULL;
473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fNext = edge;
474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fFirstY = kEDGE_HEAD_Y;
475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fX = SK_MinS32;
476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    edge->fPrev = &headEdge;
477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fPrev = last;
479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fNext = NULL;
480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fFirstY = kEDGE_TAIL_Y;
481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    last->fNext = &tailEdge;
482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // now edge is the head of the sorted linklist
484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
485c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    start_y <<= shiftEdgesUp;
486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    stop_y <<= shiftEdgesUp;
487c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    if (clipRect && start_y < clipRect->fTop) {
488c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        start_y = clipRect->fTop;
489c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    }
490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (clipRect && stop_y > clipRect->fBottom) {
491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        stop_y = clipRect->fBottom;
492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    InverseBlitter  ib;
495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    PrePostProc     proc = NULL;
496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (path.isInverseFillType()) {
498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp);
499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter = &ib;
500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        proc = PrePostInverseBlitterProc;
501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
503018395ca1906954a256b072777f4d67387a9c853reed@google.com    if (path.isConvex() && (NULL == proc)) {
504e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL);
505e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    } else {
506e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com        walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc);
507e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com    }
508bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
509bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
510434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.comvoid sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
511bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const SkIRect& cr = clip.getBounds();
512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect tmp;
513434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
514bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fLeft = cr.fLeft;
515bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fRight = cr.fRight;
516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fTop = cr.fTop;
517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fBottom = ir.fTop;
518bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (!tmp.isEmpty()) {
519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter->blitRectRegion(tmp, clip);
520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
521434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com}
522434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
523434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.comvoid sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
524434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com    const SkIRect& cr = clip.getBounds();
525434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com    SkIRect tmp;
526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
527434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com    tmp.fLeft = cr.fLeft;
528434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com    tmp.fRight = cr.fRight;
529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fTop = ir.fBottom;
530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.fBottom = cr.fBottom;
531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (!tmp.isEmpty()) {
532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter->blitRectRegion(tmp, clip);
533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
536b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
5382dad15adc1754325a3cf4dacd02162c39b3259d0reed@google.com/**
5398194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com *  If the caller is drawing an inverse-fill path, then it pass true for
5408194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com *  skipRejectTest, so we don't abort drawing just because the src bounds (ir)
5418194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com *  is outside of the clip.
5422dad15adc1754325a3cf4dacd02162c39b3259d0reed@google.com */
543b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgSkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
5448194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com                             const SkIRect& ir, bool skipRejectTest) {
545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fBlitter = NULL;     // null means blit nothing
546bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fClipRect = NULL;
547bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
548b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org    if (clip) {
549bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fClipRect = &clip->getBounds();
5508194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com        if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return;
552b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        }
553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
554b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        if (clip->isRect()) {
555b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            if (fClipRect->contains(ir)) {
556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fClipRect = NULL;
557b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org            } else {
558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                // only need a wrapper blitter if we're horizontally clipped
559b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org                if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) {
560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    fRectBlitter.init(blitter, *fClipRect);
561bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    blitter = &fRectBlitter;
562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
564b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org        } else {
565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fRgnBlitter.init(blitter, clip);
566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            blitter = &fRgnBlitter;
567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
569bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fBlitter = blitter;
570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
571bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
572bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
573bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
57454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.comstatic bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) {
57554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    const int32_t limit = 32767;
57654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com
57754843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    SkIRect limitR;
57854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    limitR.set(-limit, -limit, limit, limit);
57954843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    if (limitR.contains(orig.getBounds())) {
58054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        return false;
58154843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    }
58254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    reduced->op(orig, limitR, SkRegion::kIntersect_Op);
58354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    return true;
58454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com}
58554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com
58654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.comvoid SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
587bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                      SkBlitter* blitter) {
58854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    if (origClip.isEmpty()) {
589bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
59254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    // Our edges are fixed-point, and don't like the bounds of the clip to
59354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    // exceed that. Here we trim the clip just so we don't overflow later on
59454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    const SkRegion* clipPtr = &origClip;
59554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    SkRegion finiteClip;
59654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    if (clip_to_limit(origClip, &finiteClip)) {
59754843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        if (finiteClip.isEmpty()) {
59854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com            return;
59954843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        }
60054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        clipPtr = &finiteClip;
60154843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com    }
60254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        // don't reference "origClip" any more, just use clipPtr
60354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com
604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect ir;
605155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    path.getBounds().round(&ir);
606bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (ir.isEmpty()) {
607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (path.isInverseFillType()) {
60854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com            blitter->blitRegion(*clipPtr);
609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
611bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
6138194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com    SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType());
614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
615bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    blitter = clipper.getBlitter();
616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (blitter) {
617434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com        // we have to keep our calls to blitter in sorted order, so we
618434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com        // must blit the above section first, then the middle, then the bottom.
619bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (path.isInverseFillType()) {
62054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com            sk_blit_above(blitter, ir, *clipPtr);
621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
62254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com        sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom,
62354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com                     0, *clipPtr);
624434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com        if (path.isInverseFillType()) {
62554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com            sk_blit_below(blitter, ir, *clipPtr);
626434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com        }
627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } else {
628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // what does it mean to not have a blitter if path.isInverseFillType???
629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
63226f5a398c38318eb7eab44f72e024ef784d247fareed@google.comvoid SkScan::FillPath(const SkPath& path, const SkIRect& ir,
63326f5a398c38318eb7eab44f72e024ef784d247fareed@google.com                      SkBlitter* blitter) {
63426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    SkRegion rgn(ir);
63526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    FillPath(path, rgn, blitter);
63626f5a398c38318eb7eab44f72e024ef784d247fareed@google.com}
63726f5a398c38318eb7eab44f72e024ef784d247fareed@google.com
638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int build_tri_edges(SkEdge edge[], const SkPoint pts[],
641bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                           const SkIRect* clipRect, SkEdge* list[]) {
642bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkEdge** start = list;
643434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
644bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (edge->setLine(pts[0], pts[1], clipRect, 0)) {
645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *list++ = edge;
646bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (edge->setLine(pts[1], pts[2], clipRect, 0)) {
649bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *list++ = edge;
650bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
651bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
652bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (edge->setLine(pts[2], pts[0], clipRect, 0)) {
653bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *list++ = edge;
654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (int)(list - start);
656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
657bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
658bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
6592258a80c91fa183971ea3ed987c528e835fe9481reed@android.comstatic void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
6602258a80c91fa183971ea3ed987c528e835fe9481reed@android.com                             SkBlitter* blitter, const SkIRect& ir) {
661bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(pts && blitter);
662434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkEdge edgeStorage[3];
664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkEdge* list[3];
665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
666bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = build_tri_edges(edgeStorage, pts, clipRect, list);
667bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (count < 2) {
668bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
669bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
670bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
671bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkEdge headEdge, tailEdge, *last;
672bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
673bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // this returns the first and last edge after they're sorted into a dlink list
674bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkEdge* edge = sort_edges(list, count, &last);
675434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
676bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fPrev = NULL;
677bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fNext = edge;
678bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fFirstY = kEDGE_HEAD_Y;
679bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    headEdge.fX = SK_MinS32;
680bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    edge->fPrev = &headEdge;
681434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
682bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fPrev = last;
683bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fNext = NULL;
684bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tailEdge.fFirstY = kEDGE_TAIL_Y;
685bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    last->fNext = &tailEdge;
686434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
687bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // now edge is the head of the sorted linklist
688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int stop_y = ir.fBottom;
689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (clipRect && stop_y > clipRect->fBottom) {
690bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        stop_y = clipRect->fBottom;
691bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
692c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    int start_y = ir.fTop;
693c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    if (clipRect && start_y < clipRect->fTop) {
694c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com        start_y = clipRect->fTop;
695c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com    }
696018395ca1906954a256b072777f4d67387a9c853reed@google.com    walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL);
697018395ca1906954a256b072777f4d67387a9c853reed@google.com//    walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL);
698bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
699bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
70026f5a398c38318eb7eab44f72e024ef784d247fareed@google.comvoid SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip,
701bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          SkBlitter* blitter) {
70226f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    if (clip.isEmpty()) {
703bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
704bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
705434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRect  r;
707bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect ir;
708bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    r.set(pts, 3);
709bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    r.round(&ir);
71026f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) {
711bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
712bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
713434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
71426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    SkAAClipBlitterWrapper wrap;
71526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    const SkRegion* clipRgn;
71626f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    if (clip.isBW()) {
71726f5a398c38318eb7eab44f72e024ef784d247fareed@google.com        clipRgn = &clip.bwRgn();
71826f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    } else {
71926f5a398c38318eb7eab44f72e024ef784d247fareed@google.com        wrap.init(clip, blitter);
72026f5a398c38318eb7eab44f72e024ef784d247fareed@google.com        clipRgn = &wrap.getRgn();
72126f5a398c38318eb7eab44f72e024ef784d247fareed@google.com        blitter = wrap.getBlitter();
72226f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    }
723434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com
72426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com    SkScanClipper clipper(blitter, clipRgn, ir);
725bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    blitter = clipper.getBlitter();
726bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (NULL != blitter) {
727bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
728bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
729bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
730