1d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/*
2d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Copyright 2015 Google Inc.
3d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
4d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Use of this source code is governed by a BSD-style license that can be
5d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * found in the LICENSE file.
6d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
7d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrTessellatingPathRenderer.h"
9d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
109ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco#include "GrBatch.h"
119ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco#include "GrBatchTarget.h"
122fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt#include "GrBatchTest.h"
13d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrDefaultGeoProcFactory.h"
14d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrPathUtils.h"
15cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon#include "GrVertices.h"
16d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "SkChunkAlloc.h"
17d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "SkGeometry.h"
18d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
19d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include <stdio.h>
20d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
21d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/*
22d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * This path renderer tessellates the path into triangles, uploads the triangles to a
23d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * vertex buffer, and renders them with a single draw call. It does not currently do
24d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * antialiasing, so it must be used in conjunction with multisampling.
25d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
26d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * There are six stages to the algorithm:
27d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
28d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
29d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 2) Build a mesh of edges connecting the vertices (build_edges()).
30d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
31d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
32d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
33d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
34d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
35d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
36d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * of vertices (and the necessity of inserting new vertices on intersection).
37d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
38d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Stages (4) and (5) use an active edge list, which a list of all edges for which the
39d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * sweep line has crossed the top vertex, but not the bottom vertex.  It's sorted
40d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * left-to-right based on the point where both edges are active (when both top vertices
41d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * have been seen, so the "lower" top vertex of the two). If the top vertices are equal
42d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * (shared), it's sorted based on the last point where both edges are active, so the
43d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * "upper" bottom vertex.
44d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
45d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * The most complex step is the simplification (4). It's based on the Bentley-Ottman
46d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
47d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * not exact and may violate the mesh topology or active edge list ordering. We
48d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * accommodate this by adjusting the topology of the mesh and AEL to match the intersection
49d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * points. This occurs in three ways:
50d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
51d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * A) Intersections may cause a shortened edge to no longer be ordered with respect to its
52d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    neighbouring edges at the top or bottom vertex. This is handled by merging the
53d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    edges (merge_collinear_edges()).
54d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * B) Intersections may cause an edge to violate the left-to-right ordering of the
55d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    active edge list. This is handled by splitting the neighbour edge on the
56d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    intersected vertex (cleanup_active_edges()).
57d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * C) Shortening an edge may cause an active edge to become inactive or an inactive edge
58d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    to become active. This is handled by removing or inserting the edge in the active
59d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *    edge list (fix_active_state()).
60d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
61d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
62d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
63d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
64d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and removal also
65d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
66d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * insertions and removals was greater than the cost of infrequent O(N) lookups with the
67d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * linked list implementation. With the latter, all removals are O(1), and most insertions
68d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * are O(1), since we know the adjacent edge in the active edge list based on the topology.
69d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
70d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * frequent. There may be other data structures worth investigating, however.
71d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
726bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
736bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
746bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
756bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
766bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * that the "left" and "right" orientation in the code remains correct (edges to the left are
776bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
786bd5137e11071116fe279e2f26264f01baeff1aasenorblanco * degrees counterclockwise, rather that transposing.
79d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
80d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#define LOGGING_ENABLED 0
81d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#define WIREFRAME 0
82d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
83d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
84d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#define LOG printf
85d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#else
86d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#define LOG(...)
87d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
88d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
89d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#define ALLOC_NEW(Type, args, alloc) \
90d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkNEW_PLACEMENT_ARGS(alloc.allocThrow(sizeof(Type)), Type, args)
91d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
92d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanconamespace {
93d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
94d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Vertex;
95d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Edge;
96d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Poly;
97d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
98d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancotemplate <class T, T* T::*Prev, T* T::*Next>
99d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid insert(T* t, T* prev, T* next, T** head, T** tail) {
100d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    t->*Prev = prev;
101d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    t->*Next = next;
102d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (prev) {
103d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev->*Next = t;
104d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (head) {
105d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *head = t;
106d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
107d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (next) {
108d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        next->*Prev = t;
109d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (tail) {
110d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *tail = t;
111d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
112d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
113d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
114d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancotemplate <class T, T* T::*Prev, T* T::*Next>
115d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid remove(T* t, T** head, T** tail) {
116d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (t->*Prev) {
117d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        t->*Prev->*Next = t->*Next;
118d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (head) {
119d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *head = t->*Next;
120d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
121d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (t->*Next) {
122d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        t->*Next->*Prev = t->*Prev;
123d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (tail) {
124d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *tail = t->*Prev;
125d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
126d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    t->*Prev = t->*Next = NULL;
127d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
128d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
129d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/**
130d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Vertices are used in three ways: first, the path contours are converted into a
131d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
132d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * are re-ordered by the merge sort according to the sweep_lt comparator (usually, increasing
133d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
134d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
135d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePolys, since
136d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * an individual Vertex from the path mesh may belong to multiple
137d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * MonotonePolys, so the original Vertices cannot be re-used.
138d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
139d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
140d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Vertex {
141d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco  Vertex(const SkPoint& point)
142d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    : fPoint(point), fPrev(NULL), fNext(NULL)
143d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    , fFirstEdgeAbove(NULL), fLastEdgeAbove(NULL)
144d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    , fFirstEdgeBelow(NULL), fLastEdgeBelow(NULL)
145d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    , fProcessed(false)
146d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
147d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    , fID (-1.0f)
148d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
149d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    {}
150d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkPoint fPoint;           // Vertex position
151d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* fPrev;            // Linked list of contours, then Y-sorted vertices.
152d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* fNext;            // "
153d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*   fFirstEdgeAbove;  // Linked list of edges above this vertex.
154d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*   fLastEdgeAbove;   // "
155d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*   fFirstEdgeBelow;  // Linked list of edges below this vertex.
156d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*   fLastEdgeBelow;   // "
157d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    bool    fProcessed;       // Has this vertex been seen in simplify()?
158d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
159d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    float   fID;              // Identifier used for logging.
160d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
161d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco};
162d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
163d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/***************************************************************************************/
164d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1656bd5137e11071116fe279e2f26264f01baeff1aasenorblancotypedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
1666bd5137e11071116fe279e2f26264f01baeff1aasenorblanco
1676bd5137e11071116fe279e2f26264f01baeff1aasenorblancostruct Comparator {
1686bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    CompareFunc sweep_lt;
1696bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    CompareFunc sweep_gt;
1706bd5137e11071116fe279e2f26264f01baeff1aasenorblanco};
1716bd5137e11071116fe279e2f26264f01baeff1aasenorblanco
1726bd5137e11071116fe279e2f26264f01baeff1aasenorblancobool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
173d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX;
1746bd5137e11071116fe279e2f26264f01baeff1aasenorblanco}
1756bd5137e11071116fe279e2f26264f01baeff1aasenorblanco
1766bd5137e11071116fe279e2f26264f01baeff1aasenorblancobool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
177d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY;
178d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
179d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1806bd5137e11071116fe279e2f26264f01baeff1aasenorblancobool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) {
181d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX;
1826bd5137e11071116fe279e2f26264f01baeff1aasenorblanco}
1836bd5137e11071116fe279e2f26264f01baeff1aasenorblanco
1846bd5137e11071116fe279e2f26264f01baeff1aasenorblancobool sweep_gt_vert(const SkPoint& a, const SkPoint& b) {
185d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
186d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
187d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
188d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblancoinline SkPoint* emit_vertex(Vertex* v, SkPoint* data) {
189d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco    *data++ = v->fPoint;
190d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco    return data;
191d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
192d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
193d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblancoSkPoint* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, SkPoint* data) {
194d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if WIREFRAME
195d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v0, data);
196d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v1, data);
197d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v1, data);
198d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v2, data);
199d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v2, data);
200d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v0, data);
201d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#else
202d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v0, data);
203d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v1, data);
204d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    data = emit_vertex(v2, data);
205d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
206d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return data;
207d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
208d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
2095b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancostruct EdgeList {
2105b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    EdgeList() : fHead(NULL), fTail(NULL) {}
2115b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    Edge* fHead;
2125b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    Edge* fTail;
2135b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco};
2145b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco
215d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/**
216d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
217d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
218d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
219d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * point). For speed, that case is only tested by the callers which require it (e.g.,
220d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * cleanup_active_edges()). Edges also handle checking for intersection with other edges.
221d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Currently, this converts the edges to the parametric form, in order to avoid doing a division
222d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * until an intersection has been confirmed. This is slightly slower in the "found" case, but
223d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * a lot faster in the "not found" case.
224d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
225d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * The coefficients of the line equation stored in double precision to avoid catastrphic
226d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
227d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * correct in float, since it's a polynomial of degree 2. The intersect() function, being
228d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * degree 5, is still subject to catastrophic cancellation. We deal with that by assuming its
229d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * output may be incorrect, and adjusting the mesh topology to match (see comment at the top of
230d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * this file).
231d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
232d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
233d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Edge {
234d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge(Vertex* top, Vertex* bottom, int winding)
235d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        : fWinding(winding)
236d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fTop(top)
237d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fBottom(bottom)
238d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fLeft(NULL)
239d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fRight(NULL)
240d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fPrevEdgeAbove(NULL)
241d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fNextEdgeAbove(NULL)
242d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fPrevEdgeBelow(NULL)
243d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fNextEdgeBelow(NULL)
244d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fLeftPoly(NULL)
245d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fRightPoly(NULL) {
246d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            recompute();
247d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
248d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    int      fWinding;          // 1 == edge goes downward; -1 = edge goes upward.
249d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex*  fTop;              // The top vertex in vertex-sort-order (sweep_lt).
250d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex*  fBottom;           // The bottom vertex in vertex-sort-order.
251d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fLeft;             // The linked list of edges in the active edge list.
252d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fRight;            // "
253d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fPrevEdgeAbove;    // The linked list of edges in the bottom Vertex's "edges above".
254d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fNextEdgeAbove;    // "
255d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fPrevEdgeBelow;    // The linked list of edges in the top Vertex's "edges below".
256d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge*    fNextEdgeBelow;    // "
257d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly*    fLeftPoly;         // The Poly to the left of this edge, if any.
258d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly*    fRightPoly;        // The Poly to the right of this edge, if any.
259d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    double   fDX;               // The line equation for this edge, in implicit form.
260d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    double   fDY;               // fDY * x + fDX * y + fC = 0, for point (x, y) on the line.
261d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    double   fC;
262d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    double dist(const SkPoint& p) const {
263d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return fDY * p.fX - fDX * p.fY + fC;
264d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
265d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    bool isRightOf(Vertex* v) const {
266d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return dist(v->fPoint) < 0.0;
267d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
268d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    bool isLeftOf(Vertex* v) const {
269d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return dist(v->fPoint) > 0.0;
270d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
271d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    void recompute() {
272d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX;
273d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY;
274d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX -
275d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco             static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY;
276d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
277d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    bool intersect(const Edge& other, SkPoint* p) {
278d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("intersecting %g -> %g with %g -> %g\n",
279d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco               fTop->fID, fBottom->fID,
280d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco               other.fTop->fID, other.fBottom->fID);
281d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (fTop == other.fTop || fBottom == other.fBottom) {
282d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return false;
283d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
284d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double denom = fDX * other.fDY - fDY * other.fDX;
285d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (denom == 0.0) {
286d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return false;
287d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
288d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX;
289d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY;
290d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double sNumer = dy * other.fDX - dx * other.fDY;
291d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double tNumer = dy * fDX - dx * fDY;
292d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
293d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        // This saves us doing the divide below unless absolutely necessary.
294d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
295d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
296d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return false;
297d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
298d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        double s = sNumer / denom;
299d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        SkASSERT(s >= 0.0 && s <= 1.0);
300d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX);
301d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY);
302d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return true;
303d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
3045b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    bool isActive(EdgeList* activeEdges) const {
3055b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        return activeEdges && (fLeft || fRight || activeEdges->fHead == this);
306d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
307d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco};
308d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
309d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/***************************************************************************************/
310d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
311d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancostruct Poly {
312d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly(int winding)
313d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        : fWinding(winding)
314d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fHead(NULL)
315d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fTail(NULL)
316d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fActive(NULL)
317d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fNext(NULL)
318d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fPartner(NULL)
319d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        , fCount(0)
320d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    {
321d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
322d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        static int gID = 0;
323d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fID = gID++;
324d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("*** created Poly %d\n", fID);
325d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
326d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
327d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side;
328d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    struct MonotonePoly {
329d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        MonotonePoly()
330d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            : fSide(kNeither_Side)
331d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            , fHead(NULL)
332d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            , fTail(NULL)
333d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            , fPrev(NULL)
334d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            , fNext(NULL) {}
335d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Side          fSide;
336d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex*       fHead;
337d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex*       fTail;
338d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        MonotonePoly* fPrev;
339d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        MonotonePoly* fNext;
340d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
341d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc);
342d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            bool done = false;
343d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (fSide == kNeither_Side) {
344d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fSide = side;
345d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
346d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                done = side != fSide;
347d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
348d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (fHead == NULL) {
349d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fHead = fTail = newV;
350d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else if (fSide == kRight_Side) {
351d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                newV->fPrev = fTail;
352d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fTail->fNext = newV;
353d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fTail = newV;
354d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
355d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                newV->fNext = fHead;
356d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fHead->fPrev = newV;
357d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fHead = newV;
358d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
359d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return done;
360d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
361d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
362d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        SkPoint* emit(SkPoint* data) {
363d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* first = fHead;
364d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* v = first->fNext;
365d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            while (v != fTail) {
366d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                SkASSERT(v && v->fPrev && v->fNext);
367d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Vertex* prev = v->fPrev;
368d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Vertex* curr = v;
369d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Vertex* next = v->fNext;
370d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
371d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
372d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
373d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
374d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (ax * by - ay * bx >= 0.0) {
375d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    data = emit_triangle(prev, curr, next, data);
376d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    v->fPrev->fNext = v->fNext;
377d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    v->fNext->fPrev = v->fPrev;
378d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    if (v->fPrev == first) {
379d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        v = v->fNext;
380d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    } else {
381d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        v = v->fPrev;
382d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
383d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                } else {
384d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    v = v->fNext;
385d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
386d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
387d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return data;
388d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
389d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    };
390d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
391d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoint.fX, v->fPoint.fY,
392d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco               side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "neither");
393d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Poly* partner = fPartner;
394d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Poly* poly = this;
395d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (partner) {
396d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            fPartner = partner->fPartner = NULL;
397d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
398d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (!fActive) {
399d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            fActive = ALLOC_NEW(MonotonePoly, (), alloc);
400d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
401d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (fActive->addVertex(v, side, alloc)) {
402d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (fTail) {
403d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fActive->fPrev = fTail;
404d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fTail->fNext = fActive;
405d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fTail = fActive;
406d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
407d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fHead = fTail = fActive;
408d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
409d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (partner) {
410d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                partner->addVertex(v, side, alloc);
411d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                poly = partner;
412d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
413d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Vertex* prev = fActive->fSide == Poly::kLeft_Side ?
414d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                               fActive->fHead->fNext : fActive->fTail->fPrev;
415d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fActive = ALLOC_NEW(MonotonePoly, , alloc);
416d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fActive->addVertex(prev, Poly::kNeither_Side, alloc);
417d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fActive->addVertex(v, side, alloc);
418d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
419d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
420d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fCount++;
421d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return poly;
422d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
423d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    void end(Vertex* v, SkChunkAlloc& alloc) {
424d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY);
425d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (fPartner) {
426d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            fPartner = fPartner->fPartner = NULL;
427d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
428d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, alloc);
429d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
430d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco    SkPoint* emit(SkPoint *data) {
431d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (fCount < 3) {
432d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return data;
433d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
434d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("emit() %d, size %d\n", fID, fCount);
435d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (MonotonePoly* m = fHead; m != NULL; m = m->fNext) {
436d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            data = m->emit(data);
437d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
438d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return data;
439d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
440d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    int fWinding;
441d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    MonotonePoly* fHead;
442d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    MonotonePoly* fTail;
443d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    MonotonePoly* fActive;
444d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly* fNext;
445d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly* fPartner;
446d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    int fCount;
447d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
448d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    int fID;
449d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
450d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco};
451d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
452d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/***************************************************************************************/
453d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
454d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancobool coincident(const SkPoint& a, const SkPoint& b) {
455d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return a == b;
456d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
457d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
458d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoPoly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) {
459d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly* poly = ALLOC_NEW(Poly, (winding), alloc);
460d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    poly->addVertex(v, Poly::kNeither_Side, alloc);
461d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    poly->fNext = *head;
462d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    *head = poly;
463d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return poly;
464d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
465d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
466d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoVertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head,
467d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                SkChunkAlloc& alloc) {
468d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* v = ALLOC_NEW(Vertex, (p), alloc);
469d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
470d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    static float gID = 0.0f;
471d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    v->fID = gID++;
472d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
473d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (prev) {
474d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev->fNext = v;
475d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        v->fPrev = prev;
476d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else {
477d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *head = v;
478d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
479d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return v;
480d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
481d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
482d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoVertex* generate_quadratic_points(const SkPoint& p0,
483d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  const SkPoint& p1,
484d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  const SkPoint& p2,
485d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  SkScalar tolSqd,
486d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  Vertex* prev,
487d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  Vertex** head,
488d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  int pointsLeft,
489d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                  SkChunkAlloc& alloc) {
490d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2);
491d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) {
492d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return append_point_to_contour(p2, prev, head, alloc);
493d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
494d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
495d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const SkPoint q[] = {
496d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
497d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
498d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    };
499d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) };
500d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
501d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    pointsLeft >>= 1;
502d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft, alloc);
503d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft, alloc);
504d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return prev;
505d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
506d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
507d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoVertex* generate_cubic_points(const SkPoint& p0,
508d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              const SkPoint& p1,
509d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              const SkPoint& p2,
510d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              const SkPoint& p3,
511d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              SkScalar tolSqd,
512d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              Vertex* prev,
513d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              Vertex** head,
514d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              int pointsLeft,
515d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                              SkChunkAlloc& alloc) {
516d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3);
517d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3);
518d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
519d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
520d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return append_point_to_contour(p3, prev, head, alloc);
521d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
522d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const SkPoint q[] = {
523d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
524d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
525d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
526d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    };
527d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const SkPoint r[] = {
528d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
529d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
530d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    };
531d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
532d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    pointsLeft >>= 1;
533d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLeft, alloc);
534d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLeft, alloc);
535d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return prev;
536d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
537d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
538d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
539d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
540d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
541d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                      Vertex** contours, SkChunkAlloc& alloc) {
542d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
543d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkScalar toleranceSqd = tolerance * tolerance;
544d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
545d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkPoint pts[4];
546d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    bool done = false;
547d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkPath::Iter iter(path, false);
548d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* prev = NULL;
549d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* head = NULL;
550d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (path.isInverseFillType()) {
551d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        SkPoint quad[4];
552d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        clipBounds.toQuad(quad);
553d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (int i = 3; i >= 0; i--) {
554d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            prev = append_point_to_contour(quad[i], prev, &head, alloc);
555d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
556d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        head->fPrev = prev;
557d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev->fNext = head;
558d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *contours++ = head;
559d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        head = prev = NULL;
560d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
561d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkAutoConicToQuads converter;
562d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    while (!done) {
563d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        SkPath::Verb verb = iter.next(pts);
564d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        switch (verb) {
565d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kConic_Verb: {
566d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                SkScalar weight = iter.conicWeight();
567d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
568d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                for (int i = 0; i < converter.countQuads(); ++i) {
5696d88bdb6f1408ec9861ee1306a026e15c5bacc9csenorblanco                    int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, tolerance);
570d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    prev = generate_quadratic_points(quadPts[0], quadPts[1], quadPts[2],
571d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                                     toleranceSqd, prev, &head, pointsLeft, alloc);
572d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    quadPts += 2;
573d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
574d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
575d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
576d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kMove_Verb:
577d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (head) {
578d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    head->fPrev = prev;
579d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    prev->fNext = head;
580d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    *contours++ = head;
581d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
582d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                head = prev = NULL;
583d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prev = append_point_to_contour(pts[0], prev, &head, alloc);
584d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
585d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kLine_Verb: {
586d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prev = append_point_to_contour(pts[1], prev, &head, alloc);
587d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
588d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
589d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kQuad_Verb: {
5906d88bdb6f1408ec9861ee1306a026e15c5bacc9csenorblanco                int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance);
591d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleranceSqd, prev,
592d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                                 &head, pointsLeft, alloc);
593d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
594d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
595d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kCubic_Verb: {
5966d88bdb6f1408ec9861ee1306a026e15c5bacc9csenorblanco                int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
597d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
598d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                toleranceSqd, prev, &head, pointsLeft, alloc);
599d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
600d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
601d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kClose_Verb:
602d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (head) {
603d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    head->fPrev = prev;
604d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    prev->fNext = head;
605d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    *contours++ = head;
606d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
607d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                head = prev = NULL;
608d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
609d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            case SkPath::kDone_Verb:
610d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (head) {
611d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    head->fPrev = prev;
612d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    prev->fNext = head;
613d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    *contours++ = head;
614d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
615d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                done = true;
616d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                break;
617d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
618d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
619d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
620d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
621d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoinline bool apply_fill_type(SkPath::FillType fillType, int winding) {
622d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    switch (fillType) {
623d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        case SkPath::kWinding_FillType:
624d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return winding != 0;
625d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        case SkPath::kEvenOdd_FillType:
626d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return (winding & 1) != 0;
627d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        case SkPath::kInverseWinding_FillType:
628d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return winding == 1;
629d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        case SkPath::kInverseEvenOdd_FillType:
630d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return (winding & 1) == 1;
631d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        default:
632d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            SkASSERT(false);
633d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            return false;
634d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
635d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
636d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6376bd5137e11071116fe279e2f26264f01baeff1aasenorblancoEdge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) {
6386bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
639d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* top = winding < 0 ? next : prev;
640d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* bottom = winding < 0 ? prev : next;
641d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
642d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
643d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6445b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid remove_edge(Edge* edge, EdgeList* edges) {
645d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
6465b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    SkASSERT(edge->isActive(edges));
6475b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges->fTail);
648d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
649d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6505b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
651d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
6525b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    SkASSERT(!edge->isActive(edges));
6535b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    Edge* next = prev ? prev->fRight : edges->fHead;
6545b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHead, &edges->fTail);
655d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
656d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6575b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
658d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (v->fFirstEdgeAbove) {
659d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *left = v->fFirstEdgeAbove->fLeft;
660d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *right = v->fLastEdgeAbove->fRight;
661d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return;
662d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
6635b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    Edge* next = NULL;
6645b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    Edge* prev;
6655b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    for (prev = edges->fTail; prev != NULL; prev = prev->fLeft) {
6665b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        if (prev->isLeftOf(v)) {
667d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            break;
668d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
6695b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        next = prev;
670d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
671d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    *left = prev;
672d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    *right = next;
673d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return;
674d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
675d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6765b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid find_enclosing_edges(Edge* edge, EdgeList* edges, Comparator& c, Edge** left, Edge** right) {
677d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* prev = NULL;
678d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* next;
6795b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    for (next = edges->fHead; next != NULL; next = next->fRight) {
6806bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if ((c.sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf(edge->fTop)) ||
6816bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            (c.sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf(next->fTop)) ||
6826bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            (c.sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) &&
683d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco             next->isRightOf(edge->fBottom)) ||
6846bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            (c.sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) &&
685d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco             edge->isLeftOf(next->fBottom))) {
686d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            break;
687d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
688d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev = next;
689d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
690d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    *left = prev;
691d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    *right = next;
692d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return;
693d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
694d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
6955b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) {
696d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->isActive(activeEdges)) {
697d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
698d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            remove_edge(edge, activeEdges);
699d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
700d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) {
701d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* left;
702d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* right;
7035b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        find_enclosing_edges(edge, activeEdges, c, &left, &right);
704d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        insert_edge(edge, left, activeEdges);
705d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
706d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
707d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7086bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
709d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fTop->fPoint == edge->fBottom->fPoint ||
7106bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
711d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return;
712d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
713d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
714d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* prev = NULL;
715d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* next;
716d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
717d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (next->isRightOf(edge->fTop)) {
718d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            break;
719d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
720d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev = next;
721d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
722d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
723d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
724d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
725d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7266bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
727d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fTop->fPoint == edge->fBottom->fPoint ||
7286bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
729d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return;
730d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
731d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
732d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* prev = NULL;
733d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Edge* next;
734d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
735d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (next->isRightOf(edge->fBottom)) {
736d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            break;
737d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
738d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev = next;
739d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
740d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
741d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
742d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
743d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
744d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid remove_edge_above(Edge* edge) {
745d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
746d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fBottom->fID);
747d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
748d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
749d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
750d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
751d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid remove_edge_below(Edge* edge) {
752d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
753d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fTop->fID);
754d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
755d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
756d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
757d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7585b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) {
759d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fWinding != 0) {
760d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return;
761d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
762d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
763d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove_edge_above(edge);
764d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove_edge_below(edge);
7655b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    if (edge->isActive(edges)) {
7665b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        remove_edge(edge, edges);
767d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
768d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
769d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7705b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c);
771d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7725b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) {
773d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove_edge_below(edge);
774d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    edge->fTop = v;
775d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    edge->recompute();
7766bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    insert_edge_below(edge, v, c);
7776bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    fix_active_state(edge, activeEdges, c);
7786bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_collinear_edges(edge, activeEdges, c);
779d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
780d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7815b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) {
782d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove_edge_above(edge);
783d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    edge->fBottom = v;
784d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    edge->recompute();
7856bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    insert_edge_above(edge, v, c);
7866bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    fix_active_state(edge, activeEdges, c);
7876bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_collinear_edges(edge, activeEdges, c);
788d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
789d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
7905b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c) {
791d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
792d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
793d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
794d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
795d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        other->fWinding += edge->fWinding;
796d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(other, activeEdges);
797d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fWinding = 0;
798d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(edge, activeEdges);
7996bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
800d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        other->fWinding += edge->fWinding;
801d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(other, activeEdges);
8026bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_bottom(edge, other->fTop, activeEdges, c);
803d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else {
804d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fWinding += other->fWinding;
805d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(edge, activeEdges);
8066bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_bottom(other, edge->fTop, activeEdges, c);
807d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
808d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
809d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8105b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c) {
811d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
812d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
813d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
814d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
815d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        other->fWinding += edge->fWinding;
816d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(other, activeEdges);
817d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fWinding = 0;
818d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(edge, activeEdges);
8196bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
820d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fWinding += other->fWinding;
821d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(edge, activeEdges);
8226bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_top(other, edge->fBottom, activeEdges, c);
823d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else {
824d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        other->fWinding += edge->fWinding;
825d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        erase_edge_if_zero_winding(other, activeEdges);
8266bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_top(edge, other->fBottom, activeEdges, c);
827d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
828d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
829d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8305b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c) {
831d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
832d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
8336bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, c);
834d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
835d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                        !edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
8366bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, c);
837d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
838d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
839d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
8406bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c);
841d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
842d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                        !edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
8436bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c);
844d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
845d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
846d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8475b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc);
848d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8495b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid cleanup_active_edges(Edge* edge, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc) {
850d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* top = edge->fTop;
851d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* bottom = edge->fBottom;
852d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fLeft) {
853d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* leftTop = edge->fLeft->fTop;
854d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* leftBottom = edge->fLeft->fBottom;
8556bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top)) {
8566bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc);
8576bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(leftTop)) {
8586bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, leftTop, activeEdges, c, alloc);
8596bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
8606bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                   !edge->fLeft->isLeftOf(bottom)) {
8616bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge->fLeft, bottom, activeEdges, c, alloc);
8626bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
8636bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, leftBottom, activeEdges, c, alloc);
864d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
865d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
866d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->fRight) {
867d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* rightTop = edge->fRight->fTop;
868d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* rightBottom = edge->fRight->fBottom;
8696bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf(top)) {
8706bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge->fRight, top, activeEdges, c, alloc);
8716bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(rightTop)) {
8726bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, rightTop, activeEdges, c, alloc);
8736bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
874d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                   !edge->fRight->isRightOf(bottom)) {
8756bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge->fRight, bottom, activeEdges, c, alloc);
8766bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
877d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                   !edge->isLeftOf(rightBottom)) {
8786bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, rightBottom, activeEdges, c, alloc);
879d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
880d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
881d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
882d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8835b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancovoid split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc) {
884d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
885d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge->fTop->fID, edge->fBottom->fID,
886d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        v->fID, v->fPoint.fX, v->fPoint.fY);
8876bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
8886bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_top(edge, v, activeEdges, c);
8896bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) {
8906bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_bottom(edge, v, activeEdges, c);
891a2b6d28755916cbb4817cd9d1cd1b0e237de9a50senorblanco    } else {
892a2b6d28755916cbb4817cd9d1cd1b0e237de9a50senorblanco        Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
8936bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        insert_edge_below(newEdge, v, c);
8946bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        insert_edge_above(newEdge, edge->fBottom, c);
8956bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_bottom(edge, v, activeEdges, c);
8966bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        cleanup_active_edges(edge, activeEdges, c, alloc);
8976bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        fix_active_state(newEdge, activeEdges, c);
8986bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        merge_collinear_edges(newEdge, activeEdges, c);
899a2b6d28755916cbb4817cd9d1cd1b0e237de9a50senorblanco    }
900d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
901d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
9026bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkChunkAlloc& alloc) {
903d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
904d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        src->fID, dst->fID);
905d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Edge* edge = src->fFirstEdgeAbove; edge;) {
906d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* next = edge->fNextEdgeAbove;
9076bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_bottom(edge, dst, NULL, c);
908d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge = next;
909d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
910d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Edge* edge = src->fFirstEdgeBelow; edge;) {
911d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* next = edge->fNextEdgeBelow;
9126bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        set_top(edge, dst, NULL, c);
913d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        edge = next;
914d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
915d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL);
916d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
917d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
9185b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblancoVertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c,
9196bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                               SkChunkAlloc& alloc) {
920d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkPoint p;
921d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (!edge || !other) {
922d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return NULL;
923d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
924d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (edge->intersect(*other, &p)) {
925d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* v;
926d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
9276bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) {
9286bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(other, edge->fTop, activeEdges, c, alloc);
929d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v = edge->fTop;
9306bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fPoint)) {
9316bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(other, edge->fBottom, activeEdges, c, alloc);
932d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v = edge->fBottom;
9336bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint)) {
9346bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, other->fTop, activeEdges, c, alloc);
935d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v = other->fTop;
9366bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->fPoint)) {
9376bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, other->fBottom, activeEdges, c, alloc);
938d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v = other->fBottom;
939d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        } else {
940d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* nextV = edge->fTop;
9416bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            while (c.sweep_lt(p, nextV->fPoint)) {
942d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                nextV = nextV->fPrev;
943d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
9446bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            while (c.sweep_lt(nextV->fPoint, p)) {
945d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                nextV = nextV->fNext;
946d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
947d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* prevV = nextV->fPrev;
948d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (coincident(prevV->fPoint, p)) {
949d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v = prevV;
950d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else if (coincident(nextV->fPoint, p)) {
951d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v = nextV;
952d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
953d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v = ALLOC_NEW(Vertex, (p), alloc);
954d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                LOG("inserting between %g (%g, %g) and %g (%g, %g)\n",
955d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY,
956d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY);
957d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
958d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fID = (nextV->fID + prevV->fID) * 0.5f;
959d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
960d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fPrev = prevV;
961d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fNext = nextV;
962d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prevV->fNext = v;
963d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                nextV->fPrev = v;
964d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
9656bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(edge, v, activeEdges, c, alloc);
9666bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            split_edge(other, v, activeEdges, c, alloc);
967d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
968d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return v;
969d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
970d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return NULL;
971d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
972d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
973d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid sanitize_contours(Vertex** contours, int contourCnt) {
974d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (int i = 0; i < contourCnt; ++i) {
975d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        SkASSERT(contours[i]);
976d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Vertex* v = contours[i];;) {
977d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (coincident(v->fPrev->fPoint, v->fPoint)) {
978d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
979d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (v->fPrev == v) {
980d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    contours[i] = NULL;
981d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    break;
982d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
983d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fPrev->fNext = v->fNext;
984d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fNext->fPrev = v->fPrev;
985d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (contours[i] == v) {
986d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    contours[i] = v->fNext;
987d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
988d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v = v->fPrev;
989d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
990d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v = v->fNext;
991d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (v == contours[i]) break;
992d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
993d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
994d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
995d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
996d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
9976bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid merge_coincident_vertices(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) {
998d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) {
9996bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1000d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v->fPoint = v->fPrev->fPoint;
1001d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1002d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (coincident(v->fPrev->fPoint, v->fPoint)) {
10036bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            merge_vertices(v->fPrev, v, vertices, c, alloc);
1004d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1005d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1006d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1007d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1008d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// Stage 2: convert the contours to a mesh of edges connecting the vertices.
1009d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10106bd5137e11071116fe279e2f26264f01baeff1aasenorblancoVertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAlloc& alloc) {
1011d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* vertices = NULL;
1012d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* prev = NULL;
1013d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (int i = 0; i < contourCnt; ++i) {
1014d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Vertex* v = contours[i]; v != NULL;) {
1015d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Vertex* vNext = v->fNext;
10166bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            Edge* edge = new_edge(v->fPrev, v, alloc, c);
1017d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (edge->fWinding > 0) {
10186bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                insert_edge_below(edge, v->fPrev, c);
10196bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                insert_edge_above(edge, v, c);
1020d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
10216bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                insert_edge_below(edge, v, c);
10226bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                insert_edge_above(edge, v->fPrev, c);
1023d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
10246bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            merge_collinear_edges(edge, NULL, c);
1025d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (prev) {
1026d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                prev->fNext = v;
1027d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                v->fPrev = prev;
1028d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
1029d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                vertices = v;
1030d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1031d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            prev = v;
1032d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v = vNext;
1033d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (v == contours[i]) break;
1034d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1035d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1036d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (prev) {
1037d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        prev->fNext = vertices->fPrev = NULL;
1038d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1039d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return vertices;
1040d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1041d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10426bd5137e11071116fe279e2f26264f01baeff1aasenorblanco// Stage 3: sort the vertices by increasing sweep direction.
1043d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10446bd5137e11071116fe279e2f26264f01baeff1aasenorblancoVertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c);
1045d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1046d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancovoid front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) {
1047d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* fast;
1048d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* slow;
1049d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (!v || !v->fNext) {
1050d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *pFront = v;
1051d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *pBack = NULL;
1052d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    } else {
1053d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        slow = v;
1054d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        fast = v->fNext;
1055d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1056d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        while (fast != NULL) {
1057d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            fast = fast->fNext;
1058d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (fast != NULL) {
1059d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                slow = slow->fNext;
1060d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                fast = fast->fNext;
1061d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1062d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1063d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1064d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *pFront = v;
1065d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        *pBack = slow->fNext;
1066d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        slow->fNext->fPrev = NULL;
1067d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        slow->fNext = NULL;
1068d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1069d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1070d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10716bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid merge_sort(Vertex** head, Comparator& c) {
1072d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (!*head || !(*head)->fNext) {
1073d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return;
1074d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1075d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1076d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* a;
1077d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Vertex* b;
1078d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    front_back_split(*head, &a, &b);
1079d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10806bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_sort(&a, c);
10816bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_sort(&b, c);
1082d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10836bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    *head = sorted_merge(a, b, c);
1084d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1085d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10867ef63c85c5891ca59906e3c783a7f954be3f7f62senorblancoinline void append_vertex(Vertex* v, Vertex** head, Vertex** tail) {
10877ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, NULL, head, tail);
10887ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco}
1089d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10907ef63c85c5891ca59906e3c783a7f954be3f7f62senorblancoinline void append_vertex_list(Vertex* v, Vertex** head, Vertex** tail) {
10917ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, v->fNext, head, tail);
10927ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco}
1093d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10946bd5137e11071116fe279e2f26264f01baeff1aasenorblancoVertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c) {
10957ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    Vertex* head = NULL;
10967ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    Vertex* tail = NULL;
10977ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco
10987ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    while (a && b) {
10996bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (c.sweep_lt(a->fPoint, b->fPoint)) {
11007ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            Vertex* next = a->fNext;
11017ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            append_vertex(a, &head, &tail);
11027ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            a = next;
11037ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco        } else {
11047ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            Vertex* next = b->fNext;
11057ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            append_vertex(b, &head, &tail);
11067ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco            b = next;
11077ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco        }
11087ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    }
11097ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    if (a) {
11107ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco        append_vertex_list(a, &head, &tail);
11117ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    }
11127ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    if (b) {
11137ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco        append_vertex_list(b, &head, &tail);
1114d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
11157ef63c85c5891ca59906e3c783a7f954be3f7f62senorblanco    return head;
1116d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1117d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1118d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1119d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
11206bd5137e11071116fe279e2f26264f01baeff1aasenorblancovoid simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) {
1121d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("simplifying complex polygons\n");
11225b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    EdgeList activeEdges;
1123d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1124d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1125d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            continue;
1126d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1127d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1128d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1129d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
1130d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* leftEnclosingEdge = NULL;
1131d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* rightEnclosingEdge = NULL;
1132d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        bool restartChecks;
1133d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        do {
1134d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            restartChecks = false;
11355b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco            find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1136d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (v->fFirstEdgeBelow) {
1137d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge->fNextEdgeBelow) {
11386bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                    if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, c, alloc)) {
1139d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        restartChecks = true;
1140d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        break;
1141d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
11426bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                    if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, c, alloc)) {
1143d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        restartChecks = true;
1144d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        break;
1145d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
1146d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1147d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            } else {
1148d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (Vertex* pv = check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
11496bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                                                        &activeEdges, c, alloc)) {
11506bd5137e11071116fe279e2f26264f01baeff1aasenorblanco                    if (c.sweep_lt(pv->fPoint, v->fPoint)) {
1151d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        v = pv;
1152d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
1153d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    restartChecks = true;
1154d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1155d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1156d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1157d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        } while (restartChecks);
1158d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1159d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            remove_edge(e, &activeEdges);
1160d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1161d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* leftEdge = leftEnclosingEdge;
1162d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1163d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            insert_edge(e, leftEdge, &activeEdges);
1164d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            leftEdge = e;
1165d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1166d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        v->fProcessed = true;
1167d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1168d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1169d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1170d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// Stage 5: Tessellate the simplified mesh into monotone polygons.
1171d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1172d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoPoly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) {
1173d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    LOG("tessellating simple polygons\n");
11745b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco    EdgeList activeEdges;
1175d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    Poly* polys = NULL;
1176d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1177d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1178d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            continue;
1179d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1180d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1181d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1182d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
1183d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* leftEnclosingEdge = NULL;
1184d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Edge* rightEnclosingEdge = NULL;
11855b9f42c4d1ddc776334b3de676450f4cdaf607bdsenorblanco        find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1186d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Poly* leftPoly = NULL;
1187d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Poly* rightPoly = NULL;
1188d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (v->fFirstEdgeAbove) {
1189d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1190d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            rightPoly = v->fLastEdgeAbove->fRightPoly;
1191d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        } else {
1192d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : NULL;
1193d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : NULL;
1194d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1195d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1196d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("edges above:\n");
1197d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1198d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1199d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1200d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1201d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("edges below:\n");
1202d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1203d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1204d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1205d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1206d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
1207d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (v->fFirstEdgeAbove) {
1208d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (leftPoly) {
1209d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1210d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1211d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (rightPoly) {
1212d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1213d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1214d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
1215d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Edge* leftEdge = e;
1216d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                Edge* rightEdge = e->fNextEdgeAbove;
1217d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                SkASSERT(rightEdge->isRightOf(leftEdge->fTop));
1218d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                remove_edge(leftEdge, &activeEdges);
1219d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (leftEdge->fRightPoly) {
1220d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    leftEdge->fRightPoly->end(v, alloc);
1221d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1222d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fRightPoly) {
1223d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    rightEdge->fLeftPoly->end(v, alloc);
1224d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1225d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1226d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            remove_edge(v->fLastEdgeAbove, &activeEdges);
1227d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (!v->fFirstEdgeBelow) {
1228d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (leftPoly && rightPoly && leftPoly != rightPoly) {
1229d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    SkASSERT(leftPoly->fPartner == NULL && rightPoly->fPartner == NULL);
1230d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    rightPoly->fPartner = leftPoly;
1231d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    leftPoly->fPartner = rightPoly;
1232d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1233d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1234d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1235d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (v->fFirstEdgeBelow) {
1236d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            if (!v->fFirstEdgeAbove) {
1237d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (leftPoly && leftPoly == rightPoly) {
1238d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    // Split the poly.
1239d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    if (leftPoly->fActive->fSide == Poly::kLeft_Side) {
1240d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        leftPoly = new_poly(&polys, leftEnclosingEdge->fTop, leftPoly->fWinding,
1241d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            alloc);
1242d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1243d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1244d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        leftEnclosingEdge->fRightPoly = leftPoly;
1245d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    } else {
1246d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        rightPoly = new_poly(&polys, rightEnclosingEdge->fTop, rightPoly->fWinding,
1247d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                             alloc);
1248d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1249d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1250d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        rightEnclosingEdge->fLeftPoly = rightPoly;
1251d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
1252d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                } else {
1253d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    if (leftPoly) {
1254d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1255d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
1256d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    if (rightPoly) {
1257d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                        rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1258d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    }
1259d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1260d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1261d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            Edge* leftEdge = v->fFirstEdgeBelow;
1262d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            leftEdge->fLeftPoly = leftPoly;
1263d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1264d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1265d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                 rightEdge = rightEdge->fNextEdgeBelow) {
1266d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                insert_edge(rightEdge, leftEdge, &activeEdges);
1267d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1268d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                winding += leftEdge->fWinding;
1269d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                if (winding != 0) {
1270d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    Poly* poly = new_poly(&polys, v, winding, alloc);
1271d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                    leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1272d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                }
1273d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                leftEdge = rightEdge;
1274d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            }
1275d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            v->fLastEdgeBelow->fRightPoly = rightPoly;
1276d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1277d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1278d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("\nactive edges:\n");
1279d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        for (Edge* e = activeEdges.fHead; e != NULL; e = e->fRight) {
1280d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1281d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1282d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1283d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
1284d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1285d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return polys;
1286d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1287d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1288d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// This is a driver function which calls stages 2-5 in turn.
1289d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
12906bd5137e11071116fe279e2f26264f01baeff1aasenorblancoPoly* contours_to_polys(Vertex** contours, int contourCnt, Comparator& c, SkChunkAlloc& alloc) {
1291d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1292d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (int i = 0; i < contourCnt; ++i) {
1293d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        Vertex* v = contours[i];
1294d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        SkASSERT(v);
1295d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1296d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        for (v = v->fNext; v != contours[i]; v = v->fNext) {
1297d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1298d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1299d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1300d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
1301d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    sanitize_contours(contours, contourCnt);
13026bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    Vertex* vertices = build_edges(contours, contourCnt, c, alloc);
1303d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (!vertices) {
1304d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return NULL;
1305d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1306d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1307d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    // Sort vertices in Y (secondarily in X).
13086bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_sort(&vertices, c);
13096bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    merge_coincident_vertices(&vertices, c, alloc);
1310d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#if LOGGING_ENABLED
1311d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1312d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        static float gID = 0.0f;
1313d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        v->fID = gID++;
1314d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1315d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#endif
13166bd5137e11071116fe279e2f26264f01baeff1aasenorblanco    simplify(vertices, c, alloc);
1317d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return tessellate(vertices, alloc);
1318d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1319d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1320d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco// Stage 6: Triangulate the monotone polygons into a vertex buffer.
1321d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1322d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblancoSkPoint* polys_to_triangles(Poly* polys, SkPath::FillType fillType, SkPoint* data) {
1323d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco    SkPoint* d = data;
1324d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    for (Poly* poly = polys; poly; poly = poly->fNext) {
1325d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        if (apply_fill_type(fillType, poly->fWinding)) {
1326d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco            d = poly->emit(d);
1327d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        }
1328d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1329d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return d;
1330d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1331d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1332d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco};
1333d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1334d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoGrTessellatingPathRenderer::GrTessellatingPathRenderer() {
1335d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1336d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1337d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoGrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport(
1338d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                                            const GrDrawTarget*,
1339d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                                            const GrPipelineBuilder*,
1340d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                                            const SkPath&,
13411899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                                            const GrStrokeInfo&) const {
1342d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return GrPathRenderer::kNoSupport_StencilSupport;
1343d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1344d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1345d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancobool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target,
1346d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                             const GrPipelineBuilder* pipelineBuilder,
1347d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                             const SkMatrix& viewMatrix,
1348d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                             const SkPath& path,
13491899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                             const GrStrokeInfo& stroke,
1350d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                             bool antiAlias) const {
1351d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    // This path renderer can draw all fill styles, but does not do antialiasing. It can do convex
1352d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    // and concave paths, but we'll leave the convex ones to simpler algorithms.
1353d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return stroke.isFillStyle() && !antiAlias && !path.isConvex();
1354d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
1355d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
13569ba3972ed93321ee606e2974e00a926cd871ddccsenorblancoclass TessellatingPathBatch : public GrBatch {
13579ba3972ed93321ee606e2974e00a926cd871ddccsenorblancopublic:
13589ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
13599ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    static GrBatch* Create(const GrColor& color,
13609ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                           const SkPath& path,
13619ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                           const SkMatrix& viewMatrix,
13629ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                           SkRect clipBounds) {
13639ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipBounds));
13649ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
13659ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
136636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "TessellatingPathBatch"; }
13679ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
136836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
13699ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        out->setKnownFourComponents(fColor);
13709ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
13719ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
137236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
13739ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        out->setUnknownSingleComponent();
13749ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
13759ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
137636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void initBatchTracker(const GrPipelineInfo& init) override {
13779ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        // Handle any color overrides
13789ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        if (init.fColorIgnored) {
13799ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            fColor = GrColor_ILLEGAL;
13809ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        } else if (GrColor_ILLEGAL != init.fOverrideColor) {
13819ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            fColor = init.fOverrideColor;
13829ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        }
13839ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        fPipelineInfo = init;
13849ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
13859ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
138636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
13876bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        SkRect pathBounds = fPath.getBounds();
13886bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        Comparator c;
13896bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        if (pathBounds.width() > pathBounds.height()) {
13906bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            c.sweep_lt = sweep_lt_horiz;
13916bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            c.sweep_gt = sweep_gt_horiz;
13926bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        } else {
13936bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            c.sweep_lt = sweep_lt_vert;
13946bd5137e11071116fe279e2f26264f01baeff1aasenorblanco            c.sweep_gt = sweep_gt_vert;
13956bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        }
13962b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco        SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
13972b4bb07492790d7d18dc046f05999915d4384c5dsenorblanco        SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, pathBounds);
13989ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        int contourCnt;
13999ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol);
14009ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        if (maxPts <= 0) {
14019ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            return;
14029ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        }
14039ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        if (maxPts > ((int)SK_MaxU16 + 1)) {
14049ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
14059ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            return;
14069ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        }
14079ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        SkPath::FillType fillType = fPath.getFillType();
14089ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        if (SkPath::IsInverseFillType(fillType)) {
14099ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            contourCnt++;
14109ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        }
14119ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14129ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        LOG("got %d pts, %d contours\n", maxPts, contourCnt);
14139ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
14149ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        SkAutoTUnref<const GrGeometryProcessor> gp(
14159ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            GrDefaultGeoProcFactory::Create(flags, fColor, fViewMatrix, SkMatrix::I()));
14169ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        batchTarget->initDraw(gp, pipeline);
14179ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        gp->initBatchTracker(batchTarget->currentBatchTracker(), fPipelineInfo);
14189ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14199ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
14209ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14219ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        // For the initial size of the chunk allocator, estimate based on the point count:
14229ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        // one vertex per point for the initial passes, plus two for the vertices in the
14239ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        // resulting Polys, since the same point may end up in two Polys.  Assume minimal
14249ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        // connectivity of one Edge per Vertex (will grow for intersections).
14259ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
14269ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc);
14279ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        Poly* polys;
14286bd5137e11071116fe279e2f26264f01baeff1aasenorblanco        polys = contours_to_polys(contours.get(), contourCnt, c, alloc);
14299ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        int count = 0;
14309ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        for (Poly* poly = polys; poly; poly = poly->fNext) {
14319ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
14329ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
14339ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco            }
14349ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        }
1435e833107a30b240e0685b354838bf6098066da6f8senorblanco        if (0 == count) {
1436e833107a30b240e0685b354838bf6098066da6f8senorblanco            return;
1437e833107a30b240e0685b354838bf6098066da6f8senorblanco        }
14389ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14399ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        size_t stride = gp->getVertexStride();
1440d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        SkASSERT(stride == sizeof(SkPoint));
14419ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        const GrVertexBuffer* vertexBuffer;
14429ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        int firstVertex;
1443d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        SkPoint* verts = static_cast<SkPoint*>(
1444d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco            batchTarget->makeVertSpace(stride, count, &vertexBuffer, &firstVertex));
1445cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        if (!verts) {
14464b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            SkDebugf("Could not allocate vertices\n");
14474b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            return;
14484b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt        }
14494b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt
14509ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        LOG("emitting %d verts\n", count);
1451d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        SkPoint* end = polys_to_triangles(polys, fillType, verts);
1452d4d83eb032845b7aefbeeb717bdb3faeba864aa9senorblanco        int actualCount = static_cast<int>(end - verts);
14539ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        LOG("actual count: %d\n", actualCount);
14549ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        SkASSERT(actualCount <= count);
14559ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14569ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
14579ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                                                  : kTriangles_GrPrimitiveType;
1458cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        GrVertices vertices;
1459cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        vertices.init(primitiveType, vertexBuffer, firstVertex, actualCount);
1460cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        batchTarget->draw(vertices);
14619ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14629ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        batchTarget->putBackVertices((size_t)(count - actualCount), stride);
14639ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        return;
14649ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
14659ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
146636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onCombineIfPossible(GrBatch*) override {
14679ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        return false;
14689ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
14699ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14709ba3972ed93321ee606e2974e00a926cd871ddccsenorblancoprivate:
14719ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    TessellatingPathBatch(const GrColor& color,
14729ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                          const SkPath& path,
14739ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                          const SkMatrix& viewMatrix,
14749ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco                          const SkRect& clipBounds)
14759ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco      : fColor(color)
14769ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco      , fPath(path)
14779ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco      , fViewMatrix(viewMatrix)
14789ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco      , fClipBounds(clipBounds) {
14799ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco        this->initClassID<TessellatingPathBatch>();
148099c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
148199c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        fBounds = path.getBounds();
148299c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        viewMatrix.mapRect(&fBounds);
14839ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
14849ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
14859ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    GrColor        fColor;
14869ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    SkPath         fPath;
14879ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    SkMatrix       fViewMatrix;
14889ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    SkRect         fClipBounds; // in source space
14899ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    GrPipelineInfo fPipelineInfo;
14909ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco};
14919ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
1492d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancobool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target,
1493d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            GrPipelineBuilder* pipelineBuilder,
1494d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            GrColor color,
1495d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            const SkMatrix& viewM,
1496d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            const SkPath& path,
14971899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                            const GrStrokeInfo&,
1498d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco                                            bool antiAlias) {
1499d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkASSERT(!antiAlias);
1500d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
1501d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (NULL == rt) {
1502d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return false;
1503d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1504d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1505d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkIRect clipBoundsI;
1506d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI);
1507d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkRect clipBounds = SkRect::Make(clipBoundsI);
1508d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkMatrix vmi;
1509d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    if (!viewM.invert(&vmi)) {
1510d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco        return false;
1511d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    }
1512d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    vmi.mapRect(&clipBounds);
15139ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM, clipBounds));
15149ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    target->drawBatch(pipelineBuilder, batch);
1515d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1516d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return true;
1517d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
15182fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
15192fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt///////////////////////////////////////////////////////////////////////////////////////////////////
15202fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
15212fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt#ifdef GR_TEST_UTILS
15222fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
15236c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualittBATCH_TEST_DEFINE(TesselatingPathBatch) {
15242fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    GrColor color = GrRandomColor(random);
15252fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
15262fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkPath path = GrTest::TestPath(random);
15272fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkRect clipBounds = GrTest::TestRect(random);
15282fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkMatrix vmi;
15292fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    bool result = viewMatrix.invert(&vmi);
15302fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    if (!result) {
15312fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt        SkFAIL("Cannot invert matrix\n");
15322fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    }
15332fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    vmi.mapRect(&clipBounds);
15342fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds);
15352fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt}
15362fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
15372fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt#endif
1538