180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScanPriv.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBlitter.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkEdge.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkEdgeBuilder.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkGeometry.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkQuadClipper.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRasterClip.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRegion.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplates.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTSort.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_USE_LEGACY_AA_COVERAGE
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SK_USE_STD_SORT_FOR_EDGES
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define kEDGE_HEAD_Y    SK_MinS32
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define kEDGE_TAIL_Y    SK_MaxS32
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static void validate_sort(const SkEdge* edge) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int y = kEDGE_HEAD_Y;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (edge->fFirstY != SK_MaxS32) {
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            edge->validate();
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(y <= edge->fFirstY);
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            y = edge->fFirstY;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            edge = edge->fNext;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define validate_sort(edge)
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void remove_edge(SkEdge* edge) {
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    edge->fPrev->fNext = edge->fNext;
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    edge->fNext->fPrev = edge->fPrev;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void swap_edges(SkEdge* prev, SkEdge* next) {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(prev->fNext == next && next->fPrev == prev);
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // remove prev from the list
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    prev->fPrev->fNext = next;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    next->fPrev = prev->fPrev;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // insert prev after next
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    prev->fNext = next->fNext;
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    next->fNext->fPrev = prev;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    next->fNext = prev;
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    prev->fPrev = next;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed x = edge->fX;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkEdge* prev = edge->fPrev;
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // add 1 to curr_y since we may have added new edges (built from curves)
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // that start on the next scanline
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(prev && prev->fFirstY <= curr_y + 1);
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (prev->fX <= x) {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        swap_edges(prev, edge);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void insert_new_edges(SkEdge* newEdge, int curr_y) {
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(newEdge->fFirstY >= curr_y);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (newEdge->fFirstY == curr_y) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkEdge* next = newEdge->fNext;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        backward_insert_edge_based_on_x(newEdge  SkPARAM(curr_y));
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        newEdge = next;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void validate_edges_for_y(const SkEdge* edge, int curr_y) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (edge->fFirstY <= curr_y) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(edge->fPrev && edge->fNext);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(edge->fPrev->fNext == edge);
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(edge->fNext->fPrev == edge);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(edge->fFirstY <= edge->fLastY);
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(edge->fPrev->fX <= edge->fX);
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        edge = edge->fNext;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define validate_edges_for_y(edge, curr_y)
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( push )
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( disable : 4701 )
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline);
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define PREPOST_START   true
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define PREPOST_END     false
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void walk_edges(SkEdge* prevHead, SkPath::FillType fillType,
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       SkBlitter* blitter, int start_y, int stop_y,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       PrePostProc proc) {
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    validate_sort(prevHead->fNext);
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int curr_y = start_y;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int windingMask = (fillType & 1) ? 1 : -1;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int     w = 0;
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int     left SK_INIT_TO_AVOID_WARNING;
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool    in_interval = false;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkEdge* currE = prevHead->fNext;
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed prevX = prevHead->fX;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        validate_edges_for_y(currE, curr_y);
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (proc) {
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc(blitter, curr_y, PREPOST_START);    // pre-proc
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (currE->fFirstY <= curr_y) {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(currE->fLastY >= curr_y);
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int x = SkFixedRoundToInt(currE->fX);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            w += currE->fWinding;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((w & windingMask) == 0) { // we finished an interval
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(in_interval);
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int width = x - left;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(width >= 0);
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (width)
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    blitter->blitH(left, curr_y, width);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                in_interval = false;
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (!in_interval) {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                left = x;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                in_interval = true;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkEdge* next = currE->fNext;
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkFixed newX;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (currE->fLastY == curr_y) {    // are we done with this edge?
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (currE->fCurveCount < 0) {
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (((SkCubicEdge*)currE)->updateCubic()) {
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkASSERT(currE->fFirstY == curr_y + 1);
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        newX = currE->fX;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        goto NEXT_X;
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else if (currE->fCurveCount > 0) {
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (((SkQuadraticEdge*)currE)->updateQuadratic()) {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        newX = currE->fX;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        goto NEXT_X;
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                remove_edge(currE);
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(currE->fLastY > curr_y);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                newX = currE->fX + currE->fDX;
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                currE->fX = newX;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            NEXT_X:
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (newX < prevX) { // ripple currE backwards until it is x-sorted
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    backward_insert_edge_based_on_x(currE  SkPARAM(curr_y));
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    prevX = newX;
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            currE = next;
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(currE);
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (proc) {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc(blitter, curr_y, PREPOST_END);    // post-proc
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        curr_y += 1;
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (curr_y >= stop_y) {
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // now currE points to the first edge with a Yint larger than curr_y
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        insert_new_edges(currE, curr_y);
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// return true if we're done with this edge
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool update_edge(SkEdge* edge, int last_y) {
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(edge->fLastY >= last_y);
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (last_y == edge->fLastY) {
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (edge->fCurveCount < 0) {
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (((SkCubicEdge*)edge)->updateCubic()) {
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(edge->fFirstY == last_y + 1);
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (edge->fCurveCount > 0) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (((SkQuadraticEdge*)edge)->updateQuadratic()) {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(edge->fFirstY == last_y + 1);
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void walk_convex_edges(SkEdge* prevHead, SkPath::FillType,
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              SkBlitter* blitter, int start_y, int stop_y,
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              PrePostProc proc) {
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    validate_sort(prevHead->fNext);
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* leftE = prevHead->fNext;
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* riteE = leftE->fNext;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* currE = riteE->fNext;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int local_top = leftE->fFirstY;
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(local_top == riteE->fFirstY);
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // our edge choppers for curves can result in the initial edges
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // not lining up, so we take the max.
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY);
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(local_top >= start_y);
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(leftE->fFirstY <= stop_y);
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(riteE->fFirstY <= stop_y);
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX &&
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      leftE->fDX > riteE->fDX)) {
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTSwap(leftE, riteE);
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int local_bot = SkMin32(leftE->fLastY, riteE->fLastY);
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        local_bot = SkMin32(local_bot, stop_y - 1);
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(local_top <= local_bot);
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed left = leftE->fX;
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed dLeft = leftE->fDX;
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed rite = riteE->fX;
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed dRite = riteE->fDX;
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int count = local_bot - local_top;
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(count >= 0);
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == (dLeft | dRite)) {
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int L = SkFixedRoundToInt(left);
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int R = SkFixedRoundToInt(rite);
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (L < R) {
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                count += 1;
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                blitter->blitRect(L, local_top, R - L, count);
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                left += count * dLeft;
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rite += count * dRite;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            local_top = local_bot + 1;
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int L = SkFixedRoundToInt(left);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int R = SkFixedRoundToInt(rite);
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (L < R) {
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    blitter->blitH(L, local_top, R - L);
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                left += dLeft;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rite += dRite;
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                local_top += 1;
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (--count >= 0);
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        leftE->fX = left;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        riteE->fX = rite;
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (update_edge(leftE, local_bot)) {
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (currE->fFirstY >= stop_y) {
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            leftE = currE;
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            currE = currE->fNext;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (update_edge(riteE, local_bot)) {
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (currE->fFirstY >= stop_y) {
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            riteE = currE;
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            currE = currE->fNext;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(leftE);
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(riteE);
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // check our bottom clip
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(local_top == local_bot + 1);
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (local_top >= stop_y) {
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this guy overrides blitH, and will call its proxy blitter with the inverse
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// of the spans it is given (clipped to the left/right of the cliprect)
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// used to implement inverse filltypes on paths
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass InverseBlitter : public SkBlitter {
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) {
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter = blitter;
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFirstX = clip.fLeft << shift;
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLastX = clip.fRight << shift;
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void prepost(int y, bool isStart) {
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (isStart) {
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fPrevX = fFirstX;
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int invWidth = fLastX - fPrevX;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (invWidth > 0) {
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBlitter->blitH(fPrevX, y, invWidth);
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // overrides
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitH(int x, int y, int width) {
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int invWidth = x - fPrevX;
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (invWidth > 0) {
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBlitter->blitH(fPrevX, y, invWidth);
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPrevX = x + width;
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we do not expect to get called with these entrypoints
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) {
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("blitAntiH unexpected");
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitV(int x, int y, int height, SkAlpha alpha) {
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("blitV unexpected");
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitRect(int x, int y, int width, int height) {
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("blitRect unexpected");
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitMask(const SkMask&, const SkIRect& clip) {
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("blitMask unexpected");
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) {
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGFAIL("justAnOpaqueColor unexpected");
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBlitter*  fBlitter;
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int         fFirstX, fLastX, fPrevX;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) {
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((InverseBlitter*)blitter)->prepost(y, isStart);
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined _WIN32 && _MSC_VER >= 1300
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma warning ( pop )
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_USE_STD_SORT_FOR_EDGES
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruextern "C" {
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int edge_compare(const void* a, const void* b) {
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkEdge* edgea = *(const SkEdge**)a;
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkEdge* edgeb = *(const SkEdge**)b;
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int valuea = edgea->fFirstY;
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int valueb = edgeb->fFirstY;
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (valuea == valueb) {
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            valuea = edgea->fX;
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            valueb = edgeb->fX;
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // this overflows if valuea >>> valueb or vice-versa
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        //     return valuea - valueb;
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // do perform the slower but safe compares
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (valuea < valueb) ? -1 : (valuea > valueb);
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool operator<(const SkEdge& a, const SkEdge& b) {
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int valuea = a.fFirstY;
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int valueb = b.fFirstY;
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (valuea == valueb) {
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        valuea = a.fX;
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        valueb = b.fX;
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return valuea < valueb;
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) {
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_USE_STD_SORT_FOR_EDGES
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    qsort(list, count, sizeof(SkEdge*), edge_compare);
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTQSort(list, list + count - 1);
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now make the edges linked in sorted order
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 1; i < count; i++) {
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        list[i - 1]->fNext = list[i];
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        list[i]->fPrev = list[i - 1];
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *last = list[count - 1];
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return list[0];
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// clipRect may be null, even though we always have a clip. This indicates that
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// the path is contained in the clip, and so we can ignore it during the blit
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// clipRect (if no null) has already been shifted up
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter,
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  int start_y, int stop_y, int shiftEdgesUp,
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  const SkRegion& clipRgn) {
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(&path && blitter);
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdgeBuilder   builder;
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = builder.build(path, clipRect, shiftEdgesUp);
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge**    list = builder.edgeList();
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count < 2) {
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (path.isInverseFillType()) {
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            /*
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             *  Since we are in inverse-fill, our caller has already drawn above
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             *  our top (start_y) and will draw below our bottom (stop_y). Thus
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             *  we need to restrict our drawing to the intersection of the clip
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             *  and those two limits.
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             */
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkIRect rect = clipRgn.getBounds();
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (rect.fTop < start_y) {
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rect.fTop = start_y;
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (rect.fBottom > stop_y) {
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rect.fBottom = stop_y;
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (!rect.isEmpty()) {
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                blitter->blitRect(rect.fLeft << shiftEdgesUp,
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  rect.fTop << shiftEdgesUp,
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  rect.width() << shiftEdgesUp,
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  rect.height() << shiftEdgesUp);
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge headEdge, tailEdge, *last;
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this returns the first and last edge after they're sorted into a dlink list
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* edge = sort_edges(list, count, &last);
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fPrev = NULL;
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fNext = edge;
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fFirstY = kEDGE_HEAD_Y;
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fX = SK_MinS32;
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    edge->fPrev = &headEdge;
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fPrev = last;
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fNext = NULL;
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fFirstY = kEDGE_TAIL_Y;
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    last->fNext = &tailEdge;
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now edge is the head of the sorted linklist
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    start_y <<= shiftEdgesUp;
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stop_y <<= shiftEdgesUp;
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clipRect && start_y < clipRect->fTop) {
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        start_y = clipRect->fTop;
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clipRect && stop_y > clipRect->fBottom) {
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stop_y = clipRect->fBottom;
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    InverseBlitter  ib;
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    PrePostProc     proc = NULL;
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (path.isInverseFillType()) {
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp);
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter = &ib;
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        proc = PrePostInverseBlitterProc;
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (path.isConvex() && (NULL == proc)) {
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL);
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc);
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkIRect& cr = clip.getBounds();
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect tmp;
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fLeft = cr.fLeft;
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fRight = cr.fRight;
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fTop = cr.fTop;
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fBottom = ir.fTop;
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!tmp.isEmpty()) {
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter->blitRectRegion(tmp, clip);
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkIRect& cr = clip.getBounds();
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect tmp;
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fLeft = cr.fLeft;
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fRight = cr.fRight;
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fTop = ir.fBottom;
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tmp.fBottom = cr.fBottom;
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!tmp.isEmpty()) {
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter->blitRectRegion(tmp, clip);
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  If the caller is drawing an inverse-fill path, then it pass true for
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  skipRejectTest, so we don't abort drawing just because the src bounds (ir)
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  is outside of the clip.
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkIRect& ir, bool skipRejectTest) {
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBlitter = NULL;     // null means blit nothing
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClipRect = NULL;
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip) {
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fClipRect = &clip->getBounds();
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (clip->isRect()) {
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fClipRect->contains(ir)) {
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fClipRect = NULL;
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // only need a wrapper blitter if we're horizontally clipped
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) {
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fRectBlitter.init(blitter, *fClipRect);
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    blitter = &fRectBlitter;
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRgnBlitter.init(blitter, clip);
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter = &fRgnBlitter;
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBlitter = blitter;
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) {
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int32_t limit = 32767;
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect limitR;
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    limitR.set(-limit, -limit, limit, limit);
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (limitR.contains(orig.getBounds())) {
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reduced->op(orig, limitR, SkRegion::kIntersect_Op);
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkBlitter* blitter) {
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (origClip.isEmpty()) {
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Our edges are fixed-point, and don't like the bounds of the clip to
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // exceed that. Here we trim the clip just so we don't overflow later on
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkRegion* clipPtr = &origClip;
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion finiteClip;
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip_to_limit(origClip, &finiteClip)) {
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (finiteClip.isEmpty()) {
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipPtr = &finiteClip;
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // don't reference "origClip" any more, just use clipPtr
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect ir;
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path.getBounds().round(&ir);
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ir.isEmpty()) {
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (path.isInverseFillType()) {
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter->blitRegion(*clipPtr);
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType());
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    blitter = clipper.getBlitter();
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (blitter) {
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // we have to keep our calls to blitter in sorted order, so we
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // must blit the above section first, then the middle, then the bottom.
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (path.isInverseFillType()) {
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_blit_above(blitter, ir, *clipPtr);
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom,
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     0, *clipPtr);
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (path.isInverseFillType()) {
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_blit_below(blitter, ir, *clipPtr);
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // what does it mean to not have a blitter if path.isInverseFillType???
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScan::FillPath(const SkPath& path, const SkIRect& ir,
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkBlitter* blitter) {
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion rgn(ir);
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FillPath(path, rgn, blitter);
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int build_tri_edges(SkEdge edge[], const SkPoint pts[],
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkIRect* clipRect, SkEdge* list[]) {
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge** start = list;
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (edge->setLine(pts[0], pts[1], clipRect, 0)) {
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *list++ = edge;
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (edge->setLine(pts[1], pts[2], clipRect, 0)) {
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *list++ = edge;
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (edge->setLine(pts[2], pts[0], clipRect, 0)) {
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *list++ = edge;
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (int)(list - start);
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             SkBlitter* blitter, const SkIRect& ir) {
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(pts && blitter);
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge edgeStorage[3];
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* list[3];
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = build_tri_edges(edgeStorage, pts, clipRect, list);
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count < 2) {
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge headEdge, tailEdge, *last;
67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this returns the first and last edge after they're sorted into a dlink list
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkEdge* edge = sort_edges(list, count, &last);
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fPrev = NULL;
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fNext = edge;
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fFirstY = kEDGE_HEAD_Y;
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    headEdge.fX = SK_MinS32;
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    edge->fPrev = &headEdge;
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fPrev = last;
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fNext = NULL;
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tailEdge.fFirstY = kEDGE_TAIL_Y;
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    last->fNext = &tailEdge;
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now edge is the head of the sorted linklist
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int stop_y = ir.fBottom;
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clipRect && stop_y > clipRect->fBottom) {
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stop_y = clipRect->fBottom;
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int start_y = ir.fTop;
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clipRect && start_y < clipRect->fTop) {
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        start_y = clipRect->fTop;
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL);
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL);
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip,
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          SkBlitter* blitter) {
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip.isEmpty()) {
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect  r;
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect ir;
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r.set(pts, 3);
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r.round(&ir);
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) {
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAAClipBlitterWrapper wrap;
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkRegion* clipRgn;
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip.isBW()) {
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipRgn = &clip.bwRgn();
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        wrap.init(clip, blitter);
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipRgn = &wrap.getRgn();
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter = wrap.getBlitter();
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScanClipper clipper(blitter, clipRgn, ir);
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    blitter = clipper.getBlitter();
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != blitter) {
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
730