Simplify.cpp revision 24c29d91caa4eaa31f9e77bad614627a252df35e
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#include "Simplify.h"
8
9#undef SkASSERT
10#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
11
12// Terminology:
13// A Path contains one of more Contours
14// A Contour is made up of Segment array
15// A Segment is described by a Verb and a Point array with 2, 3, or 4 points
16// A Verb is one of Line, Quad(ratic), or Cubic
17// A Segment contains a Span array
18// A Span is describes a portion of a Segment using starting and ending T
19// T values range from 0 to 1, where 0 is the first Point in the Segment
20// An Edge is a Segment generated from a Span
21
22// FIXME: remove once debugging is complete
23#ifdef SK_DEBUG
24int gDebugMaxWindSum = SK_MaxS32;
25int gDebugMaxWindValue = SK_MaxS32;
26#endif
27
28#define PRECISE_T_SORT 1
29#define SORTABLE_CONTOURS 0 // set to 1 for old code that works most of the time
30
31#define DEBUG_UNUSED 0 // set to expose unused functions
32#define FORCE_RELEASE 1
33
34#if FORCE_RELEASE || defined SK_RELEASE // set force release to 1 for multiple thread -- no debugging
35
36const bool gRunTestsInOneThread = false;
37
38#define DEBUG_ACTIVE_SPANS 0
39#define DEBUG_ADD_INTERSECTING_TS 0
40#define DEBUG_ADD_T_PAIR 0
41#define DEBUG_ANGLE 0
42#define DEBUG_CONCIDENT 0
43#define DEBUG_CROSS 0
44#define DEBUG_MARK_DONE 0
45#define DEBUG_PATH_CONSTRUCTION 1
46#define DEBUG_SORT 0
47#define DEBUG_WIND_BUMP 0
48#define DEBUG_WINDING 0
49
50#else
51
52const bool gRunTestsInOneThread = true;
53
54#define DEBUG_ACTIVE_SPANS 1
55#define DEBUG_ADD_INTERSECTING_TS 1
56#define DEBUG_ADD_T_PAIR 1
57#define DEBUG_ANGLE 1
58#define DEBUG_CONCIDENT 1
59#define DEBUG_CROSS 0
60#define DEBUG_MARK_DONE 1
61#define DEBUG_PATH_CONSTRUCTION 1
62#define DEBUG_SORT 1
63#define DEBUG_WIND_BUMP 0
64#define DEBUG_WINDING 1
65
66#endif
67
68#define DEBUG_DUMP (DEBUG_ACTIVE_SPANS | DEBUG_CONCIDENT | DEBUG_SORT | DEBUG_PATH_CONSTRUCTION)
69
70#if DEBUG_DUMP
71static const char* kLVerbStr[] = {"", "line", "quad", "cubic"};
72// static const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"};
73static int gContourID;
74static int gSegmentID;
75#endif
76
77#ifndef DEBUG_TEST
78#define DEBUG_TEST 0
79#endif
80
81#define MAKE_CONST_LINE(line, pts) \
82    const _Line line = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}}
83#define MAKE_CONST_QUAD(quad, pts) \
84    const Quadratic quad = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
85            {pts[2].fX, pts[2].fY}}
86#define MAKE_CONST_CUBIC(cubic, pts) \
87    const Cubic cubic = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
88            {pts[2].fX, pts[2].fY}, {pts[3].fX, pts[3].fY}}
89
90static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
91        Intersections& intersections) {
92    MAKE_CONST_LINE(aLine, a);
93    MAKE_CONST_LINE(bLine, b);
94    return intersect(aLine, bLine, intersections.fT[0], intersections.fT[1]);
95}
96
97static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
98        Intersections& intersections) {
99    MAKE_CONST_QUAD(aQuad, a);
100    MAKE_CONST_LINE(bLine, b);
101    return intersect(aQuad, bLine, intersections);
102}
103
104static int CubicLineIntersect(const SkPoint a[4], const SkPoint b[2],
105        Intersections& intersections) {
106    MAKE_CONST_CUBIC(aCubic, a);
107    MAKE_CONST_LINE(bLine, b);
108    return intersect(aCubic, bLine, intersections.fT[0], intersections.fT[1]);
109}
110
111static int QuadIntersect(const SkPoint a[3], const SkPoint b[3],
112        Intersections& intersections) {
113    MAKE_CONST_QUAD(aQuad, a);
114    MAKE_CONST_QUAD(bQuad, b);
115#define TRY_QUARTIC_SOLUTION 1
116#if TRY_QUARTIC_SOLUTION
117    intersect2(aQuad, bQuad, intersections);
118#else
119    intersect(aQuad, bQuad, intersections);
120#endif
121    return intersections.fUsed ? intersections.fUsed : intersections.fCoincidentUsed;
122}
123
124static int CubicIntersect(const SkPoint a[4], const SkPoint b[4],
125        Intersections& intersections) {
126    MAKE_CONST_CUBIC(aCubic, a);
127    MAKE_CONST_CUBIC(bCubic, b);
128    intersect(aCubic, bCubic, intersections);
129    return intersections.fUsed;
130}
131
132static int HLineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
133        SkScalar y, bool flipped, Intersections& intersections) {
134    MAKE_CONST_LINE(aLine, a);
135    return horizontalIntersect(aLine, left, right, y, flipped, intersections);
136}
137
138static int HQuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right,
139        SkScalar y, bool flipped, Intersections& intersections) {
140    MAKE_CONST_QUAD(aQuad, a);
141    return horizontalIntersect(aQuad, left, right, y, flipped, intersections);
142}
143
144static int HCubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right,
145        SkScalar y, bool flipped, Intersections& intersections) {
146    MAKE_CONST_CUBIC(aCubic, a);
147    return horizontalIntersect(aCubic, left, right, y, flipped, intersections);
148}
149
150static int VLineIntersect(const SkPoint a[2], SkScalar top, SkScalar bottom,
151        SkScalar x, bool flipped, Intersections& intersections) {
152    MAKE_CONST_LINE(aLine, a);
153    return verticalIntersect(aLine, top, bottom, x, flipped, intersections);
154}
155
156static int VQuadIntersect(const SkPoint a[3], SkScalar top, SkScalar bottom,
157        SkScalar x, bool flipped, Intersections& intersections) {
158    MAKE_CONST_QUAD(aQuad, a);
159    return verticalIntersect(aQuad, top, bottom, x, flipped, intersections);
160}
161
162static int VCubicIntersect(const SkPoint a[4], SkScalar top, SkScalar bottom,
163        SkScalar x, bool flipped, Intersections& intersections) {
164    MAKE_CONST_CUBIC(aCubic, a);
165    return verticalIntersect(aCubic, top, bottom, x, flipped, intersections);
166}
167
168static int (* const VSegmentIntersect[])(const SkPoint [], SkScalar ,
169        SkScalar , SkScalar , bool , Intersections& ) = {
170    NULL,
171    VLineIntersect,
172    VQuadIntersect,
173    VCubicIntersect
174};
175
176static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
177    MAKE_CONST_LINE(line, a);
178    double x, y;
179    xy_at_t(line, t, x, y);
180    out->fX = SkDoubleToScalar(x);
181    out->fY = SkDoubleToScalar(y);
182}
183
184static void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) {
185    MAKE_CONST_QUAD(quad, a);
186    double x, y;
187    xy_at_t(quad, t, x, y);
188    out->fX = SkDoubleToScalar(x);
189    out->fY = SkDoubleToScalar(y);
190}
191
192static void QuadXYAtT(const SkPoint a[3], double t, _Point* out) {
193    MAKE_CONST_QUAD(quad, a);
194    xy_at_t(quad, t, out->x, out->y);
195}
196
197static void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) {
198    MAKE_CONST_CUBIC(cubic, a);
199    double x, y;
200    xy_at_t(cubic, t, x, y);
201    out->fX = SkDoubleToScalar(x);
202    out->fY = SkDoubleToScalar(y);
203}
204
205static void (* const SegmentXYAtT[])(const SkPoint [], double , SkPoint* ) = {
206    NULL,
207    LineXYAtT,
208    QuadXYAtT,
209    CubicXYAtT
210};
211
212static SkScalar LineXAtT(const SkPoint a[2], double t) {
213    MAKE_CONST_LINE(aLine, a);
214    double x;
215    xy_at_t(aLine, t, x, *(double*) 0);
216    return SkDoubleToScalar(x);
217}
218
219static SkScalar QuadXAtT(const SkPoint a[3], double t) {
220    MAKE_CONST_QUAD(quad, a);
221    double x;
222    xy_at_t(quad, t, x, *(double*) 0);
223    return SkDoubleToScalar(x);
224}
225
226static SkScalar CubicXAtT(const SkPoint a[4], double t) {
227    MAKE_CONST_CUBIC(cubic, a);
228    double x;
229    xy_at_t(cubic, t, x, *(double*) 0);
230    return SkDoubleToScalar(x);
231}
232
233static SkScalar (* const SegmentXAtT[])(const SkPoint [], double ) = {
234    NULL,
235    LineXAtT,
236    QuadXAtT,
237    CubicXAtT
238};
239
240static SkScalar LineYAtT(const SkPoint a[2], double t) {
241    MAKE_CONST_LINE(aLine, a);
242    double y;
243    xy_at_t(aLine, t, *(double*) 0, y);
244    return SkDoubleToScalar(y);
245}
246
247static SkScalar QuadYAtT(const SkPoint a[3], double t) {
248    MAKE_CONST_QUAD(quad, a);
249    double y;
250    xy_at_t(quad, t, *(double*) 0, y);
251    return SkDoubleToScalar(y);
252}
253
254static SkScalar CubicYAtT(const SkPoint a[4], double t) {
255    MAKE_CONST_CUBIC(cubic, a);
256    double y;
257    xy_at_t(cubic, t, *(double*) 0, y);
258    return SkDoubleToScalar(y);
259}
260
261static SkScalar (* const SegmentYAtT[])(const SkPoint [], double ) = {
262    NULL,
263    LineYAtT,
264    QuadYAtT,
265    CubicYAtT
266};
267
268static SkScalar LineDXAtT(const SkPoint a[2], double ) {
269    return a[1].fX - a[0].fX;
270}
271
272static SkScalar QuadDXAtT(const SkPoint a[3], double t) {
273    MAKE_CONST_QUAD(quad, a);
274    double x;
275    dxdy_at_t(quad, t, x, *(double*) 0);
276    return SkDoubleToScalar(x);
277}
278
279static SkScalar CubicDXAtT(const SkPoint a[4], double t) {
280    MAKE_CONST_CUBIC(cubic, a);
281    double x;
282    dxdy_at_t(cubic, t, x, *(double*) 0);
283    return SkDoubleToScalar(x);
284}
285
286static SkScalar (* const SegmentDXAtT[])(const SkPoint [], double ) = {
287    NULL,
288    LineDXAtT,
289    QuadDXAtT,
290    CubicDXAtT
291};
292
293static void LineSubDivide(const SkPoint a[2], double startT, double endT,
294        SkPoint sub[2]) {
295    MAKE_CONST_LINE(aLine, a);
296    _Line dst;
297    sub_divide(aLine, startT, endT, dst);
298    sub[0].fX = SkDoubleToScalar(dst[0].x);
299    sub[0].fY = SkDoubleToScalar(dst[0].y);
300    sub[1].fX = SkDoubleToScalar(dst[1].x);
301    sub[1].fY = SkDoubleToScalar(dst[1].y);
302}
303
304static void QuadSubDivide(const SkPoint a[3], double startT, double endT,
305        SkPoint sub[3]) {
306    MAKE_CONST_QUAD(aQuad, a);
307    Quadratic dst;
308    sub_divide(aQuad, startT, endT, dst);
309    sub[0].fX = SkDoubleToScalar(dst[0].x);
310    sub[0].fY = SkDoubleToScalar(dst[0].y);
311    sub[1].fX = SkDoubleToScalar(dst[1].x);
312    sub[1].fY = SkDoubleToScalar(dst[1].y);
313    sub[2].fX = SkDoubleToScalar(dst[2].x);
314    sub[2].fY = SkDoubleToScalar(dst[2].y);
315}
316
317static void CubicSubDivide(const SkPoint a[4], double startT, double endT,
318        SkPoint sub[4]) {
319    MAKE_CONST_CUBIC(aCubic, a);
320    Cubic dst;
321    sub_divide(aCubic, startT, endT, dst);
322    sub[0].fX = SkDoubleToScalar(dst[0].x);
323    sub[0].fY = SkDoubleToScalar(dst[0].y);
324    sub[1].fX = SkDoubleToScalar(dst[1].x);
325    sub[1].fY = SkDoubleToScalar(dst[1].y);
326    sub[2].fX = SkDoubleToScalar(dst[2].x);
327    sub[2].fY = SkDoubleToScalar(dst[2].y);
328    sub[3].fX = SkDoubleToScalar(dst[3].x);
329    sub[3].fY = SkDoubleToScalar(dst[3].y);
330}
331
332static void (* const SegmentSubDivide[])(const SkPoint [], double , double ,
333        SkPoint []) = {
334    NULL,
335    LineSubDivide,
336    QuadSubDivide,
337    CubicSubDivide
338};
339
340static void LineSubDivideHD(const SkPoint a[2], double startT, double endT,
341        _Line sub) {
342    MAKE_CONST_LINE(aLine, a);
343    _Line dst;
344    sub_divide(aLine, startT, endT, dst);
345    sub[0] = dst[0];
346    sub[1] = dst[1];
347}
348
349static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT,
350        Quadratic sub) {
351    MAKE_CONST_QUAD(aQuad, a);
352    Quadratic dst;
353    sub_divide(aQuad, startT, endT, dst);
354    sub[0] = dst[0];
355    sub[1] = dst[1];
356    sub[2] = dst[2];
357}
358
359static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT,
360        Cubic sub) {
361    MAKE_CONST_CUBIC(aCubic, a);
362    Cubic dst;
363    sub_divide(aCubic, startT, endT, dst);
364    sub[0] = dst[0];
365    sub[1] = dst[1];
366    sub[2] = dst[2];
367    sub[3] = dst[3];
368}
369
370#if DEBUG_UNUSED
371static void QuadSubBounds(const SkPoint a[3], double startT, double endT,
372        SkRect& bounds) {
373    SkPoint dst[3];
374    QuadSubDivide(a, startT, endT, dst);
375    bounds.fLeft = bounds.fRight = dst[0].fX;
376    bounds.fTop = bounds.fBottom = dst[0].fY;
377    for (int index = 1; index < 3; ++index) {
378        bounds.growToInclude(dst[index].fX, dst[index].fY);
379    }
380}
381
382static void CubicSubBounds(const SkPoint a[4], double startT, double endT,
383        SkRect& bounds) {
384    SkPoint dst[4];
385    CubicSubDivide(a, startT, endT, dst);
386    bounds.fLeft = bounds.fRight = dst[0].fX;
387    bounds.fTop = bounds.fBottom = dst[0].fY;
388    for (int index = 1; index < 4; ++index) {
389        bounds.growToInclude(dst[index].fX, dst[index].fY);
390    }
391}
392#endif
393
394static SkPath::Verb QuadReduceOrder(const SkPoint a[3],
395        SkTDArray<SkPoint>& reducePts) {
396    MAKE_CONST_QUAD(aQuad, a);
397    Quadratic dst;
398    int order = reduceOrder(aQuad, dst);
399    if (order == 2) { // quad became line
400        for (int index = 0; index < order; ++index) {
401            SkPoint* pt = reducePts.append();
402            pt->fX = SkDoubleToScalar(dst[index].x);
403            pt->fY = SkDoubleToScalar(dst[index].y);
404        }
405    }
406    return (SkPath::Verb) (order - 1);
407}
408
409static SkPath::Verb CubicReduceOrder(const SkPoint a[4],
410        SkTDArray<SkPoint>& reducePts) {
411    MAKE_CONST_CUBIC(aCubic, a);
412    Cubic dst;
413    int order = reduceOrder(aCubic, dst, kReduceOrder_QuadraticsAllowed);
414    if (order == 2 || order == 3) { // cubic became line or quad
415        for (int index = 0; index < order; ++index) {
416            SkPoint* pt = reducePts.append();
417            pt->fX = SkDoubleToScalar(dst[index].x);
418            pt->fY = SkDoubleToScalar(dst[index].y);
419        }
420    }
421    return (SkPath::Verb) (order - 1);
422}
423
424static bool QuadIsLinear(const SkPoint a[3]) {
425    MAKE_CONST_QUAD(aQuad, a);
426    return isLinear(aQuad, 0, 2);
427}
428
429static bool CubicIsLinear(const SkPoint a[4]) {
430    MAKE_CONST_CUBIC(aCubic, a);
431    return isLinear(aCubic, 0, 3);
432}
433
434static SkScalar LineLeftMost(const SkPoint a[2], double startT, double endT) {
435    MAKE_CONST_LINE(aLine, a);
436    double x[2];
437    xy_at_t(aLine, startT, x[0], *(double*) 0);
438    xy_at_t(aLine, endT, x[1], *(double*) 0);
439    return SkMinScalar((float) x[0], (float) x[1]);
440}
441
442static SkScalar QuadLeftMost(const SkPoint a[3], double startT, double endT) {
443    MAKE_CONST_QUAD(aQuad, a);
444    return (float) leftMostT(aQuad, startT, endT);
445}
446
447static SkScalar CubicLeftMost(const SkPoint a[4], double startT, double endT) {
448    MAKE_CONST_CUBIC(aCubic, a);
449    return (float) leftMostT(aCubic, startT, endT);
450}
451
452static SkScalar (* const SegmentLeftMost[])(const SkPoint [], double , double) = {
453    NULL,
454    LineLeftMost,
455    QuadLeftMost,
456    CubicLeftMost
457};
458
459#if 0 // currently unused
460static int QuadRayIntersect(const SkPoint a[3], const SkPoint b[2],
461        Intersections& intersections) {
462    MAKE_CONST_QUAD(aQuad, a);
463    MAKE_CONST_LINE(bLine, b);
464    return intersectRay(aQuad, bLine, intersections);
465}
466#endif
467
468static int QuadRayIntersect(const SkPoint a[3], const _Line& bLine,
469        Intersections& intersections) {
470    MAKE_CONST_QUAD(aQuad, a);
471    return intersectRay(aQuad, bLine, intersections);
472}
473
474class Segment;
475
476struct Span {
477    Segment* fOther;
478    mutable SkPoint fPt; // lazily computed as needed
479    double fT;
480    double fOtherT; // value at fOther[fOtherIndex].fT
481    int fOtherIndex;  // can't be used during intersection
482    int fWindSum; // accumulated from contours surrounding this one
483    int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
484    int fWindValueOpp; // opposite value, if any (for binary ops with coincidence)
485    bool fDone; // if set, this span to next higher T has been processed
486    bool fUnsortableStart; // set when start is part of an unsortable pair
487    bool fUnsortableEnd; // set when end is part of an unsortable pair
488};
489
490// sorting angles
491// given angles of {dx dy ddx ddy dddx dddy} sort them
492class Angle {
493public:
494    // FIXME: this is bogus for quads and cubics
495    // if the quads and cubics' line from end pt to ctrl pt are coincident,
496    // there's no obvious way to determine the curve ordering from the
497    // derivatives alone. In particular, if one quadratic's coincident tangent
498    // is longer than the other curve, the final control point can place the
499    // longer curve on either side of the shorter one.
500    // Using Bezier curve focus http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
501    // may provide some help, but nothing has been figured out yet.
502
503    /*(
504    for quads and cubics, set up a parameterized line (e.g. LineParameters )
505    for points [0] to [1]. See if point [2] is on that line, or on one side
506    or the other. If it both quads' end points are on the same side, choose
507    the shorter tangent. If the tangents are equal, choose the better second
508    tangent angle
509
510    maybe I could set up LineParameters lazily
511    */
512    bool operator<(const Angle& rh) const {
513        double y = dy();
514        double ry = rh.dy();
515        if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
516            return y < 0;
517        }
518        double x = dx();
519        double rx = rh.dx();
520        if (y == 0 && ry == 0 && x * rx < 0) {
521            return x < rx;
522        }
523        double x_ry = x * ry;
524        double rx_y = rx * y;
525        double cmp = x_ry - rx_y;
526        if (!approximately_zero(cmp)) {
527            return cmp < 0;
528        }
529        if (approximately_zero(x_ry) && approximately_zero(rx_y)
530                && !approximately_zero_squared(cmp)) {
531            return cmp < 0;
532        }
533        // at this point, the initial tangent line is coincident
534        if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide) || !approximately_zero(rh.fSide))) {
535            // FIXME: running demo will trigger this assertion
536            // (don't know if commenting out will trigger further assertion or not)
537            // commenting it out allows demo to run in release, though
538     //       SkASSERT(fSide != rh.fSide);
539            return fSide < rh.fSide;
540        }
541        // see if either curve can be lengthened and try the tangent compare again
542        if (cmp && (*fSpans)[fEnd].fOther != rh.fSegment // tangents not absolutely identical
543                && (*rh.fSpans)[rh.fEnd].fOther != fSegment) { // and not intersecting
544            Angle longer = *this;
545            Angle rhLonger = rh;
546            if (longer.lengthen() | rhLonger.lengthen()) {
547                return longer < rhLonger;
548            }
549            // what if we extend in the other direction?
550            longer = *this;
551            rhLonger = rh;
552            if (longer.reverseLengthen() | rhLonger.reverseLengthen()) {
553                return longer < rhLonger;
554            }
555        }
556        if ((fVerb == SkPath::kLine_Verb && approximately_zero(x) && approximately_zero(y))
557                || (rh.fVerb == SkPath::kLine_Verb && approximately_zero(rx) && approximately_zero(ry))) {
558            // See general unsortable comment below. This case can happen when
559            // one line has a non-zero change in t but no change in x and y.
560            fUnsortable = true;
561            rh.fUnsortable = true;
562            return this < &rh; // even with no solution, return a stable sort
563        }
564        SkASSERT(fVerb == SkPath::kQuad_Verb); // worry about cubics later
565        SkASSERT(rh.fVerb == SkPath::kQuad_Verb);
566        // FIXME: until I can think of something better, project a ray from the
567        // end of the shorter tangent to midway between the end points
568        // through both curves and use the resulting angle to sort
569        // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive
570        double len = fTangent1.normalSquared();
571        double rlen = rh.fTangent1.normalSquared();
572        _Line ray;
573        Intersections i, ri;
574        int roots, rroots;
575        bool flip = false;
576        do {
577            const Quadratic& q = (len < rlen) ^ flip ? fQ : rh.fQ;
578            double midX = (q[0].x + q[2].x) / 2;
579            double midY = (q[0].y + q[2].y) / 2;
580            ray[0] = q[1];
581            ray[1].x = midX;
582            ray[1].y = midY;
583            SkASSERT(ray[0] != ray[1]);
584            roots = QuadRayIntersect(fPts, ray, i);
585            rroots = QuadRayIntersect(rh.fPts, ray, ri);
586        } while ((roots == 0 || rroots == 0) && (flip ^= true));
587        if (roots == 0 || rroots == 0) {
588            // FIXME: we don't have a solution in this case. The interim solution
589            // is to mark the edges as unsortable, exclude them from this and
590            // future computations, and allow the returned path to be fragmented
591            fUnsortable = true;
592            rh.fUnsortable = true;
593            return this < &rh; // even with no solution, return a stable sort
594        }
595        _Point loc;
596        double best = SK_ScalarInfinity;
597        double dx, dy, dist;
598        int index;
599        for (index = 0; index < roots; ++index) {
600            QuadXYAtT(fPts, i.fT[0][index], &loc);
601            dx = loc.x - ray[0].x;
602            dy = loc.y - ray[0].y;
603            dist = dx * dx + dy * dy;
604            if (best > dist) {
605                best = dist;
606            }
607        }
608        for (index = 0; index < rroots; ++index) {
609            QuadXYAtT(rh.fPts, ri.fT[0][index], &loc);
610            dx = loc.x - ray[0].x;
611            dy = loc.y - ray[0].y;
612            dist = dx * dx + dy * dy;
613            if (best > dist) {
614                return fSide < 0;
615            }
616        }
617        return fSide > 0;
618    }
619
620    double dx() const {
621        return fTangent1.dx();
622    }
623
624    double dy() const {
625        return fTangent1.dy();
626    }
627
628    int end() const {
629        return fEnd;
630    }
631
632    bool isHorizontal() const {
633        return dy() == 0 && fVerb == SkPath::kLine_Verb;
634    }
635
636    bool lengthen() {
637        int newEnd = fEnd;
638        if (fStart < fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
639            fEnd = newEnd;
640            setSpans();
641            return true;
642        }
643        return false;
644    }
645
646    bool reverseLengthen() {
647        if (fReversed) {
648            return false;
649        }
650        int newEnd = fStart;
651        if (fStart > fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
652            fEnd = newEnd;
653            fReversed = true;
654            setSpans();
655            return true;
656        }
657        return false;
658    }
659
660    void set(const SkPoint* orig, SkPath::Verb verb, const Segment* segment,
661            int start, int end, const SkTDArray<Span>& spans) {
662        fSegment = segment;
663        fStart = start;
664        fEnd = end;
665        fPts = orig;
666        fVerb = verb;
667        fSpans = &spans;
668        fReversed = false;
669        fUnsortable = false;
670        setSpans();
671    }
672
673    void setSpans() {
674        double startT = (*fSpans)[fStart].fT;
675        double endT = (*fSpans)[fEnd].fT;
676        switch (fVerb) {
677        case SkPath::kLine_Verb:
678            _Line l;
679            LineSubDivideHD(fPts, startT, endT, l);
680            // OPTIMIZATION: for pure line compares, we never need fTangent1.c
681            fTangent1.lineEndPoints(l);
682            fSide = 0;
683            break;
684        case SkPath::kQuad_Verb:
685            QuadSubDivideHD(fPts, startT, endT, fQ);
686            fTangent1.quadEndPoints(fQ, 0, 1);
687            fSide = -fTangent1.pointDistance(fQ[2]); // not normalized -- compare sign only
688            break;
689        case SkPath::kCubic_Verb:
690            Cubic c;
691            CubicSubDivideHD(fPts, startT, endT, c);
692            fTangent1.cubicEndPoints(c, 0, 1);
693            fSide = -fTangent1.pointDistance(c[2]); // not normalized -- compare sign only
694            break;
695        default:
696            SkASSERT(0);
697        }
698    }
699
700    Segment* segment() const {
701        return const_cast<Segment*>(fSegment);
702    }
703
704    int sign() const {
705        return SkSign32(fStart - fEnd);
706    }
707
708    const SkTDArray<Span>* spans() const {
709        return fSpans;
710    }
711
712    int start() const {
713        return fStart;
714    }
715
716    bool unsortable() const {
717        return fUnsortable;
718    }
719
720#if DEBUG_ANGLE
721    const SkPoint* pts() const {
722        return fPts;
723    }
724
725    SkPath::Verb verb() const {
726        return fVerb;
727    }
728
729    void debugShow(const SkPoint& a) const {
730        SkDebugf("    d=(%1.9g,%1.9g) side=%1.9g\n", dx(), dy(), fSide);
731    }
732#endif
733
734private:
735    const SkPoint* fPts;
736    Quadratic fQ;
737    SkPath::Verb fVerb;
738    double fSide;
739    LineParameters fTangent1;
740    const SkTDArray<Span>* fSpans;
741    const Segment* fSegment;
742    int fStart;
743    int fEnd;
744    bool fReversed;
745    mutable bool fUnsortable; // this alone is editable by the less than operator
746};
747
748// Bounds, unlike Rect, does not consider a line to be empty.
749struct Bounds : public SkRect {
750    static bool Intersects(const Bounds& a, const Bounds& b) {
751        return a.fLeft <= b.fRight && b.fLeft <= a.fRight &&
752                a.fTop <= b.fBottom && b.fTop <= a.fBottom;
753    }
754
755    void add(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
756        if (left < fLeft) {
757            fLeft = left;
758        }
759        if (top < fTop) {
760            fTop = top;
761        }
762        if (right > fRight) {
763            fRight = right;
764        }
765        if (bottom > fBottom) {
766            fBottom = bottom;
767        }
768    }
769
770    void add(const Bounds& toAdd) {
771        add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom);
772    }
773
774    bool isEmpty() {
775        return fLeft > fRight || fTop > fBottom
776                || (fLeft == fRight && fTop == fBottom)
777                || isnan(fLeft) || isnan(fRight)
778                || isnan(fTop) || isnan(fBottom);
779    }
780
781    void setCubicBounds(const SkPoint a[4]) {
782        _Rect dRect;
783        MAKE_CONST_CUBIC(cubic, a);
784        dRect.setBounds(cubic);
785        set((float) dRect.left, (float) dRect.top, (float) dRect.right,
786                (float) dRect.bottom);
787    }
788
789    void setQuadBounds(const SkPoint a[3]) {
790        MAKE_CONST_QUAD(quad, a);
791        _Rect dRect;
792        dRect.setBounds(quad);
793        set((float) dRect.left, (float) dRect.top, (float) dRect.right,
794                (float) dRect.bottom);
795    }
796};
797
798static bool useInnerWinding(int outerWinding, int innerWinding) {
799    SkASSERT(outerWinding != innerWinding);
800    int absOut = abs(outerWinding);
801    int absIn = abs(innerWinding);
802    bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
803    if (outerWinding * innerWinding < 0) {
804#if DEBUG_WINDING
805        SkDebugf("%s outer=%d inner=%d result=%s\n", __FUNCTION__,
806                outerWinding, innerWinding, result ? "true" : "false");
807#endif
808    }
809    return result;
810}
811
812static const bool opLookup[][2][2] = {
813    //     ==0             !=0
814    //  b      a        b      a
815    {{true , false}, {false, true }}, // a - b
816    {{false, false}, {true , true }}, // a & b
817    {{true , true }, {false, false}}, // a | b
818    {{true , true }, {true , true }}, // a ^ b
819};
820
821static bool activeOp(bool angleIsOp, int otherNonZero, ShapeOp op) {
822    return opLookup[op][otherNonZero][angleIsOp];
823}
824
825class Segment {
826public:
827    Segment() {
828#if DEBUG_DUMP
829        fID = ++gSegmentID;
830#endif
831    }
832
833    bool operator<(const Segment& rh) const {
834        return fBounds.fTop < rh.fBounds.fTop;
835    }
836
837    bool activeAngle(int index, int& done, SkTDArray<Angle>& angles) const {
838        if (activeAngleInner(index, done, angles)) {
839            return true;
840        }
841        double referenceT = fTs[index].fT;
842        int lesser = index;
843        while (--lesser >= 0 && approximately_negative(referenceT - fTs[lesser].fT)) {
844            if (activeAngleOther(lesser, done, angles)) {
845                return true;
846            }
847        }
848        do {
849            if (activeAngleOther(index, done, angles)) {
850                return true;
851            }
852        } while (++index < fTs.count() && approximately_negative(fTs[index].fT - referenceT));
853        return false;
854    }
855
856    bool activeAngleOther(int index, int& done, SkTDArray<Angle>& angles) const {
857        Span* span = &fTs[index];
858        Segment* other = span->fOther;
859        int oIndex = span->fOtherIndex;
860        return other->activeAngleInner(oIndex, done, angles);
861    }
862
863    bool activeAngleInner(int index, int& done, SkTDArray<Angle>& angles) const {
864        int next = nextExactSpan(index, 1);
865        if (next > 0) {
866            const Span& upSpan = fTs[index];
867            if (upSpan.fWindValue) {
868                addAngle(angles, index, next);
869                if (upSpan.fDone) {
870                    done++;
871                } else if (upSpan.fWindSum != SK_MinS32) {
872                    return true;
873                }
874            }
875        }
876        int prev = nextExactSpan(index, -1);
877        // edge leading into junction
878        if (prev >= 0) {
879            const Span& downSpan = fTs[prev];
880            if (downSpan.fWindValue) {
881                addAngle(angles, index, prev);
882                if (downSpan.fDone) {
883                    done++;
884                 } else if (downSpan.fWindSum != SK_MinS32) {
885                    return true;
886                }
887            }
888        }
889        return false;
890    }
891
892    SkScalar activeTop() const {
893        SkASSERT(!done());
894        int count = fTs.count();
895        SkScalar result = SK_ScalarMax;
896        bool lastDone = true;
897        for (int index = 0; index < count; ++index) {
898            bool done = fTs[index].fDone;
899            if (!done || !lastDone) {
900                SkScalar y = yAtT(index);
901                if (result > y) {
902                    result = y;
903                }
904            }
905            lastDone = done;
906        }
907        SkASSERT(result < SK_ScalarMax);
908        return result;
909    }
910
911    void addAngle(SkTDArray<Angle>& angles, int start, int end) const {
912        SkASSERT(start != end);
913        Angle* angle = angles.append();
914#if DEBUG_ANGLE
915        if (angles.count() > 1) {
916            SkPoint angle0Pt, newPt;
917            (*SegmentXYAtT[angles[0].verb()])(angles[0].pts(),
918                    (*angles[0].spans())[angles[0].start()].fT, &angle0Pt);
919            (*SegmentXYAtT[fVerb])(fPts, fTs[start].fT, &newPt);
920            SkASSERT(approximately_equal(angle0Pt.fX, newPt.fX));
921            SkASSERT(approximately_equal(angle0Pt.fY, newPt.fY));
922        }
923#endif
924        angle->set(fPts, fVerb, this, start, end, fTs);
925    }
926
927    void addCancelOutsides(double tStart, double oStart, Segment& other,
928            double oEnd) {
929        int tIndex = -1;
930        int tCount = fTs.count();
931        int oIndex = -1;
932        int oCount = other.fTs.count();
933        do {
934            ++tIndex;
935        } while (!approximately_negative(tStart - fTs[tIndex].fT) && tIndex < tCount);
936        int tIndexStart = tIndex;
937        do {
938            ++oIndex;
939        } while (!approximately_negative(oStart - other.fTs[oIndex].fT) && oIndex < oCount);
940        int oIndexStart = oIndex;
941        double nextT;
942        do {
943            nextT = fTs[++tIndex].fT;
944        } while (nextT < 1 && approximately_negative(nextT - tStart));
945        double oNextT;
946        do {
947            oNextT = other.fTs[++oIndex].fT;
948        } while (oNextT < 1 && approximately_negative(oNextT - oStart));
949        // at this point, spans before and after are at:
950        //  fTs[tIndexStart - 1], fTs[tIndexStart], fTs[tIndex]
951        // if tIndexStart == 0, no prior span
952        // if nextT == 1, no following span
953
954        // advance the span with zero winding
955        // if the following span exists (not past the end, non-zero winding)
956        // connect the two edges
957        if (!fTs[tIndexStart].fWindValue) {
958            if (tIndexStart > 0 && fTs[tIndexStart - 1].fWindValue) {
959    #if DEBUG_CONCIDENT
960                SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
961                        __FUNCTION__, fID, other.fID, tIndexStart - 1,
962                        fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
963                        xyAtT(tIndexStart).fY);
964    #endif
965                addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT, false);
966            }
967            if (nextT < 1 && fTs[tIndex].fWindValue) {
968    #if DEBUG_CONCIDENT
969                SkDebugf("%s 2 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
970                        __FUNCTION__, fID, other.fID, tIndex,
971                        fTs[tIndex].fT, xyAtT(tIndex).fX,
972                        xyAtT(tIndex).fY);
973    #endif
974                addTPair(fTs[tIndex].fT, other, other.fTs[oIndexStart].fT, false);
975            }
976        } else {
977            SkASSERT(!other.fTs[oIndexStart].fWindValue);
978            if (oIndexStart > 0 && other.fTs[oIndexStart - 1].fWindValue) {
979    #if DEBUG_CONCIDENT
980                SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
981                        __FUNCTION__, fID, other.fID, oIndexStart - 1,
982                        other.fTs[oIndexStart].fT, other.xyAtT(oIndexStart).fX,
983                        other.xyAtT(oIndexStart).fY);
984                other.debugAddTPair(other.fTs[oIndexStart].fT, *this, fTs[tIndex].fT);
985    #endif
986            }
987            if (oNextT < 1 && other.fTs[oIndex].fWindValue) {
988    #if DEBUG_CONCIDENT
989                SkDebugf("%s 4 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
990                        __FUNCTION__, fID, other.fID, oIndex,
991                        other.fTs[oIndex].fT, other.xyAtT(oIndex).fX,
992                        other.xyAtT(oIndex).fY);
993                other.debugAddTPair(other.fTs[oIndex].fT, *this, fTs[tIndexStart].fT);
994    #endif
995            }
996        }
997    }
998
999    void addCoinOutsides(const SkTDArray<double>& outsideTs, Segment& other,
1000            double oEnd) {
1001        // walk this to outsideTs[0]
1002        // walk other to outsideTs[1]
1003        // if either is > 0, add a pointer to the other, copying adjacent winding
1004        int tIndex = -1;
1005        int oIndex = -1;
1006        double tStart = outsideTs[0];
1007        double oStart = outsideTs[1];
1008        do {
1009            ++tIndex;
1010        } while (!approximately_negative(tStart - fTs[tIndex].fT));
1011        do {
1012            ++oIndex;
1013        } while (!approximately_negative(oStart - other.fTs[oIndex].fT));
1014        if (tIndex > 0 || oIndex > 0) {
1015            addTPair(tStart, other, oStart, false);
1016        }
1017        tStart = fTs[tIndex].fT;
1018        oStart = other.fTs[oIndex].fT;
1019        do {
1020            double nextT;
1021            do {
1022                nextT = fTs[++tIndex].fT;
1023            } while (approximately_negative(nextT - tStart));
1024            tStart = nextT;
1025            do {
1026                nextT = other.fTs[++oIndex].fT;
1027            } while (approximately_negative(nextT - oStart));
1028            oStart = nextT;
1029            if (tStart == 1 && oStart == 1) {
1030                break;
1031            }
1032            addTPair(tStart, other, oStart, false);
1033        } while (tStart < 1 && oStart < 1 && !approximately_negative(oEnd - oStart));
1034    }
1035
1036    void addCubic(const SkPoint pts[4], bool operand) {
1037        init(pts, SkPath::kCubic_Verb, operand);
1038        fBounds.setCubicBounds(pts);
1039    }
1040
1041    // FIXME: this needs to defer add for aligned consecutive line segments
1042    SkPoint addCurveTo(int start, int end, SkPath& path, bool active) {
1043        SkPoint edge[4];
1044        // OPTIMIZE? if not active, skip remainder and return xy_at_t(end)
1045        (*SegmentSubDivide[fVerb])(fPts, fTs[start].fT, fTs[end].fT, edge);
1046        if (active) {
1047    #if DEBUG_PATH_CONSTRUCTION
1048            SkDebugf("path.%sTo(%1.9g,%1.9g",
1049                    kLVerbStr[fVerb], edge[1].fX, edge[1].fY);
1050            if (fVerb > 1) {
1051                SkDebugf(", %1.9g,%1.9g", edge[2].fX, edge[2].fY);
1052            }
1053            if (fVerb > 2) {
1054                SkDebugf(", %1.9g,%1.9g", edge[3].fX, edge[3].fY);
1055            }
1056            SkDebugf(");\n");
1057    #endif
1058            switch (fVerb) {
1059                case SkPath::kLine_Verb:
1060                    path.lineTo(edge[1].fX, edge[1].fY);
1061                    break;
1062                case SkPath::kQuad_Verb:
1063                    path.quadTo(edge[1].fX, edge[1].fY, edge[2].fX, edge[2].fY);
1064                    break;
1065                case SkPath::kCubic_Verb:
1066                    path.cubicTo(edge[1].fX, edge[1].fY, edge[2].fX, edge[2].fY,
1067                            edge[3].fX, edge[3].fY);
1068                    break;
1069                default:
1070                    SkASSERT(0);
1071            }
1072        }
1073        return edge[fVerb];
1074    }
1075
1076    void addLine(const SkPoint pts[2], bool operand) {
1077        init(pts, SkPath::kLine_Verb, operand);
1078        fBounds.set(pts, 2);
1079    }
1080
1081    const SkPoint& addMoveTo(int tIndex, SkPath& path, bool active) {
1082        const SkPoint& pt = xyAtT(tIndex);
1083        if (active) {
1084    #if DEBUG_PATH_CONSTRUCTION
1085            SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pt.fX, pt.fY);
1086    #endif
1087            path.moveTo(pt.fX, pt.fY);
1088        }
1089        return pt;
1090    }
1091
1092    // add 2 to edge or out of range values to get T extremes
1093    void addOtherT(int index, double otherT, int otherIndex) {
1094        Span& span = fTs[index];
1095        if (precisely_less_than_zero(otherT)) {
1096            otherT = 0;
1097        } else if (precisely_greater_than_one(otherT)) {
1098            otherT = 1;
1099        }
1100        span.fOtherT = otherT;
1101        span.fOtherIndex = otherIndex;
1102    }
1103
1104    void addQuad(const SkPoint pts[3], bool operand) {
1105        init(pts, SkPath::kQuad_Verb, operand);
1106        fBounds.setQuadBounds(pts);
1107    }
1108
1109    // Defer all coincident edge processing until
1110    // after normal intersections have been computed
1111
1112// no need to be tricky; insert in normal T order
1113// resolve overlapping ts when considering coincidence later
1114
1115    // add non-coincident intersection. Resulting edges are sorted in T.
1116    int addT(double newT, Segment* other) {
1117        // FIXME: in the pathological case where there is a ton of intercepts,
1118        //  binary search?
1119        int insertedAt = -1;
1120        size_t tCount = fTs.count();
1121        // FIXME: only do this pinning here (e.g. this is done also in quad/line intersect)
1122        if (precisely_less_than_zero(newT)) {
1123            newT = 0;
1124        } else if (precisely_greater_than_one(newT)) {
1125            newT = 1;
1126        }
1127        for (size_t index = 0; index < tCount; ++index) {
1128            // OPTIMIZATION: if there are three or more identical Ts, then
1129            // the fourth and following could be further insertion-sorted so
1130            // that all the edges are clockwise or counterclockwise.
1131            // This could later limit segment tests to the two adjacent
1132            // neighbors, although it doesn't help with determining which
1133            // circular direction to go in.
1134            if (newT < fTs[index].fT) {
1135                insertedAt = index;
1136                break;
1137            }
1138        }
1139        Span* span;
1140        if (insertedAt >= 0) {
1141            span = fTs.insert(insertedAt);
1142        } else {
1143            insertedAt = tCount;
1144            span = fTs.append();
1145        }
1146        span->fT = newT;
1147        span->fOther = other;
1148        span->fPt.fX = SK_ScalarNaN;
1149        span->fWindSum = SK_MinS32;
1150        span->fWindValue = 1;
1151        span->fWindValueOpp = 0;
1152        if ((span->fDone = newT == 1)) {
1153            ++fDoneSpans;
1154        }
1155        span->fUnsortableStart = false;
1156        span->fUnsortableEnd = false;
1157        return insertedAt;
1158    }
1159
1160    // set spans from start to end to decrement by one
1161    // note this walks other backwards
1162    // FIMXE: there's probably an edge case that can be constructed where
1163    // two span in one segment are separated by float epsilon on one span but
1164    // not the other, if one segment is very small. For this
1165    // case the counts asserted below may or may not be enough to separate the
1166    // spans. Even if the counts work out, what if the spans aren't correctly
1167    // sorted? It feels better in such a case to match the span's other span
1168    // pointer since both coincident segments must contain the same spans.
1169    void addTCancel(double startT, double endT, Segment& other,
1170            double oStartT, double oEndT) {
1171        SkASSERT(!approximately_negative(endT - startT));
1172        SkASSERT(!approximately_negative(oEndT - oStartT));
1173        bool binary = fOperand != other.fOperand;
1174        int index = 0;
1175        while (!approximately_negative(startT - fTs[index].fT)) {
1176            ++index;
1177        }
1178        int oIndex = other.fTs.count();
1179        while (approximately_positive(other.fTs[--oIndex].fT - oEndT))
1180            ;
1181        double tRatio = (oEndT - oStartT) / (endT - startT);
1182        Span* test = &fTs[index];
1183        Span* oTest = &other.fTs[oIndex];
1184        SkTDArray<double> outsideTs;
1185        SkTDArray<double> oOutsideTs;
1186        do {
1187            bool decrement = test->fWindValue && oTest->fWindValue;
1188            bool track = test->fWindValue || oTest->fWindValue;
1189            double testT = test->fT;
1190            double oTestT = oTest->fT;
1191            Span* span = test;
1192            do {
1193                if (decrement) {
1194                    if (binary) {
1195                        --(span->fWindValueOpp);
1196                    } else {
1197                        decrementSpan(span);
1198                    }
1199                } else if (track && span->fT < 1 && oTestT < 1) {
1200                    TrackOutside(outsideTs, span->fT, oTestT);
1201                }
1202                span = &fTs[++index];
1203            } while (approximately_negative(span->fT - testT));
1204            Span* oSpan = oTest;
1205            double otherTMatchStart = oEndT - (span->fT - startT) * tRatio;
1206            double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio;
1207            SkDEBUGCODE(int originalWindValue = oSpan->fWindValue);
1208            while (approximately_negative(otherTMatchStart - oSpan->fT)
1209                    && !approximately_negative(otherTMatchEnd - oSpan->fT)) {
1210        #ifdef SK_DEBUG
1211                SkASSERT(originalWindValue == oSpan->fWindValue);
1212        #endif
1213                if (decrement) {
1214                    other.decrementSpan(oSpan);
1215                } else if (track && oSpan->fT < 1 && testT < 1) {
1216                    TrackOutside(oOutsideTs, oSpan->fT, testT);
1217                }
1218                if (!oIndex) {
1219                    break;
1220                }
1221                oSpan = &other.fTs[--oIndex];
1222            }
1223            test = span;
1224            oTest = oSpan;
1225        } while (!approximately_negative(endT - test->fT));
1226        SkASSERT(!oIndex || approximately_negative(oTest->fT - oStartT));
1227        // FIXME: determine if canceled edges need outside ts added
1228        if (!done() && outsideTs.count()) {
1229            double tStart = outsideTs[0];
1230            double oStart = outsideTs[1];
1231            addCancelOutsides(tStart, oStart, other, oEndT);
1232            int count = outsideTs.count();
1233            if (count > 2) {
1234                double tStart = outsideTs[count - 2];
1235                double oStart = outsideTs[count - 1];
1236                addCancelOutsides(tStart, oStart, other, oEndT);
1237            }
1238        }
1239        if (!other.done() && oOutsideTs.count()) {
1240            double tStart = oOutsideTs[0];
1241            double oStart = oOutsideTs[1];
1242            other.addCancelOutsides(tStart, oStart, *this, endT);
1243        }
1244    }
1245
1246    // set spans from start to end to increment the greater by one and decrement
1247    // the lesser
1248    void addTCoincident(const bool isXor, double startT, double endT,
1249            Segment& other, double oStartT, double oEndT) {
1250        SkASSERT(!approximately_negative(endT - startT));
1251        SkASSERT(!approximately_negative(oEndT - oStartT));
1252        bool binary = fOperand != other.fOperand;
1253        int index = 0;
1254        while (!approximately_negative(startT - fTs[index].fT)) {
1255            ++index;
1256        }
1257        int oIndex = 0;
1258        while (!approximately_negative(oStartT - other.fTs[oIndex].fT)) {
1259            ++oIndex;
1260        }
1261        double tRatio = (oEndT - oStartT) / (endT - startT);
1262        Span* test = &fTs[index];
1263        Span* oTest = &other.fTs[oIndex];
1264        SkTDArray<double> outsideTs;
1265        SkTDArray<double> xOutsideTs;
1266        SkTDArray<double> oOutsideTs;
1267        SkTDArray<double> oxOutsideTs;
1268        do {
1269            bool transfer = test->fWindValue && oTest->fWindValue;
1270            bool decrementThis = (test->fWindValue < oTest->fWindValue) & !isXor;
1271            bool decrementOther = (test->fWindValue >= oTest->fWindValue) & !isXor;
1272            Span* end = test;
1273            double startT = end->fT;
1274            int startIndex = index;
1275            double oStartT = oTest->fT;
1276            int oStartIndex = oIndex;
1277            do {
1278                if (transfer) {
1279                    if (decrementOther) {
1280                #ifdef SK_DEBUG
1281                        SkASSERT(abs(end->fWindValue) < gDebugMaxWindValue);
1282                #endif
1283                        if (binary) {
1284                            ++(end->fWindValueOpp);
1285                        } else {
1286                            ++(end->fWindValue);
1287                        }
1288                    } else if (decrementSpan(end)) {
1289                        TrackOutside(outsideTs, end->fT, oStartT);
1290                    }
1291                } else if (oTest->fWindValue) {
1292                    SkASSERT(!decrementOther);
1293                    if (startIndex > 0 && fTs[startIndex - 1].fWindValue) {
1294                        TrackOutside(xOutsideTs, end->fT, oStartT);
1295                    }
1296                }
1297                end = &fTs[++index];
1298            } while (approximately_negative(end->fT - test->fT));
1299        // because of the order in which coincidences are resolved, this and other
1300        // may not have the same intermediate points. Compute the corresponding
1301        // intermediate T values (using this as the master, other as the follower)
1302        // and walk other conditionally -- hoping that it catches up in the end
1303            double otherTMatch = (test->fT - startT) * tRatio + oStartT;
1304            Span* oEnd = oTest;
1305            while (!approximately_negative(oEndT - oEnd->fT) && approximately_negative(oEnd->fT - otherTMatch)) {
1306                if (transfer) {
1307                    if (decrementThis) {
1308                 #ifdef SK_DEBUG
1309                       SkASSERT(abs(oEnd->fWindValue) < gDebugMaxWindValue);
1310                #endif
1311                        if (binary) {
1312                            ++(oEnd->fWindValueOpp);
1313                        } else {
1314                            ++(oEnd->fWindValue);
1315                        }
1316                    } else if (other.decrementSpan(oEnd)) {
1317                        TrackOutside(oOutsideTs, oEnd->fT, startT);
1318                    }
1319                } else if (test->fWindValue) {
1320                    SkASSERT(!decrementOther);
1321                    if (oStartIndex > 0 && other.fTs[oStartIndex - 1].fWindValue) {
1322                        SkASSERT(0); // track for later?
1323                    }
1324                }
1325                oEnd = &other.fTs[++oIndex];
1326            }
1327            test = end;
1328            oTest = oEnd;
1329        } while (!approximately_negative(endT - test->fT));
1330        SkASSERT(approximately_negative(oTest->fT - oEndT));
1331        SkASSERT(approximately_negative(oEndT - oTest->fT));
1332        if (!done()) {
1333            if (outsideTs.count()) {
1334                addCoinOutsides(outsideTs, other, oEndT);
1335            }
1336            if (xOutsideTs.count()) {
1337                addCoinOutsides(xOutsideTs, other, oEndT);
1338            }
1339        }
1340        if (!other.done() && oOutsideTs.count()) {
1341            other.addCoinOutsides(oOutsideTs, *this, endT);
1342        }
1343    }
1344
1345    // FIXME: this doesn't prevent the same span from being added twice
1346    // fix in caller, assert here?
1347    void addTPair(double t, Segment& other, double otherT, bool borrowWind) {
1348        int tCount = fTs.count();
1349        for (int tIndex = 0; tIndex < tCount; ++tIndex) {
1350            const Span& span = fTs[tIndex];
1351            if (!approximately_negative(span.fT - t)) {
1352                break;
1353            }
1354            if (approximately_negative(span.fT - t) && span.fOther == &other
1355                    && approximately_equal(span.fOtherT, otherT)) {
1356#if DEBUG_ADD_T_PAIR
1357                SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
1358                        __FUNCTION__, fID, t, other.fID, otherT);
1359#endif
1360                return;
1361            }
1362        }
1363#if DEBUG_ADD_T_PAIR
1364        SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
1365                __FUNCTION__, fID, t, other.fID, otherT);
1366#endif
1367        int insertedAt = addT(t, &other);
1368        int otherInsertedAt = other.addT(otherT, this);
1369        addOtherT(insertedAt, otherT, otherInsertedAt);
1370        other.addOtherT(otherInsertedAt, t, insertedAt);
1371        matchWindingValue(insertedAt, t, borrowWind);
1372        other.matchWindingValue(otherInsertedAt, otherT, borrowWind);
1373    }
1374
1375    void addTwoAngles(int start, int end, SkTDArray<Angle>& angles) const {
1376        // add edge leading into junction
1377        if (fTs[SkMin32(end, start)].fWindValue > 0) {
1378            addAngle(angles, end, start);
1379        }
1380        // add edge leading away from junction
1381        int step = SkSign32(end - start);
1382        int tIndex = nextExactSpan(end, step);
1383        if (tIndex >= 0 && fTs[SkMin32(end, tIndex)].fWindValue > 0) {
1384            addAngle(angles, end, tIndex);
1385        }
1386    }
1387
1388    const Bounds& bounds() const {
1389        return fBounds;
1390    }
1391
1392    void buildAngles(int index, SkTDArray<Angle>& angles) const {
1393        double referenceT = fTs[index].fT;
1394        int lesser = index;
1395    #if PRECISE_T_SORT
1396        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
1397            buildAnglesInner(lesser, angles);
1398        }
1399        do {
1400            buildAnglesInner(index, angles);
1401        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
1402    #else
1403        while (--lesser >= 0 && approximately_negative(referenceT - fTs[lesser].fT)) {
1404            buildAnglesInner(lesser, angles);
1405        }
1406        do {
1407            buildAnglesInner(index, angles);
1408        } while (++index < fTs.count() && approximately_negative(fTs[index].fT - referenceT));
1409    #endif
1410    }
1411
1412    void buildAnglesInner(int index, SkTDArray<Angle>& angles) const {
1413        Span* span = &fTs[index];
1414        Segment* other = span->fOther;
1415    // if there is only one live crossing, and no coincidence, continue
1416    // in the same direction
1417    // if there is coincidence, the only choice may be to reverse direction
1418        // find edge on either side of intersection
1419        int oIndex = span->fOtherIndex;
1420        // if done == -1, prior span has already been processed
1421        int step = 1;
1422    #if PRECISE_T_SORT
1423        int next = other->nextExactSpan(oIndex, step);
1424    #else
1425        int next = other->nextSpan(oIndex, step);
1426    #endif
1427       if (next < 0) {
1428            step = -step;
1429    #if PRECISE_T_SORT
1430            next = other->nextExactSpan(oIndex, step);
1431    #else
1432            next = other->nextSpan(oIndex, step);
1433    #endif
1434        }
1435        // add candidate into and away from junction
1436        other->addTwoAngles(next, oIndex, angles);
1437    }
1438
1439    // figure out if the segment's ascending T goes clockwise or not
1440    // not enough context to write this as shown
1441    // instead, add all segments meeting at the top
1442    // sort them using buildAngleList
1443    // find the first in the sort
1444    // see if ascendingT goes to top
1445    bool clockwise(int /* tIndex */) const {
1446        SkASSERT(0); // incomplete
1447        return false;
1448    }
1449
1450    // FIXME may not need this at all
1451    // FIXME once I figure out the logic, merge this and too close to call
1452    // NOTE not sure if tiny triangles can ever form at the edge, so until we
1453    // see one, only worry about triangles that happen away from 0 and 1
1454    void collapseTriangles(bool isXor) {
1455        if (fTs.count() < 3) { // require t=0, x, 1 at minimum
1456            return;
1457        }
1458        int lastIndex = 1;
1459        double lastT;
1460        while (approximately_less_than_zero((lastT = fTs[lastIndex].fT))) {
1461            ++lastIndex;
1462        }
1463        if (approximately_greater_than_one(lastT)) {
1464            return;
1465        }
1466        int matchIndex = lastIndex;
1467        do {
1468            Span& match = fTs[++matchIndex];
1469            double matchT = match.fT;
1470            if (approximately_greater_than_one(matchT)) {
1471                return;
1472            }
1473            if (matchT == lastT) {
1474                goto nextSpan;
1475            }
1476            if (approximately_negative(matchT - lastT)) {
1477                Span& last = fTs[lastIndex];
1478                Segment* lOther = last.fOther;
1479                double lT = last.fOtherT;
1480                if (approximately_less_than_zero(lT) || approximately_greater_than_one(lT)) {
1481                    goto nextSpan;
1482                }
1483                Segment* mOther = match.fOther;
1484                double mT = match.fOtherT;
1485                if (approximately_less_than_zero(mT) || approximately_greater_than_one(mT)) {
1486                    goto nextSpan;
1487                }
1488                // add new point to connect adjacent spurs
1489                int count = lOther->fTs.count();
1490                for (int index = 0; index < count; ++index) {
1491                    Span& span = lOther->fTs[index];
1492                    if (span.fOther == mOther && approximately_zero(span.fOtherT - mT)) {
1493                        goto nextSpan;
1494                    }
1495                }
1496                mOther->addTPair(mT, *lOther, lT, false);
1497                // FIXME ? this could go on to detect that spans on mOther, lOther are now coincident
1498            }
1499    nextSpan:
1500            lastIndex = matchIndex;
1501            lastT = matchT;
1502        } while (true);
1503    }
1504
1505    int computeSum(int startIndex, int endIndex) {
1506        SkTDArray<Angle> angles;
1507        addTwoAngles(startIndex, endIndex, angles);
1508        buildAngles(endIndex, angles);
1509        // OPTIMIZATION: check all angles to see if any have computed wind sum
1510        // before sorting (early exit if none)
1511        SkTDArray<Angle*> sorted;
1512        bool sortable = SortAngles(angles, sorted);
1513#if DEBUG_SORT
1514        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0);
1515#endif
1516        if (!sortable) {
1517            return SK_MinS32;
1518        }
1519        int angleCount = angles.count();
1520        const Angle* angle;
1521        const Segment* base;
1522        int winding;
1523        int firstIndex = 0;
1524        do {
1525            angle = sorted[firstIndex];
1526            base = angle->segment();
1527            winding = base->windSum(angle);
1528            if (winding != SK_MinS32) {
1529                break;
1530            }
1531            if (++firstIndex == angleCount) {
1532                return SK_MinS32;
1533            }
1534        } while (true);
1535        // turn winding into contourWinding
1536        int spanWinding = base->spanSign(angle);
1537        bool inner = useInnerWinding(winding + spanWinding, winding);
1538    #if DEBUG_WINDING
1539        SkDebugf("%s spanWinding=%d winding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
1540            spanWinding, winding, angle->sign(), inner,
1541            inner ? winding + spanWinding : winding);
1542    #endif
1543        if (inner) {
1544            winding += spanWinding;
1545        }
1546    #if DEBUG_SORT
1547        base->debugShowSort(__FUNCTION__, sorted, firstIndex, winding);
1548    #endif
1549        int nextIndex = firstIndex + 1;
1550        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1551        winding -= base->spanSign(angle);
1552        do {
1553            if (nextIndex == angleCount) {
1554                nextIndex = 0;
1555            }
1556            angle = sorted[nextIndex];
1557            Segment* segment = angle->segment();
1558            int maxWinding = winding;
1559            winding -= segment->spanSign(angle);
1560            if (segment->windSum(angle) == SK_MinS32) {
1561                if (useInnerWinding(maxWinding, winding)) {
1562                    maxWinding = winding;
1563                }
1564                segment->markAndChaseWinding(angle, maxWinding);
1565            }
1566        } while (++nextIndex != lastIndex);
1567        return windSum(SkMin32(startIndex, endIndex));
1568    }
1569
1570    int crossedSpan(const SkPoint& basePt, SkScalar& bestY, double& hitT) const {
1571        int bestT = -1;
1572        SkScalar top = bounds().fTop;
1573        SkScalar bottom = bounds().fBottom;
1574        int end = 0;
1575        do {
1576            int start = end;
1577            end = nextSpan(start, 1);
1578            if (fTs[start].fWindValue == 0) {
1579                continue;
1580            }
1581            SkPoint edge[4];
1582            double startT = fTs[start].fT;
1583            double endT = fTs[end].fT;
1584            (*SegmentSubDivide[fVerb])(fPts, startT, endT, edge);
1585            // intersect ray starting at basePt with edge
1586            Intersections intersections;
1587            // FIXME: always use original and limit results to T values within
1588            // start t and end t.
1589            // OPTIMIZE: use specialty function that intersects ray with curve,
1590            // returning t values only for curve (we don't care about t on ray)
1591            int pts = (*VSegmentIntersect[fVerb])(edge, top, bottom, basePt.fX,
1592                    false, intersections);
1593            if (pts == 0) {
1594                continue;
1595            }
1596            if (pts > 1 && fVerb == SkPath::kLine_Verb) {
1597            // if the intersection is edge on, wait for another one
1598                continue;
1599            }
1600            for (int index = 0; index < pts; ++index) {
1601                SkPoint pt;
1602                double foundT = intersections.fT[0][index];
1603                double testT = startT + (endT - startT) * foundT;
1604                (*SegmentXYAtT[fVerb])(fPts, testT, &pt);
1605                if (bestY < pt.fY && pt.fY < basePt.fY) {
1606                    if (fVerb > SkPath::kLine_Verb
1607                            && !approximately_less_than_zero(foundT)
1608                            && !approximately_greater_than_one(foundT)) {
1609                        SkScalar dx = (*SegmentDXAtT[fVerb])(fPts, testT);
1610                        if (approximately_zero(dx)) {
1611                            continue;
1612                        }
1613                    }
1614                    bestY = pt.fY;
1615                    bestT = foundT < 1 ? start : end;
1616                    hitT = testT;
1617                }
1618            }
1619        } while (fTs[end].fT != 1);
1620        return bestT;
1621    }
1622
1623    bool crossedSpanHalves(const SkPoint& basePt, bool leftHalf, bool rightHalf) {
1624        // if a segment is connected to this one, consider it crossing
1625        int tIndex;
1626        if (fPts[0].fX == basePt.fX) {
1627            tIndex = 0;
1628            do {
1629                const Span& sSpan = fTs[tIndex];
1630                const Segment* sOther = sSpan.fOther;
1631                if (!sOther->fTs[sSpan.fOtherIndex].fWindValue) {
1632                    continue;
1633                }
1634                if (leftHalf ? sOther->fBounds.fLeft < basePt.fX
1635                        : sOther->fBounds.fRight > basePt.fX) {
1636                    return true;
1637                }
1638            } while (fTs[++tIndex].fT == 0);
1639        }
1640        if (fPts[fVerb].fX == basePt.fX) {
1641            tIndex = fTs.count() - 1;
1642            do {
1643                const Span& eSpan = fTs[tIndex];
1644                const Segment* eOther = eSpan.fOther;
1645                if (!eOther->fTs[eSpan.fOtherIndex].fWindValue) {
1646                    continue;
1647                }
1648                if (leftHalf ? eOther->fBounds.fLeft < basePt.fX
1649                        : eOther->fBounds.fRight > basePt.fX) {
1650                    return true;
1651                }
1652            } while (fTs[--tIndex].fT == 1);
1653        }
1654        return false;
1655    }
1656
1657    bool decrementSpan(Span* span) {
1658        SkASSERT(span->fWindValue > 0);
1659        if (--(span->fWindValue) == 0) {
1660            span->fDone = true;
1661            ++fDoneSpans;
1662            return true;
1663        }
1664        return false;
1665    }
1666
1667    bool done() const {
1668        SkASSERT(fDoneSpans <= fTs.count());
1669        return fDoneSpans == fTs.count();
1670    }
1671
1672    bool done(const Angle& angle) const {
1673        int start = angle.start();
1674        int end = angle.end();
1675        const Span& mSpan = fTs[SkMin32(start, end)];
1676        return mSpan.fDone;
1677    }
1678
1679    Segment* findNextOp(SkTDArray<Span*>& chase, bool active,
1680            int& nextStart, int& nextEnd, int& winding, int& spanWinding,
1681            bool& unsortable, ShapeOp op,
1682            const int aXorMask, const int bXorMask) {
1683        const int startIndex = nextStart;
1684        const int endIndex = nextEnd;
1685        int outerWinding = winding;
1686        int innerWinding = winding + spanWinding;
1687    #if DEBUG_WINDING
1688        SkDebugf("%s winding=%d spanWinding=%d outerWinding=%d innerWinding=%d\n",
1689                __FUNCTION__, winding, spanWinding, outerWinding, innerWinding);
1690    #endif
1691        if (useInnerWinding(outerWinding, innerWinding)) {
1692            outerWinding = innerWinding;
1693        }
1694        SkASSERT(startIndex != endIndex);
1695        int count = fTs.count();
1696        SkASSERT(startIndex < endIndex ? startIndex < count - 1
1697                : startIndex > 0);
1698        int step = SkSign32(endIndex - startIndex);
1699    #if PRECISE_T_SORT
1700        int end = nextExactSpan(startIndex, step);
1701    #else
1702        int end = nextSpan(startIndex, step);
1703    #endif
1704        SkASSERT(end >= 0);
1705        Span* endSpan = &fTs[end];
1706        Segment* other;
1707        if (isSimple(end)) {
1708        // mark the smaller of startIndex, endIndex done, and all adjacent
1709        // spans with the same T value (but not 'other' spans)
1710    #if DEBUG_WINDING
1711            SkDebugf("%s simple\n", __FUNCTION__);
1712    #endif
1713            markDone(SkMin32(startIndex, endIndex), outerWinding);
1714            other = endSpan->fOther;
1715            nextStart = endSpan->fOtherIndex;
1716            double startT = other->fTs[nextStart].fT;
1717            nextEnd = nextStart;
1718            do {
1719                nextEnd += step;
1720            }
1721    #if PRECISE_T_SORT
1722            while (precisely_zero(startT - other->fTs[nextEnd].fT));
1723    #else
1724            while (approximately_zero(startT - other->fTs[nextEnd].fT));
1725    #endif
1726            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
1727            return other;
1728        }
1729        // more than one viable candidate -- measure angles to find best
1730        SkTDArray<Angle> angles;
1731        SkASSERT(startIndex - endIndex != 0);
1732        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1733        addTwoAngles(startIndex, end, angles);
1734        buildAngles(end, angles);
1735        SkTDArray<Angle*> sorted;
1736        bool sortable = SortAngles(angles, sorted);
1737        int angleCount = angles.count();
1738        int firstIndex = findStartingEdge(sorted, startIndex, end);
1739        SkASSERT(firstIndex >= 0);
1740    #if DEBUG_SORT
1741        debugShowSort(__FUNCTION__, sorted, firstIndex, winding);
1742    #endif
1743        if (!sortable) {
1744            unsortable = true;
1745            return NULL;
1746        }
1747        SkASSERT(sorted[firstIndex]->segment() == this);
1748    #if DEBUG_WINDING
1749        SkDebugf("%s [%d] sign=%d\n", __FUNCTION__, firstIndex, sorted[firstIndex]->sign());
1750    #endif
1751        int aSumWinding = winding;
1752        int bSumWinding = winding;
1753        bool angleIsOp = sorted[firstIndex]->segment()->operand();
1754        int angleSpan = spanSign(sorted[firstIndex]);
1755        if (angleIsOp) {
1756            bSumWinding -= angleSpan;
1757        } else {
1758            aSumWinding -= angleSpan;
1759        }
1760        int nextIndex = firstIndex + 1;
1761        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1762        const Angle* foundAngle = NULL;
1763        // FIXME: found done logic probably fails if there are more than 4
1764        // sorted angles. It should bias towards the first and last undone
1765        // edges -- but not sure that it won't choose a middle (incorrect)
1766        // edge if one is undone
1767        bool foundDone = false;
1768        bool foundDone2 = false;
1769        // iterate through the angle, and compute everyone's winding
1770        bool altFlipped = false;
1771        bool foundFlipped = false;
1772        int foundMax = SK_MinS32;
1773        int foundSum = SK_MinS32;
1774        Segment* nextSegment;
1775        int lastNonZeroSum = winding;
1776        do {
1777            if (nextIndex == angleCount) {
1778                nextIndex = 0;
1779            }
1780            const Angle* nextAngle = sorted[nextIndex];
1781            nextSegment = nextAngle->segment();
1782            angleIsOp = nextSegment->operand();
1783            int sumWinding = angleIsOp ? bSumWinding : aSumWinding;
1784            int maxWinding = sumWinding;
1785            if (sumWinding) {
1786                lastNonZeroSum = sumWinding;
1787            }
1788            sumWinding -= nextSegment->spanSign(nextAngle);
1789            int xorMask = nextSegment->operand() ? bXorMask : aXorMask;
1790            bool otherNonZero;
1791            if (angleIsOp) {
1792                bSumWinding = sumWinding;
1793                otherNonZero = aSumWinding & aXorMask;
1794            } else {
1795                aSumWinding = sumWinding;
1796                otherNonZero = bSumWinding & bXorMask;
1797            }
1798            altFlipped ^= lastNonZeroSum * sumWinding < 0; // flip if different signs
1799    #if 0 &&  DEBUG_WINDING
1800            SkASSERT(abs(sumWinding) <= gDebugMaxWindSum);
1801            SkDebugf("%s [%d] maxWinding=%d sumWinding=%d sign=%d altFlipped=%d\n", __FUNCTION__,
1802                    nextIndex, maxWinding, sumWinding, nextAngle->sign(), altFlipped);
1803    #endif
1804
1805            if (!(sumWinding & xorMask) && activeOp(angleIsOp, otherNonZero, op)) {
1806                if (!active) {
1807                    markDone(SkMin32(startIndex, endIndex), outerWinding);
1808                    // FIXME: seems like a bug that this isn't calling userInnerWinding
1809                    nextSegment->markWinding(SkMin32(nextAngle->start(),
1810                                nextAngle->end()), maxWinding);
1811    #if DEBUG_WINDING
1812                    SkDebugf("%s [%d] inactive\n", __FUNCTION__, nextIndex);
1813    #endif
1814                    return NULL;
1815                }
1816                if (!foundAngle || foundDone) {
1817                    foundAngle = nextAngle;
1818                    foundDone = nextSegment->done(*nextAngle);
1819                    foundFlipped = altFlipped;
1820                    foundMax = maxWinding;
1821                }
1822                continue;
1823            }
1824            if (!(maxWinding & xorMask) && (!foundAngle || foundDone2)
1825                    && activeOp(angleIsOp, otherNonZero, op)) {
1826        #if DEBUG_WINDING
1827                if (foundAngle && foundDone2) {
1828                    SkDebugf("%s [%d] !foundAngle && foundDone2\n", __FUNCTION__, nextIndex);
1829                }
1830        #endif
1831                foundAngle = nextAngle;
1832                foundDone2 = nextSegment->done(*nextAngle);
1833                foundFlipped = altFlipped;
1834                foundSum = sumWinding;
1835            }
1836            if (nextSegment->done()) {
1837                continue;
1838            }
1839            // if the winding is non-zero, nextAngle does not connect to
1840            // current chain. If we haven't done so already, mark the angle
1841            // as done, record the winding value, and mark connected unambiguous
1842            // segments as well.
1843            if (nextSegment->windSum(nextAngle) == SK_MinS32) {
1844                if (useInnerWinding(maxWinding, sumWinding)) {
1845                    maxWinding = sumWinding;
1846                }
1847                Span* last;
1848                if (foundAngle) {
1849                    last = nextSegment->markAndChaseWinding(nextAngle, maxWinding);
1850                } else {
1851                    last = nextSegment->markAndChaseDone(nextAngle, maxWinding);
1852                }
1853                if (last) {
1854                    *chase.append() = last;
1855                }
1856            }
1857        } while (++nextIndex != lastIndex);
1858        markDone(SkMin32(startIndex, endIndex), outerWinding);
1859        if (!foundAngle) {
1860            return NULL;
1861        }
1862        nextStart = foundAngle->start();
1863        nextEnd = foundAngle->end();
1864        nextSegment = foundAngle->segment();
1865        int flipped = foundFlipped ? -1 : 1;
1866        spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue(
1867                SkMin32(nextStart, nextEnd));
1868        if (winding) {
1869    #if DEBUG_WINDING
1870            SkDebugf("%s ---6 winding=%d foundSum=", __FUNCTION__, winding);
1871            if (foundSum == SK_MinS32) {
1872                SkDebugf("?");
1873            } else {
1874                SkDebugf("%d", foundSum);
1875            }
1876            SkDebugf(" foundMax=");
1877            if (foundMax == SK_MinS32) {
1878                SkDebugf("?");
1879            } else {
1880                SkDebugf("%d", foundMax);
1881            }
1882            SkDebugf("\n");
1883     #endif
1884            winding = foundSum;
1885        }
1886    #if DEBUG_WINDING
1887        SkDebugf("%s spanWinding=%d flipped=%d\n", __FUNCTION__, spanWinding, flipped);
1888    #endif
1889        return nextSegment;
1890    }
1891
1892    // so the span needs to contain the pairing info found here
1893    // this should include the winding computed for the edge, and
1894    //  what edge it connects to, and whether it is discarded
1895    //  (maybe discarded == abs(winding) > 1) ?
1896    // only need derivatives for duration of sorting, add a new struct
1897    // for pairings, remove extra spans that have zero length and
1898    //  reference an unused other
1899    // for coincident, the last span on the other may be marked done
1900    //  (always?)
1901
1902    // if loop is exhausted, contour may be closed.
1903    // FIXME: pass in close point so we can check for closure
1904
1905    // given a segment, and a sense of where 'inside' is, return the next
1906    // segment. If this segment has an intersection, or ends in multiple
1907    // segments, find the mate that continues the outside.
1908    // note that if there are multiples, but no coincidence, we can limit
1909    // choices to connections in the correct direction
1910
1911    // mark found segments as done
1912
1913    // start is the index of the beginning T of this edge
1914    // it is guaranteed to have an end which describes a non-zero length (?)
1915    // winding -1 means ccw, 1 means cw
1916    Segment* findNextWinding(SkTDArray<Span*>& chase, bool active,
1917            int& nextStart, int& nextEnd, int& winding, int& spanWinding,
1918            bool& unsortable) {
1919        const int startIndex = nextStart;
1920        const int endIndex = nextEnd;
1921        int outerWinding = winding;
1922        int innerWinding = winding + spanWinding;
1923    #if DEBUG_WINDING
1924        SkDebugf("%s winding=%d spanWinding=%d outerWinding=%d innerWinding=%d\n",
1925                __FUNCTION__, winding, spanWinding, outerWinding, innerWinding);
1926    #endif
1927        if (useInnerWinding(outerWinding, innerWinding)) {
1928            outerWinding = innerWinding;
1929        }
1930        SkASSERT(startIndex != endIndex);
1931        int count = fTs.count();
1932        SkASSERT(startIndex < endIndex ? startIndex < count - 1
1933                : startIndex > 0);
1934        int step = SkSign32(endIndex - startIndex);
1935    #if PRECISE_T_SORT
1936        int end = nextExactSpan(startIndex, step);
1937    #else
1938        int end = nextSpan(startIndex, step);
1939    #endif
1940        SkASSERT(end >= 0);
1941        Span* endSpan = &fTs[end];
1942        Segment* other;
1943        if (isSimple(end)) {
1944        // mark the smaller of startIndex, endIndex done, and all adjacent
1945        // spans with the same T value (but not 'other' spans)
1946    #if DEBUG_WINDING
1947            SkDebugf("%s simple\n", __FUNCTION__);
1948    #endif
1949            markDone(SkMin32(startIndex, endIndex), outerWinding);
1950            other = endSpan->fOther;
1951            nextStart = endSpan->fOtherIndex;
1952            double startT = other->fTs[nextStart].fT;
1953            nextEnd = nextStart;
1954            do {
1955                nextEnd += step;
1956            }
1957    #if PRECISE_T_SORT
1958             while (precisely_zero(startT - other->fTs[nextEnd].fT));
1959    #else
1960             while (approximately_zero(startT - other->fTs[nextEnd].fT));
1961    #endif
1962            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
1963            return other;
1964        }
1965        // more than one viable candidate -- measure angles to find best
1966        SkTDArray<Angle> angles;
1967        SkASSERT(startIndex - endIndex != 0);
1968        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
1969        addTwoAngles(startIndex, end, angles);
1970        buildAngles(end, angles);
1971        SkTDArray<Angle*> sorted;
1972        bool sortable = SortAngles(angles, sorted);
1973        int angleCount = angles.count();
1974        int firstIndex = findStartingEdge(sorted, startIndex, end);
1975        SkASSERT(firstIndex >= 0);
1976    #if DEBUG_SORT
1977        debugShowSort(__FUNCTION__, sorted, firstIndex, winding);
1978    #endif
1979        if (!sortable) {
1980            unsortable = true;
1981            return NULL;
1982        }
1983        SkASSERT(sorted[firstIndex]->segment() == this);
1984    #if DEBUG_WINDING
1985        SkDebugf("%s [%d] sign=%d\n", __FUNCTION__, firstIndex, sorted[firstIndex]->sign());
1986    #endif
1987        int sumWinding = winding - spanSign(sorted[firstIndex]);
1988        int nextIndex = firstIndex + 1;
1989        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1990        const Angle* foundAngle = NULL;
1991        // FIXME: found done logic probably fails if there are more than 4
1992        // sorted angles. It should bias towards the first and last undone
1993        // edges -- but not sure that it won't choose a middle (incorrect)
1994        // edge if one is undone
1995        bool foundDone = false;
1996        bool foundDone2 = false;
1997        // iterate through the angle, and compute everyone's winding
1998        bool altFlipped = false;
1999        bool foundFlipped = false;
2000        int foundMax = SK_MinS32;
2001        int foundSum = SK_MinS32;
2002        Segment* nextSegment;
2003        int lastNonZeroSum = winding;
2004        do {
2005            if (nextIndex == angleCount) {
2006                nextIndex = 0;
2007            }
2008            const Angle* nextAngle = sorted[nextIndex];
2009            int maxWinding = sumWinding;
2010            if (sumWinding) {
2011                lastNonZeroSum = sumWinding;
2012            }
2013            nextSegment = nextAngle->segment();
2014            sumWinding -= nextSegment->spanSign(nextAngle);
2015            altFlipped ^= lastNonZeroSum * sumWinding < 0; // flip if different signs
2016    #if 0 && DEBUG_WINDING
2017            SkASSERT(abs(sumWinding) <= gDebugMaxWindSum);
2018            SkDebugf("%s [%d] maxWinding=%d sumWinding=%d sign=%d altFlipped=%d\n", __FUNCTION__,
2019                    nextIndex, maxWinding, sumWinding, nextAngle->sign(), altFlipped);
2020    #endif
2021           if (!sumWinding) {
2022                if (!active) {
2023                    markDone(SkMin32(startIndex, endIndex), outerWinding);
2024                    // FIXME: seems like a bug that this isn't calling userInnerWinding
2025                    nextSegment->markWinding(SkMin32(nextAngle->start(),
2026                                nextAngle->end()), maxWinding);
2027    #if DEBUG_WINDING
2028                    SkDebugf("%s [%d] inactive\n", __FUNCTION__, nextIndex);
2029    #endif
2030                    return NULL;
2031                }
2032                if (!foundAngle || foundDone) {
2033                    foundAngle = nextAngle;
2034                    foundDone = nextSegment->done(*nextAngle);
2035                    foundFlipped = altFlipped;
2036                    foundMax = maxWinding;
2037                }
2038                continue;
2039            }
2040            if (!maxWinding && (!foundAngle || foundDone2)) {
2041        #if DEBUG_WINDING
2042                if (foundAngle && foundDone2) {
2043                    SkDebugf("%s [%d] !foundAngle && foundDone2\n", __FUNCTION__, nextIndex);
2044                }
2045        #endif
2046                foundAngle = nextAngle;
2047                foundDone2 = nextSegment->done(*nextAngle);
2048                foundFlipped = altFlipped;
2049                foundSum = sumWinding;
2050            }
2051            if (nextSegment->done()) {
2052                continue;
2053            }
2054            // if the winding is non-zero, nextAngle does not connect to
2055            // current chain. If we haven't done so already, mark the angle
2056            // as done, record the winding value, and mark connected unambiguous
2057            // segments as well.
2058            if (nextSegment->windSum(nextAngle) == SK_MinS32) {
2059                if (useInnerWinding(maxWinding, sumWinding)) {
2060                    maxWinding = sumWinding;
2061                }
2062                Span* last;
2063                if (foundAngle) {
2064                    last = nextSegment->markAndChaseWinding(nextAngle, maxWinding);
2065                } else {
2066                    last = nextSegment->markAndChaseDone(nextAngle, maxWinding);
2067                }
2068                if (last) {
2069                    *chase.append() = last;
2070                }
2071            }
2072        } while (++nextIndex != lastIndex);
2073        markDone(SkMin32(startIndex, endIndex), outerWinding);
2074        if (!foundAngle) {
2075            return NULL;
2076        }
2077        nextStart = foundAngle->start();
2078        nextEnd = foundAngle->end();
2079        nextSegment = foundAngle->segment();
2080        int flipped = foundFlipped ? -1 : 1;
2081        spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue(
2082                SkMin32(nextStart, nextEnd));
2083        if (winding) {
2084    #if DEBUG_WINDING
2085            SkDebugf("%s ---6 winding=%d foundSum=", __FUNCTION__, winding);
2086            if (foundSum == SK_MinS32) {
2087                SkDebugf("?");
2088            } else {
2089                SkDebugf("%d", foundSum);
2090            }
2091            SkDebugf(" foundMax=");
2092            if (foundMax == SK_MinS32) {
2093                SkDebugf("?");
2094            } else {
2095                SkDebugf("%d", foundMax);
2096            }
2097            SkDebugf("\n");
2098     #endif
2099            winding = foundSum;
2100        }
2101    #if DEBUG_WINDING
2102        SkDebugf("%s spanWinding=%d flipped=%d\n", __FUNCTION__, spanWinding, flipped);
2103    #endif
2104        return nextSegment;
2105    }
2106
2107    Segment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable) {
2108        const int startIndex = nextStart;
2109        const int endIndex = nextEnd;
2110        SkASSERT(startIndex != endIndex);
2111        int count = fTs.count();
2112        SkASSERT(startIndex < endIndex ? startIndex < count - 1
2113                : startIndex > 0);
2114        int step = SkSign32(endIndex - startIndex);
2115    #if PRECISE_T_SORT
2116        int end = nextExactSpan(startIndex, step);
2117    #else
2118        int end = nextSpan(startIndex, step);
2119    #endif
2120        SkASSERT(end >= 0);
2121        Span* endSpan = &fTs[end];
2122        Segment* other;
2123        markDone(SkMin32(startIndex, endIndex), 1);
2124        if (isSimple(end)) {
2125    #if DEBUG_WINDING
2126            SkDebugf("%s simple\n", __FUNCTION__);
2127    #endif
2128            other = endSpan->fOther;
2129            nextStart = endSpan->fOtherIndex;
2130            double startT = other->fTs[nextStart].fT;
2131            SkDEBUGCODE(bool firstLoop = true;)
2132            if ((approximately_less_than_zero(startT) && step < 0)
2133                    || (approximately_greater_than_one(startT) && step > 0)) {
2134                step = -step;
2135                SkDEBUGCODE(firstLoop = false;)
2136            }
2137            do {
2138                nextEnd = nextStart;
2139                do {
2140                    nextEnd += step;
2141                }
2142    #if PRECISE_T_SORT
2143                 while (precisely_zero(startT - other->fTs[nextEnd].fT));
2144    #else
2145                 while (approximately_zero(startT - other->fTs[nextEnd].fT));
2146    #endif
2147                if (other->fTs[SkMin32(nextStart, nextEnd)].fWindValue) {
2148                    break;
2149                }
2150 #ifdef SK_DEBUG
2151                SkASSERT(firstLoop);
2152 #endif
2153                SkDEBUGCODE(firstLoop = false;)
2154                step = -step;
2155            } while (true);
2156            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
2157            return other;
2158        }
2159        SkTDArray<Angle> angles;
2160        SkASSERT(startIndex - endIndex != 0);
2161        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2162        addTwoAngles(startIndex, end, angles);
2163        buildAngles(end, angles);
2164        SkTDArray<Angle*> sorted;
2165        bool sortable = SortAngles(angles, sorted);
2166        int angleCount = angles.count();
2167        int firstIndex = findStartingEdge(sorted, startIndex, end);
2168        SkASSERT(firstIndex >= 0);
2169    #if DEBUG_SORT
2170        debugShowSort(__FUNCTION__, sorted, firstIndex, 0);
2171    #endif
2172        if (!sortable) {
2173            unsortable = true;
2174            return NULL;
2175        }
2176        SkASSERT(sorted[firstIndex]->segment() == this);
2177        int nextIndex = firstIndex + 1;
2178        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
2179        const Angle* nextAngle;
2180        Segment* nextSegment;
2181        do {
2182            if (nextIndex == angleCount) {
2183                nextIndex = 0;
2184            }
2185            nextAngle = sorted[nextIndex];
2186            nextSegment = nextAngle->segment();
2187            if (!nextSegment->done(*nextAngle)) {
2188                break;
2189            }
2190            if (++nextIndex == lastIndex) {
2191                return NULL;
2192            }
2193        } while (true);
2194        nextStart = nextAngle->start();
2195        nextEnd = nextAngle->end();
2196        return nextSegment;
2197    }
2198
2199    int findStartingEdge(SkTDArray<Angle*>& sorted, int start, int end) {
2200        int angleCount = sorted.count();
2201        int firstIndex = -1;
2202        for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2203            const Angle* angle = sorted[angleIndex];
2204            if (angle->segment() == this && angle->start() == end &&
2205                    angle->end() == start) {
2206                firstIndex = angleIndex;
2207                break;
2208            }
2209        }
2210        return firstIndex;
2211    }
2212
2213    // FIXME: this is tricky code; needs its own unit test
2214    void findTooCloseToCall(bool isXor) {
2215        int count = fTs.count();
2216        if (count < 3) { // require t=0, x, 1 at minimum
2217            return;
2218        }
2219        int matchIndex = 0;
2220        int moCount;
2221        Span* match;
2222        Segment* mOther;
2223        do {
2224            match = &fTs[matchIndex];
2225            mOther = match->fOther;
2226            // FIXME: allow quads, cubics to be near coincident?
2227            if (mOther->fVerb == SkPath::kLine_Verb) {
2228                moCount = mOther->fTs.count();
2229                if (moCount >= 3) {
2230                    break;
2231                }
2232            }
2233            if (++matchIndex >= count) {
2234                return;
2235            }
2236        } while (true); // require t=0, x, 1 at minimum
2237        // OPTIMIZATION: defer matchPt until qualifying toCount is found?
2238        const SkPoint* matchPt = &xyAtT(match);
2239        // look for a pair of nearby T values that map to the same (x,y) value
2240        // if found, see if the pair of other segments share a common point. If
2241        // so, the span from here to there is coincident.
2242        for (int index = matchIndex + 1; index < count; ++index) {
2243            Span* test = &fTs[index];
2244            if (test->fDone) {
2245                continue;
2246            }
2247            Segment* tOther = test->fOther;
2248            if (tOther->fVerb != SkPath::kLine_Verb) {
2249                continue; // FIXME: allow quads, cubics to be near coincident?
2250            }
2251            int toCount = tOther->fTs.count();
2252            if (toCount < 3) { // require t=0, x, 1 at minimum
2253                continue;
2254            }
2255            const SkPoint* testPt = &xyAtT(test);
2256            if (*matchPt != *testPt) {
2257                matchIndex = index;
2258                moCount = toCount;
2259                match = test;
2260                mOther = tOther;
2261                matchPt = testPt;
2262                continue;
2263            }
2264            int moStart = -1;
2265            int moEnd = -1;
2266            double moStartT, moEndT;
2267            for (int moIndex = 0; moIndex < moCount; ++moIndex) {
2268                Span& moSpan = mOther->fTs[moIndex];
2269                if (moSpan.fDone) {
2270                    continue;
2271                }
2272                if (moSpan.fOther == this) {
2273                    if (moSpan.fOtherT == match->fT) {
2274                        moStart = moIndex;
2275                        moStartT = moSpan.fT;
2276                    }
2277                    continue;
2278                }
2279                if (moSpan.fOther == tOther) {
2280                    if (tOther->fTs[moSpan.fOtherIndex].fWindValue == 0) {
2281                        moStart = -1;
2282                        break;
2283                    }
2284                    SkASSERT(moEnd == -1);
2285                    moEnd = moIndex;
2286                    moEndT = moSpan.fT;
2287                }
2288            }
2289            if (moStart < 0 || moEnd < 0) {
2290                continue;
2291            }
2292            // FIXME: if moStartT, moEndT are initialized to NaN, can skip this test
2293            if (approximately_equal(moStartT, moEndT)) {
2294                continue;
2295            }
2296            int toStart = -1;
2297            int toEnd = -1;
2298            double toStartT, toEndT;
2299            for (int toIndex = 0; toIndex < toCount; ++toIndex) {
2300                Span& toSpan = tOther->fTs[toIndex];
2301                if (toSpan.fDone) {
2302                    continue;
2303                }
2304                if (toSpan.fOther == this) {
2305                    if (toSpan.fOtherT == test->fT) {
2306                        toStart = toIndex;
2307                        toStartT = toSpan.fT;
2308                    }
2309                    continue;
2310                }
2311                if (toSpan.fOther == mOther && toSpan.fOtherT == moEndT) {
2312                    if (mOther->fTs[toSpan.fOtherIndex].fWindValue == 0) {
2313                        moStart = -1;
2314                        break;
2315                    }
2316                    SkASSERT(toEnd == -1);
2317                    toEnd = toIndex;
2318                    toEndT = toSpan.fT;
2319                }
2320            }
2321            // FIXME: if toStartT, toEndT are initialized to NaN, can skip this test
2322            if (toStart <= 0 || toEnd <= 0) {
2323                continue;
2324            }
2325            if (approximately_equal(toStartT, toEndT)) {
2326                continue;
2327            }
2328            // test to see if the segment between there and here is linear
2329            if (!mOther->isLinear(moStart, moEnd)
2330                    || !tOther->isLinear(toStart, toEnd)) {
2331                continue;
2332            }
2333            bool flipped = (moStart - moEnd) * (toStart - toEnd) < 1;
2334            if (flipped) {
2335                mOther->addTCancel(moStartT, moEndT, *tOther, toEndT, toStartT);
2336            } else {
2337                // FIXME: this is bogus for multiple ops
2338                // the xorMask needs to be accumulated from the union of the two
2339                // edges -- which means that the segment must have its own copy of the mask
2340                mOther->addTCoincident(isXor, moStartT, moEndT, *tOther, toStartT, toEndT);
2341            }
2342        }
2343    }
2344
2345 //   start here;
2346    // either:
2347    // a) mark spans with either end unsortable as done, or
2348    // b) rewrite findTop / findTopSegment / findTopContour to iterate further
2349    //    when encountering an unsortable span
2350
2351    // OPTIMIZATION : for a pair of lines, can we compute points at T (cached)
2352    // and use more concise logic like the old edge walker code?
2353    // FIXME: this needs to deal with coincident edges
2354    Segment* findTop(int& tIndex, int& endIndex) {
2355        // iterate through T intersections and return topmost
2356        // topmost tangent from y-min to first pt is closer to horizontal
2357        SkASSERT(!done());
2358        int firstT;
2359        int lastT;
2360        SkPoint topPt;
2361        topPt.fY = SK_ScalarMax;
2362        int count = fTs.count();
2363        // see if either end is not done since we want smaller Y of the pair
2364        bool lastDone = true;
2365        for (int index = 0; index < count; ++index) {
2366            const Span& span = fTs[index];
2367            if (!span.fDone || !lastDone) {
2368                const SkPoint& intercept = xyAtT(&span);
2369                if (topPt.fY > intercept.fY || (topPt.fY == intercept.fY
2370                        && topPt.fX > intercept.fX)) {
2371                    topPt = intercept;
2372                    firstT = lastT = index;
2373                } else if (topPt == intercept) {
2374                    lastT = index;
2375                }
2376            }
2377            lastDone = span.fDone;
2378        }
2379        // sort the edges to find the leftmost
2380        int step = 1;
2381        int end = nextSpan(firstT, step);
2382        if (end == -1) {
2383            step = -1;
2384            end = nextSpan(firstT, step);
2385            SkASSERT(end != -1);
2386        }
2387        // if the topmost T is not on end, or is three-way or more, find left
2388        // look for left-ness from tLeft to firstT (matching y of other)
2389        SkTDArray<Angle> angles;
2390        SkASSERT(firstT - end != 0);
2391        addTwoAngles(end, firstT, angles);
2392        buildAngles(firstT, angles);
2393        SkTDArray<Angle*> sorted;
2394        (void) SortAngles(angles, sorted);
2395    #if DEBUG_SORT
2396        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0);
2397    #endif
2398        // skip edges that have already been processed
2399        firstT = -1;
2400        Segment* leftSegment;
2401        do {
2402            const Angle* angle = sorted[++firstT];
2403            if (angle->unsortable()) {
2404                // FIXME: if all angles are unsortable, find next topmost
2405                if (firstT >= angles.count() - 1) {
2406    #if SORTABLE_CONTOURS
2407                    SkASSERT(0);
2408    #endif
2409                    return NULL;
2410                }
2411            }
2412            leftSegment = angle->segment();
2413            tIndex = angle->end();
2414            endIndex = angle->start();
2415        } while (leftSegment->fTs[SkMin32(tIndex, endIndex)].fDone);
2416        return leftSegment;
2417    }
2418
2419    // FIXME: not crazy about this
2420    // when the intersections are performed, the other index is into an
2421    // incomplete array. as the array grows, the indices become incorrect
2422    // while the following fixes the indices up again, it isn't smart about
2423    // skipping segments whose indices are already correct
2424    // assuming we leave the code that wrote the index in the first place
2425    void fixOtherTIndex() {
2426        int iCount = fTs.count();
2427        for (int i = 0; i < iCount; ++i) {
2428            Span& iSpan = fTs[i];
2429            double oT = iSpan.fOtherT;
2430            Segment* other = iSpan.fOther;
2431            int oCount = other->fTs.count();
2432            for (int o = 0; o < oCount; ++o) {
2433                Span& oSpan = other->fTs[o];
2434                if (oT == oSpan.fT && this == oSpan.fOther) {
2435                    iSpan.fOtherIndex = o;
2436                    break;
2437                }
2438            }
2439        }
2440    }
2441
2442    // OPTIMIZATION: uses tail recursion. Unwise?
2443    Span* innerChaseDone(int index, int step, int winding) {
2444        int end = nextExactSpan(index, step);
2445        SkASSERT(end >= 0);
2446        if (multipleSpans(end)) {
2447            return &fTs[end];
2448        }
2449        const Span& endSpan = fTs[end];
2450        Segment* other = endSpan.fOther;
2451        index = endSpan.fOtherIndex;
2452        int otherEnd = other->nextExactSpan(index, step);
2453        Span* last = other->innerChaseDone(index, step, winding);
2454        other->markDone(SkMin32(index, otherEnd), winding);
2455        return last;
2456    }
2457
2458    Span* innerChaseWinding(int index, int step, int winding) {
2459        int end = nextExactSpan(index, step);
2460        SkASSERT(end >= 0);
2461        if (multipleSpans(end)) {
2462            return &fTs[end];
2463        }
2464        const Span& endSpan = fTs[end];
2465        Segment* other = endSpan.fOther;
2466        index = endSpan.fOtherIndex;
2467        int otherEnd = other->nextExactSpan(index, step);
2468        int min = SkMin32(index, otherEnd);
2469        if (other->fTs[min].fWindSum != SK_MinS32) {
2470            SkASSERT(other->fTs[min].fWindSum == winding);
2471            return NULL;
2472        }
2473        Span* last = other->innerChaseWinding(index, step, winding);
2474        other->markWinding(min, winding);
2475        return last;
2476    }
2477
2478    void init(const SkPoint pts[], SkPath::Verb verb, bool operand) {
2479        fDoneSpans = 0;
2480        fOperand = operand;
2481        fPts = pts;
2482        fVerb = verb;
2483    }
2484
2485    bool intersected() const {
2486        return fTs.count() > 0;
2487    }
2488
2489    bool isConnected(int startIndex, int endIndex) const {
2490        return fTs[startIndex].fWindSum != SK_MinS32
2491                || fTs[endIndex].fWindSum != SK_MinS32;
2492    }
2493
2494    bool isHorizontal() const {
2495        return fBounds.fTop == fBounds.fBottom;
2496    }
2497
2498    bool isLinear(int start, int end) const {
2499        if (fVerb == SkPath::kLine_Verb) {
2500            return true;
2501        }
2502        if (fVerb == SkPath::kQuad_Verb) {
2503            SkPoint qPart[3];
2504            QuadSubDivide(fPts, fTs[start].fT, fTs[end].fT, qPart);
2505            return QuadIsLinear(qPart);
2506        } else {
2507            SkASSERT(fVerb == SkPath::kCubic_Verb);
2508            SkPoint cPart[4];
2509            CubicSubDivide(fPts, fTs[start].fT, fTs[end].fT, cPart);
2510            return CubicIsLinear(cPart);
2511        }
2512    }
2513
2514    // OPTIMIZE: successive calls could start were the last leaves off
2515    // or calls could specialize to walk forwards or backwards
2516    bool isMissing(double startT) const {
2517        size_t tCount = fTs.count();
2518        for (size_t index = 0; index < tCount; ++index) {
2519            if (approximately_zero(startT - fTs[index].fT)) {
2520                return false;
2521            }
2522        }
2523        return true;
2524    }
2525
2526    bool isSimple(int end) const {
2527        int count = fTs.count();
2528        if (count == 2) {
2529            return true;
2530        }
2531        double t = fTs[end].fT;
2532        if (approximately_less_than_zero(t)) {
2533            return !approximately_less_than_zero(fTs[1].fT);
2534        }
2535        if (approximately_greater_than_one(t)) {
2536            return !approximately_greater_than_one(fTs[count - 2].fT);
2537        }
2538        return false;
2539    }
2540
2541    bool isVertical() const {
2542        return fBounds.fLeft == fBounds.fRight;
2543    }
2544
2545    SkScalar leftMost(int start, int end) const {
2546        return (*SegmentLeftMost[fVerb])(fPts, fTs[start].fT, fTs[end].fT);
2547    }
2548
2549    // this span is excluded by the winding rule -- chase the ends
2550    // as long as they are unambiguous to mark connections as done
2551    // and give them the same winding value
2552    Span* markAndChaseDone(const Angle* angle, int winding) {
2553        int index = angle->start();
2554        int endIndex = angle->end();
2555        int step = SkSign32(endIndex - index);
2556        Span* last = innerChaseDone(index, step, winding);
2557        markDone(SkMin32(index, endIndex), winding);
2558        return last;
2559    }
2560
2561    Span* markAndChaseWinding(const Angle* angle, int winding) {
2562        int index = angle->start();
2563        int endIndex = angle->end();
2564        int min = SkMin32(index, endIndex);
2565        int step = SkSign32(endIndex - index);
2566        Span* last = innerChaseWinding(index, step, winding);
2567        markWinding(min, winding);
2568        return last;
2569    }
2570
2571    // FIXME: this should also mark spans with equal (x,y)
2572    // This may be called when the segment is already marked done. While this
2573    // wastes time, it shouldn't do any more than spin through the T spans.
2574    // OPTIMIZATION: abort on first done found (assuming that this code is
2575    // always called to mark segments done).
2576    void markDone(int index, int winding) {
2577      //  SkASSERT(!done());
2578        SkASSERT(winding);
2579        double referenceT = fTs[index].fT;
2580        int lesser = index;
2581    #if PRECISE_T_SORT
2582        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2583            markOneDone(__FUNCTION__, lesser, winding);
2584        }
2585        do {
2586            markOneDone(__FUNCTION__, index, winding);
2587        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
2588    #else
2589        while (--lesser >= 0 && approximately_negative(referenceT - fTs[lesser].fT)) {
2590            markOneDone(__FUNCTION__, lesser, winding);
2591        }
2592        do {
2593            markOneDone(__FUNCTION__, index, winding);
2594        } while (++index < fTs.count() && approximately_negative(fTs[index].fT - referenceT));
2595    #endif
2596    }
2597
2598    void markOneDone(const char* funName, int tIndex, int winding) {
2599        Span* span = markOneWinding(funName, tIndex, winding);
2600        if (!span) {
2601            return;
2602        }
2603        span->fDone = true;
2604        fDoneSpans++;
2605    }
2606
2607    Span* markOneWinding(const char* funName, int tIndex, int winding) {
2608        Span& span = fTs[tIndex];
2609        if (span.fDone) {
2610            return NULL;
2611        }
2612    #if DEBUG_MARK_DONE
2613        debugShowNewWinding(funName, span, winding);
2614    #endif
2615        SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
2616   #ifdef SK_DEBUG
2617        SkASSERT(abs(winding) <= gDebugMaxWindSum);
2618   #endif
2619        span.fWindSum = winding;
2620        return &span;
2621    }
2622
2623    void markUnsortable(int start, int end) {
2624        Span* span = &fTs[start];
2625        if (start < end) {
2626            span->fUnsortableStart = true;
2627        } else {
2628            --span;
2629            span->fUnsortableEnd = true;
2630        }
2631        if (span->fDone) {
2632            return;
2633        }
2634        span->fDone = true;
2635        fDoneSpans++;
2636    }
2637
2638    void markWinding(int index, int winding) {
2639    //    SkASSERT(!done());
2640        SkASSERT(winding);
2641        double referenceT = fTs[index].fT;
2642        int lesser = index;
2643    #if PRECISE_T_SORT
2644        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
2645            markOneWinding(__FUNCTION__, lesser, winding);
2646        }
2647        do {
2648            markOneWinding(__FUNCTION__, index, winding);
2649       } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
2650    #else
2651        while (--lesser >= 0 && approximately_negative(referenceT - fTs[lesser].fT)) {
2652            markOneWinding(__FUNCTION__, lesser, winding);
2653        }
2654        do {
2655            markOneWinding(__FUNCTION__, index, winding);
2656       } while (++index < fTs.count() && approximately_negative(fTs[index].fT - referenceT));
2657    #endif
2658    }
2659
2660    void matchWindingValue(int tIndex, double t, bool borrowWind) {
2661        int nextDoorWind = SK_MaxS32;
2662        if (tIndex > 0) {
2663            const Span& below = fTs[tIndex - 1];
2664            if (approximately_negative(t - below.fT)) {
2665                nextDoorWind = below.fWindValue;
2666            }
2667        }
2668        if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
2669            const Span& above = fTs[tIndex + 1];
2670            if (approximately_negative(above.fT - t)) {
2671                nextDoorWind = above.fWindValue;
2672            }
2673        }
2674        if (nextDoorWind == SK_MaxS32 && borrowWind && tIndex > 0 && t < 1) {
2675            const Span& below = fTs[tIndex - 1];
2676            nextDoorWind = below.fWindValue;
2677        }
2678        if (nextDoorWind != SK_MaxS32) {
2679            Span& newSpan = fTs[tIndex];
2680            newSpan.fWindValue = nextDoorWind;
2681            if (!nextDoorWind) {
2682                newSpan.fDone = true;
2683                ++fDoneSpans;
2684            }
2685        }
2686    }
2687
2688    // return span if when chasing, two or more radiating spans are not done
2689    // OPTIMIZATION: ? multiple spans is detected when there is only one valid
2690    // candidate and the remaining spans have windValue == 0 (canceled by
2691    // coincidence). The coincident edges could either be removed altogether,
2692    // or this code could be more complicated in detecting this case. Worth it?
2693    bool multipleSpans(int end) const {
2694        return end > 0 && end < fTs.count() - 1;
2695    }
2696
2697    // This has callers for two different situations: one establishes the end
2698    // of the current span, and one establishes the beginning of the next span
2699    // (thus the name). When this is looking for the end of the current span,
2700    // coincidence is found when the beginning Ts contain -step and the end
2701    // contains step. When it is looking for the beginning of the next, the
2702    // first Ts found can be ignored and the last Ts should contain -step.
2703    // OPTIMIZATION: probably should split into two functions
2704    int nextSpan(int from, int step) const {
2705        const Span& fromSpan = fTs[from];
2706        int count = fTs.count();
2707        int to = from;
2708        while (step > 0 ? ++to < count : --to >= 0) {
2709            const Span& span = fTs[to];
2710            if (approximately_zero(span.fT - fromSpan.fT)) {
2711                continue;
2712            }
2713            return to;
2714        }
2715        return -1;
2716    }
2717
2718#if PRECISE_T_SORT
2719    // FIXME
2720    // this returns at any difference in T, vs. a preset minimum. It may be
2721    // that all callers to nextSpan should use this instead.
2722    // OPTIMIZATION splitting this into separate loops for up/down steps
2723    // would allow using precisely_negative instead of precisely_zero
2724    int nextExactSpan(int from, int step) const {
2725        const Span& fromSpan = fTs[from];
2726        int count = fTs.count();
2727        int to = from;
2728        while (step > 0 ? ++to < count : --to >= 0) {
2729            const Span& span = fTs[to];
2730            if (precisely_zero(span.fT - fromSpan.fT)) {
2731                continue;
2732            }
2733            return to;
2734        }
2735        return -1;
2736    }
2737#endif
2738
2739    bool operand() const {
2740        return fOperand;
2741    }
2742
2743    int oppSign(int startIndex, int endIndex) const {
2744        int result = startIndex < endIndex ? -fTs[startIndex].fWindValueOpp :
2745                fTs[endIndex].fWindValueOpp;
2746#if DEBUG_WIND_BUMP
2747        SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
2748#endif
2749        return result;
2750    }
2751
2752    const SkPoint* pts() const {
2753        return fPts;
2754    }
2755
2756    void reset() {
2757        init(NULL, (SkPath::Verb) -1, false);
2758        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
2759        fTs.reset();
2760    }
2761
2762    static bool SortAngles(SkTDArray<Angle>& angles, SkTDArray<Angle*>& angleList) {
2763        int angleCount = angles.count();
2764        int angleIndex;
2765        angleList.setReserve(angleCount);
2766        for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2767            *angleList.append() = &angles[angleIndex];
2768        }
2769        QSort<Angle>(angleList.begin(), angleList.end() - 1);
2770        bool result = true;
2771        for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2772            Angle& angle = angles[angleIndex];
2773            if (angle.unsortable()) {
2774                // so that it is available for early exclusion in findTop and others
2775                angle.segment()->markUnsortable(angle.start(), angle.end());
2776                result = false;
2777            }
2778        }
2779        return result;
2780    }
2781
2782    // OPTIMIZATION: mark as debugging only if used solely by tests
2783    const Span& span(int tIndex) const {
2784        return fTs[tIndex];
2785    }
2786
2787    int spanSign(const Angle* angle) const {
2788        SkASSERT(angle->segment() == this);
2789        return spanSign(angle->start(), angle->end());
2790    }
2791
2792    int spanSign(int startIndex, int endIndex) const {
2793        int result = startIndex < endIndex ? -fTs[startIndex].fWindValue :
2794                fTs[endIndex].fWindValue;
2795#if DEBUG_WIND_BUMP
2796        SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
2797#endif
2798        return result;
2799    }
2800
2801    // OPTIMIZATION: mark as debugging only if used solely by tests
2802    double t(int tIndex) const {
2803        return fTs[tIndex].fT;
2804    }
2805
2806    static void TrackOutside(SkTDArray<double>& outsideTs, double end,
2807            double start) {
2808        int outCount = outsideTs.count();
2809        if (outCount == 0 || !approximately_negative(end - outsideTs[outCount - 2])) {
2810            *outsideTs.append() = end;
2811            *outsideTs.append() = start;
2812        }
2813    }
2814
2815    void undoneSpan(int& start, int& end) {
2816        size_t tCount = fTs.count();
2817        size_t index;
2818        for (index = 0; index < tCount; ++index) {
2819            if (!fTs[index].fDone) {
2820                break;
2821            }
2822        }
2823        SkASSERT(index < tCount - 1);
2824        start = index;
2825        double startT = fTs[index].fT;
2826        while (approximately_negative(fTs[++index].fT - startT))
2827            SkASSERT(index < tCount);
2828        SkASSERT(index < tCount);
2829        end = index;
2830    }
2831
2832    bool unsortable(int index) const {
2833        return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
2834    }
2835
2836    void updatePts(const SkPoint pts[]) {
2837        fPts = pts;
2838    }
2839
2840    SkPath::Verb verb() const {
2841        return fVerb;
2842    }
2843
2844    int windSum(int tIndex) const {
2845        return fTs[tIndex].fWindSum;
2846    }
2847
2848    int windSum(const Angle* angle) const {
2849        int start = angle->start();
2850        int end = angle->end();
2851        int index = SkMin32(start, end);
2852        return windSum(index);
2853    }
2854
2855    int windValue(int tIndex) const {
2856        return fTs[tIndex].fWindValue;
2857    }
2858
2859    int windValue(const Angle* angle) const {
2860        int start = angle->start();
2861        int end = angle->end();
2862        int index = SkMin32(start, end);
2863        return windValue(index);
2864    }
2865
2866    SkScalar xAtT(const Span* span) const {
2867        return xyAtT(span).fX;
2868    }
2869
2870    const SkPoint& xyAtT(int index) const {
2871        return xyAtT(&fTs[index]);
2872    }
2873
2874    const SkPoint& xyAtT(const Span* span) const {
2875        if (SkScalarIsNaN(span->fPt.fX)) {
2876            if (span->fT == 0) {
2877                span->fPt = fPts[0];
2878            } else if (span->fT == 1) {
2879                span->fPt = fPts[fVerb];
2880            } else {
2881                (*SegmentXYAtT[fVerb])(fPts, span->fT, &span->fPt);
2882            }
2883        }
2884        return span->fPt;
2885    }
2886
2887    SkScalar yAtT(int index) const {
2888        return yAtT(&fTs[index]);
2889    }
2890
2891    SkScalar yAtT(const Span* span) const {
2892        return xyAtT(span).fY;
2893    }
2894
2895#if DEBUG_DUMP
2896    void dump() const {
2897        const char className[] = "Segment";
2898        const int tab = 4;
2899        for (int i = 0; i < fTs.count(); ++i) {
2900            SkPoint out;
2901            (*SegmentXYAtT[fVerb])(fPts, t(i), &out);
2902            SkDebugf("%*s [%d] %s.fTs[%d]=%1.9g (%1.9g,%1.9g) other=%d"
2903                    " otherT=%1.9g windSum=%d\n",
2904                    tab + sizeof(className), className, fID,
2905                    kLVerbStr[fVerb], i, fTs[i].fT, out.fX, out.fY,
2906                    fTs[i].fOther->fID, fTs[i].fOtherT, fTs[i].fWindSum);
2907        }
2908        SkDebugf("%*s [%d] fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)",
2909                tab + sizeof(className), className, fID,
2910                fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
2911    }
2912#endif
2913
2914#if DEBUG_CONCIDENT
2915    // assert if pair has not already been added
2916     void debugAddTPair(double t, const Segment& other, double otherT) const {
2917        for (int i = 0; i < fTs.count(); ++i) {
2918            if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
2919                return;
2920            }
2921        }
2922        SkASSERT(0);
2923     }
2924#endif
2925
2926#if DEBUG_DUMP
2927    int debugID() const {
2928        return fID;
2929    }
2930#endif
2931
2932#if DEBUG_WINDING
2933    void debugShowSums() const {
2934        SkDebugf("%s id=%d (%1.9g,%1.9g %1.9g,%1.9g)", __FUNCTION__, fID,
2935            fPts[0].fX, fPts[0].fY, fPts[fVerb].fX, fPts[fVerb].fY);
2936        for (int i = 0; i < fTs.count(); ++i) {
2937            const Span& span = fTs[i];
2938            SkDebugf(" [t=%1.3g %1.9g,%1.9g w=", span.fT, xAtT(&span), yAtT(&span));
2939            if (span.fWindSum == SK_MinS32) {
2940                SkDebugf("?");
2941            } else {
2942                SkDebugf("%d", span.fWindSum);
2943            }
2944            SkDebugf("]");
2945        }
2946        SkDebugf("\n");
2947    }
2948#endif
2949
2950#if DEBUG_CONCIDENT
2951    void debugShowTs() const {
2952        SkDebugf("%s id=%d", __FUNCTION__, fID);
2953        for (int i = 0; i < fTs.count(); ++i) {
2954            SkDebugf(" [o=%d t=%1.3g %1.9g,%1.9g w=%d]", fTs[i].fOther->fID,
2955                    fTs[i].fT, xAtT(&fTs[i]), yAtT(&fTs[i]), fTs[i].fWindValue);
2956        }
2957        SkDebugf("\n");
2958    }
2959#endif
2960
2961#if DEBUG_ACTIVE_SPANS
2962    void debugShowActiveSpans() const {
2963        if (done()) {
2964            return;
2965        }
2966        for (int i = 0; i < fTs.count(); ++i) {
2967            if (fTs[i].fDone) {
2968                continue;
2969            }
2970            SkDebugf("%s id=%d", __FUNCTION__, fID);
2971            SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
2972            for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
2973                SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
2974            }
2975            const Span* span = &fTs[i];
2976            SkDebugf(") t=%1.9g (%1.9g,%1.9g)", fTs[i].fT,
2977                     xAtT(span), yAtT(span));
2978            const Segment* other = fTs[i].fOther;
2979            SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
2980                    other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
2981            if (fTs[i].fWindSum == SK_MinS32) {
2982                SkDebugf("?");
2983            } else {
2984                SkDebugf("%d", fTs[i].fWindSum);
2985            }
2986            SkDebugf(" windValue=%d\n", fTs[i].fWindValue);
2987        }
2988    }
2989
2990    // This isn't useful yet -- but leaving it in for now in case i think of something
2991    // to use it for
2992    void validateActiveSpans() const {
2993        if (done()) {
2994            return;
2995        }
2996        int tCount = fTs.count();
2997        for (int index = 0; index < tCount; ++index) {
2998            if (fTs[index].fDone) {
2999                continue;
3000            }
3001            // count number of connections which are not done
3002            int first = index;
3003            double baseT = fTs[index].fT;
3004            while (first > 0 && approximately_equal(fTs[first - 1].fT, baseT)) {
3005                --first;
3006            }
3007            int last = index;
3008            while (last < tCount - 1 && approximately_equal(fTs[last + 1].fT, baseT)) {
3009                ++last;
3010            }
3011            int connections = 0;
3012            connections += first > 0 && !fTs[first - 1].fDone;
3013            for (int test = first; test <= last; ++test) {
3014                connections += !fTs[test].fDone;
3015                const Segment* other = fTs[test].fOther;
3016                int oIndex = fTs[test].fOtherIndex;
3017                connections += !other->fTs[oIndex].fDone;
3018                connections += oIndex > 0 && !other->fTs[oIndex - 1].fDone;
3019            }
3020      //      SkASSERT(!(connections & 1));
3021        }
3022    }
3023#endif
3024
3025#if DEBUG_MARK_DONE
3026    void debugShowNewWinding(const char* fun, const Span& span, int winding) {
3027        const SkPoint& pt = xyAtT(&span);
3028        SkDebugf("%s id=%d", fun, fID);
3029        SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3030        for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
3031            SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3032        }
3033        SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
3034                fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
3035        SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) newWindSum=%d windSum=",
3036                span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY, winding);
3037        if (span.fWindSum == SK_MinS32) {
3038            SkDebugf("?");
3039        } else {
3040            SkDebugf("%d", span.fWindSum);
3041        }
3042        SkDebugf(" windValue=%d\n", span.fWindValue);
3043    }
3044#endif
3045
3046#if DEBUG_SORT
3047    void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first,
3048            const int contourWinding) const {
3049        SkASSERT(angles[first]->segment() == this);
3050        SkASSERT(angles.count() > 1);
3051        int lastSum = contourWinding;
3052        int windSum = lastSum - spanSign(angles[first]);
3053        SkDebugf("%s %s contourWinding=%d sign=%d\n", fun, __FUNCTION__,
3054                contourWinding, spanSign(angles[first]));
3055        int index = first;
3056        bool firstTime = true;
3057        do {
3058            const Angle& angle = *angles[index];
3059            const Segment& segment = *angle.segment();
3060            int start = angle.start();
3061            int end = angle.end();
3062            const Span& sSpan = segment.fTs[start];
3063            const Span& eSpan = segment.fTs[end];
3064            const Span& mSpan = segment.fTs[SkMin32(start, end)];
3065            if (!firstTime) {
3066                lastSum = windSum;
3067                windSum -= segment.spanSign(&angle);
3068            }
3069            SkDebugf("%s [%d] %sid=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)"
3070                    " sign=%d windValue=%d windSum=",
3071                    __FUNCTION__, index, angle.unsortable() ? "*** UNSORTABLE *** " : "",
3072                    segment.fID, kLVerbStr[segment.fVerb],
3073                    start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
3074                    segment.xAtT(&eSpan), segment.yAtT(&eSpan), angle.sign(),
3075                    mSpan.fWindValue);
3076            if (mSpan.fWindSum == SK_MinS32) {
3077                SkDebugf("?");
3078            } else {
3079                SkDebugf("%d", mSpan.fWindSum);
3080            }
3081            SkDebugf(" winding: %d->%d (max=%d) done=%d\n", lastSum, windSum,
3082                    useInnerWinding(lastSum, windSum) ? windSum : lastSum,
3083                    mSpan.fDone);
3084#if false && DEBUG_ANGLE
3085            angle.debugShow(segment.xyAtT(&sSpan));
3086#endif
3087            ++index;
3088            if (index == angles.count()) {
3089                index = 0;
3090            }
3091            if (firstTime) {
3092                firstTime = false;
3093            }
3094        } while (index != first);
3095    }
3096#endif
3097
3098#if DEBUG_WINDING
3099    bool debugVerifyWinding(int start, int end, int winding) const {
3100        const Span& span = fTs[SkMin32(start, end)];
3101        int spanWinding = span.fWindSum;
3102        if (spanWinding == SK_MinS32) {
3103            return true;
3104        }
3105        int spanSign = SkSign32(start - end);
3106        int signedVal = spanSign * span.fWindValue;
3107        if (signedVal < 0) {
3108            spanWinding -= signedVal;
3109        }
3110        return span.fWindSum == winding;
3111    }
3112#endif
3113
3114private:
3115    const SkPoint* fPts;
3116    SkPath::Verb fVerb;
3117    Bounds fBounds;
3118    SkTDArray<Span> fTs; // two or more (always includes t=0 t=1)
3119    int fDoneSpans; // quick check that segment is finished
3120    bool fOperand;
3121#if DEBUG_DUMP
3122    int fID;
3123#endif
3124};
3125
3126class Contour;
3127
3128struct Coincidence {
3129    Contour* fContours[2];
3130    int fSegments[2];
3131    double fTs[2][2];
3132    bool fXor;
3133};
3134
3135class Contour {
3136public:
3137    Contour() {
3138        reset();
3139#if DEBUG_DUMP
3140        fID = ++gContourID;
3141#endif
3142    }
3143
3144    bool operator<(const Contour& rh) const {
3145        return fBounds.fTop == rh.fBounds.fTop
3146                ? fBounds.fLeft < rh.fBounds.fLeft
3147                : fBounds.fTop < rh.fBounds.fTop;
3148    }
3149
3150    void addCoincident(int index, Contour* other, int otherIndex,
3151            const Intersections& ts, bool swap) {
3152        Coincidence& coincidence = *fCoincidences.append();
3153        coincidence.fContours[0] = this;
3154        coincidence.fContours[1] = other;
3155        coincidence.fSegments[0] = index;
3156        coincidence.fSegments[1] = otherIndex;
3157        if (fSegments[index].verb() == SkPath::kLine_Verb &&
3158                other->fSegments[otherIndex].verb() == SkPath::kLine_Verb) {
3159            // FIXME: coincident lines use legacy Ts instead of coincident Ts
3160            coincidence.fTs[swap][0] = ts.fT[0][0];
3161            coincidence.fTs[swap][1] = ts.fT[0][1];
3162            coincidence.fTs[!swap][0] = ts.fT[1][0];
3163            coincidence.fTs[!swap][1] = ts.fT[1][1];
3164        } else if (fSegments[index].verb() == SkPath::kQuad_Verb &&
3165                other->fSegments[otherIndex].verb() == SkPath::kQuad_Verb) {
3166            coincidence.fTs[swap][0] = ts.fCoincidentT[0][0];
3167            coincidence.fTs[swap][1] = ts.fCoincidentT[0][1];
3168            coincidence.fTs[!swap][0] = ts.fCoincidentT[1][0];
3169            coincidence.fTs[!swap][1] = ts.fCoincidentT[1][1];
3170        }
3171        coincidence.fXor = fOperand == other->fOperand ? fXor : true;
3172    }
3173
3174    void addCross(const Contour* crosser) {
3175#ifdef DEBUG_CROSS
3176        for (int index = 0; index < fCrosses.count(); ++index) {
3177            SkASSERT(fCrosses[index] != crosser);
3178        }
3179#endif
3180        *fCrosses.append() = crosser;
3181    }
3182
3183    void addCubic(const SkPoint pts[4]) {
3184        fSegments.push_back().addCubic(pts, fOperand);
3185        fContainsCurves = true;
3186    }
3187
3188    int addLine(const SkPoint pts[2]) {
3189        fSegments.push_back().addLine(pts, fOperand);
3190        return fSegments.count();
3191    }
3192
3193    void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
3194        fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
3195    }
3196
3197    int addQuad(const SkPoint pts[3]) {
3198        fSegments.push_back().addQuad(pts, fOperand);
3199        fContainsCurves = true;
3200        return fSegments.count();
3201    }
3202
3203    int addT(int segIndex, double newT, Contour* other, int otherIndex) {
3204        containsIntercepts();
3205        return fSegments[segIndex].addT(newT, &other->fSegments[otherIndex]);
3206    }
3207
3208    const Bounds& bounds() const {
3209        return fBounds;
3210    }
3211
3212    void collapseTriangles() {
3213        int segmentCount = fSegments.count();
3214        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
3215            fSegments[sIndex].collapseTriangles(fXor);
3216        }
3217    }
3218
3219    void complete() {
3220        setBounds();
3221        fContainsIntercepts = false;
3222    }
3223
3224    void containsIntercepts() {
3225        fContainsIntercepts = true;
3226    }
3227
3228    const Segment* crossedSegment(const SkPoint& basePt, SkScalar& bestY,
3229            int &tIndex, double& hitT) {
3230        int segmentCount = fSegments.count();
3231        const Segment* bestSegment = NULL;
3232        for (int test = 0; test < segmentCount; ++test) {
3233            Segment* testSegment = &fSegments[test];
3234            const SkRect& bounds = testSegment->bounds();
3235            if (bounds.fBottom <= bestY) {
3236                continue;
3237            }
3238            if (bounds.fTop >= basePt.fY) {
3239                continue;
3240            }
3241            if (bounds.fLeft > basePt.fX) {
3242                continue;
3243            }
3244            if (bounds.fRight < basePt.fX) {
3245                continue;
3246            }
3247            if (bounds.fLeft == bounds.fRight) {
3248                continue;
3249            }
3250     #if 0
3251            bool leftHalf = bounds.fLeft == basePt.fX;
3252            bool rightHalf = bounds.fRight == basePt.fX;
3253            if ((leftHalf || rightHalf) && !testSegment->crossedSpanHalves(
3254                    basePt, leftHalf, rightHalf)) {
3255                continue;
3256            }
3257     #endif
3258            double testHitT;
3259            int testT = testSegment->crossedSpan(basePt, bestY, testHitT);
3260            if (testT >= 0) {
3261                bestSegment = testSegment;
3262                tIndex = testT;
3263                hitT = testHitT;
3264            }
3265        }
3266        return bestSegment;
3267    }
3268
3269    bool crosses(const Contour* crosser) const {
3270        for (int index = 0; index < fCrosses.count(); ++index) {
3271            if (fCrosses[index] == crosser) {
3272                return true;
3273            }
3274        }
3275        return false;
3276    }
3277
3278    void findTooCloseToCall() {
3279        int segmentCount = fSegments.count();
3280        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
3281            fSegments[sIndex].findTooCloseToCall(fXor);
3282        }
3283    }
3284
3285    void fixOtherTIndex() {
3286        int segmentCount = fSegments.count();
3287        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
3288            fSegments[sIndex].fixOtherTIndex();
3289        }
3290    }
3291
3292    void reset() {
3293        fSegments.reset();
3294        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
3295        fContainsCurves = fContainsIntercepts = false;
3296    }
3297
3298    // FIXME: for binary ops, need to keep both ops winding contributions separately
3299    // in edge array
3300    void resolveCoincidence() {
3301        int count = fCoincidences.count();
3302        for (int index = 0; index < count; ++index) {
3303            Coincidence& coincidence = fCoincidences[index];
3304            Contour* thisContour = coincidence.fContours[0];
3305            Contour* otherContour = coincidence.fContours[1];
3306            int thisIndex = coincidence.fSegments[0];
3307            int otherIndex = coincidence.fSegments[1];
3308            Segment& thisOne = thisContour->fSegments[thisIndex];
3309            Segment& other = otherContour->fSegments[otherIndex];
3310        #if DEBUG_CONCIDENT
3311            thisOne.debugShowTs();
3312            other.debugShowTs();
3313        #endif
3314            double startT = coincidence.fTs[0][0];
3315            double endT = coincidence.fTs[0][1];
3316            bool opposite = false;
3317            if (startT > endT) {
3318                SkTSwap<double>(startT, endT);
3319                opposite ^= true;
3320            }
3321            SkASSERT(!approximately_negative(endT - startT));
3322            double oStartT = coincidence.fTs[1][0];
3323            double oEndT = coincidence.fTs[1][1];
3324            if (oStartT > oEndT) {
3325                SkTSwap<double>(oStartT, oEndT);
3326                opposite ^= true;
3327            }
3328            SkASSERT(!approximately_negative(oEndT - oStartT));
3329            if (opposite) {
3330                        // make sure startT and endT have t entries
3331                SkASSERT(opposite);
3332                if (startT > 0 || oEndT < 1
3333                        || thisOne.isMissing(startT) || other.isMissing(oEndT)) {
3334                    thisOne.addTPair(startT, other, oEndT, true);
3335                }
3336                if (oStartT > 0 || endT < 1
3337                        || thisOne.isMissing(endT) || other.isMissing(oStartT)) {
3338                    other.addTPair(oStartT, thisOne, endT, true);
3339                }
3340                thisOne.addTCancel(startT, endT, other, oStartT, oEndT);
3341            } else {
3342                if (startT > 0 || oStartT > 0
3343                        || thisOne.isMissing(startT) || other.isMissing(oStartT)) {
3344                    thisOne.addTPair(startT, other, oStartT, true);
3345                }
3346                if (endT < 1 || oEndT < 1
3347                        || thisOne.isMissing(endT) || other.isMissing(oEndT)) {
3348                    other.addTPair(oEndT, thisOne, endT, true);
3349                }
3350                thisOne.addTCoincident(coincidence.fXor, startT, endT, other, oStartT, oEndT);
3351            }
3352        #if DEBUG_CONCIDENT
3353            thisOne.debugShowTs();
3354            other.debugShowTs();
3355        #endif
3356        }
3357    }
3358
3359    const SkTArray<Segment>& segments() {
3360        return fSegments;
3361    }
3362
3363    void setOperand(bool isOp) {
3364        fOperand = isOp;
3365    }
3366
3367    void setXor(bool isXor) {
3368        fXor = isXor;
3369    }
3370
3371#if !SORTABLE_CONTOURS
3372    void sortSegments() {
3373        int segmentCount = fSegments.count();
3374        fSortedSegments.setReserve(segmentCount);
3375        for (int test = 0; test < segmentCount; ++test) {
3376            *fSortedSegments.append() = &fSegments[test];
3377        }
3378        QSort<Segment>(fSortedSegments.begin(), fSortedSegments.end() - 1);
3379        fFirstSorted = 0;
3380    }
3381#endif
3382
3383    // OPTIMIZATION: feel pretty uneasy about this. It seems like once again
3384    // we need to sort and walk edges in y, but that on the surface opens the
3385    // same can of worms as before. But then, this is a rough sort based on
3386    // segments' top, and not a true sort, so it could be ameniable to regular
3387    // sorting instead of linear searching. Still feel like I'm missing something
3388    Segment* topSegment(SkScalar& bestY) {
3389        int segmentCount = fSegments.count();
3390        SkASSERT(segmentCount > 0);
3391        int best = -1;
3392        Segment* bestSegment = NULL;
3393        while (++best < segmentCount) {
3394            Segment* testSegment = &fSegments[best];
3395            if (testSegment->done()) {
3396                continue;
3397            }
3398            bestSegment = testSegment;
3399            break;
3400        }
3401        if (!bestSegment) {
3402            return NULL;
3403        }
3404        SkScalar bestTop = bestSegment->activeTop();
3405        for (int test = best + 1; test < segmentCount; ++test) {
3406            Segment* testSegment = &fSegments[test];
3407            if (testSegment->done()) {
3408                continue;
3409            }
3410            if (testSegment->bounds().fTop > bestTop) {
3411                continue;
3412            }
3413            SkScalar testTop = testSegment->activeTop();
3414            if (bestTop > testTop) {
3415                bestTop = testTop;
3416                bestSegment = testSegment;
3417            }
3418        }
3419        bestY = bestTop;
3420        return bestSegment;
3421    }
3422
3423#if !SORTABLE_CONTOURS
3424    Segment* topSortableSegment(SkScalar& bestY) {
3425        int segmentCount = fSortedSegments.count();
3426        SkASSERT(segmentCount > 0);
3427        Segment* bestSegment = NULL;
3428        while (fFirstSorted < segmentCount) {
3429            Segment* testSegment = fSortedSegments[fFirstSorted];
3430            if (testSegment->done()) {
3431                fFirstSorted++;
3432                continue;
3433            }
3434            bestSegment = testSegment;
3435            break;
3436        }
3437        if (!bestSegment) {
3438            return NULL;
3439        }
3440        bestY = bestSegment->activeTop();
3441        return bestSegment;
3442    }
3443#endif
3444
3445    Segment* undoneSegment(int& start, int& end) {
3446        int segmentCount = fSegments.count();
3447        for (int test = 0; test < segmentCount; ++test) {
3448            Segment* testSegment = &fSegments[test];
3449            if (testSegment->done()) {
3450                continue;
3451            }
3452            testSegment->undoneSpan(start, end);
3453            return testSegment;
3454        }
3455        return NULL;
3456    }
3457
3458    int updateSegment(int index, const SkPoint* pts) {
3459        Segment& segment = fSegments[index];
3460        segment.updatePts(pts);
3461        return segment.verb() + 1;
3462    }
3463
3464#if DEBUG_TEST
3465    SkTArray<Segment>& debugSegments() {
3466        return fSegments;
3467    }
3468#endif
3469
3470#if DEBUG_DUMP
3471    void dump() {
3472        int i;
3473        const char className[] = "Contour";
3474        const int tab = 4;
3475        SkDebugf("%s %p (contour=%d)\n", className, this, fID);
3476        for (i = 0; i < fSegments.count(); ++i) {
3477            SkDebugf("%*s.fSegments[%d]:\n", tab + sizeof(className),
3478                    className, i);
3479            fSegments[i].dump();
3480        }
3481        SkDebugf("%*s.fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)\n",
3482                tab + sizeof(className), className,
3483                fBounds.fLeft, fBounds.fTop,
3484                fBounds.fRight, fBounds.fBottom);
3485        SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className),
3486                className, fContainsIntercepts);
3487        SkDebugf("%*s.fContainsCurves=%d\n", tab + sizeof(className),
3488                className, fContainsCurves);
3489    }
3490#endif
3491
3492#if DEBUG_ACTIVE_SPANS
3493    void debugShowActiveSpans() {
3494        for (int index = 0; index < fSegments.count(); ++index) {
3495            fSegments[index].debugShowActiveSpans();
3496        }
3497    }
3498
3499    void validateActiveSpans() {
3500        for (int index = 0; index < fSegments.count(); ++index) {
3501            fSegments[index].validateActiveSpans();
3502        }
3503    }
3504#endif
3505
3506protected:
3507    void setBounds() {
3508        int count = fSegments.count();
3509        if (count == 0) {
3510            SkDebugf("%s empty contour\n", __FUNCTION__);
3511            SkASSERT(0);
3512            // FIXME: delete empty contour?
3513            return;
3514        }
3515        fBounds = fSegments.front().bounds();
3516        for (int index = 1; index < count; ++index) {
3517            fBounds.add(fSegments[index].bounds());
3518        }
3519    }
3520
3521private:
3522    SkTArray<Segment> fSegments;
3523#if !SORTABLE_CONTOURS
3524    SkTDArray<Segment*> fSortedSegments;
3525    int fFirstSorted;
3526#endif
3527    SkTDArray<Coincidence> fCoincidences;
3528    SkTDArray<const Contour*> fCrosses;
3529    Bounds fBounds;
3530    bool fContainsIntercepts;
3531    bool fContainsCurves;
3532    bool fOperand; // true for the second argument to a binary operator
3533    bool fXor;
3534#if DEBUG_DUMP
3535    int fID;
3536#endif
3537};
3538
3539class EdgeBuilder {
3540public:
3541
3542EdgeBuilder(const SkPath& path, SkTArray<Contour>& contours)
3543    : fPath(&path)
3544    , fContours(contours)
3545    , fCurrentContour(NULL)
3546    , fOperand(false)
3547{
3548    fXorMask = (path.getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
3549#if DEBUG_DUMP
3550    gContourID = 0;
3551    gSegmentID = 0;
3552#endif
3553    fSecondHalf = preFetch();
3554}
3555
3556void addOperand(const SkPath& path) {
3557    fPath = &path;
3558    fXorMask = (path.getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
3559    preFetch();
3560}
3561
3562void finish() {
3563    walk();
3564    complete();
3565    if (fCurrentContour && !fCurrentContour->segments().count()) {
3566        fContours.pop_back();
3567    }
3568    // correct pointers in contours since fReducePts may have moved as it grew
3569    int cIndex = 0;
3570    int extraCount = fExtra.count();
3571    SkASSERT(extraCount == 0 || fExtra[0] == -1);
3572    int eIndex = 0;
3573    int rIndex = 0;
3574    while (++eIndex < extraCount) {
3575        int offset = fExtra[eIndex];
3576        if (offset < 0) {
3577            ++cIndex;
3578            continue;
3579        }
3580        fCurrentContour = &fContours[cIndex];
3581        rIndex += fCurrentContour->updateSegment(offset - 1,
3582                &fReducePts[rIndex]);
3583    }
3584    fExtra.reset(); // we're done with this
3585}
3586
3587ShapeOpMask xorMask() const {
3588    return fXorMask;
3589}
3590
3591protected:
3592
3593void complete() {
3594    if (fCurrentContour && fCurrentContour->segments().count()) {
3595        fCurrentContour->complete();
3596        fCurrentContour = NULL;
3597    }
3598}
3599
3600// FIXME:remove once we can access path pts directly
3601int preFetch() {
3602    SkPath::RawIter iter(*fPath); // FIXME: access path directly when allowed
3603    SkPoint pts[4];
3604    SkPath::Verb verb;
3605    do {
3606        verb = iter.next(pts);
3607        *fPathVerbs.append() = verb;
3608        if (verb == SkPath::kMove_Verb) {
3609            *fPathPts.append() = pts[0];
3610        } else if (verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
3611            fPathPts.append(verb, &pts[1]);
3612        }
3613    } while (verb != SkPath::kDone_Verb);
3614    return fPathVerbs.count();
3615}
3616
3617void walk() {
3618    SkPath::Verb reducedVerb;
3619    uint8_t* verbPtr = fPathVerbs.begin();
3620    uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
3621    const SkPoint* pointsPtr = fPathPts.begin();
3622    const SkPoint* finalCurveStart = NULL;
3623    const SkPoint* finalCurveEnd = NULL;
3624    SkPath::Verb verb;
3625    while ((verb = (SkPath::Verb) *verbPtr++) != SkPath::kDone_Verb) {
3626        switch (verb) {
3627            case SkPath::kMove_Verb:
3628                complete();
3629                if (!fCurrentContour) {
3630                    fCurrentContour = fContours.push_back_n(1);
3631                    fCurrentContour->setOperand(fOperand);
3632                    fCurrentContour->setXor(fXorMask == kEvenOdd_Mask);
3633                    *fExtra.append() = -1; // start new contour
3634                }
3635                finalCurveEnd = pointsPtr++;
3636                continue;
3637            case SkPath::kLine_Verb:
3638                // skip degenerate points
3639                if (pointsPtr[-1].fX != pointsPtr[0].fX
3640                        || pointsPtr[-1].fY != pointsPtr[0].fY) {
3641                    fCurrentContour->addLine(&pointsPtr[-1]);
3642                }
3643                break;
3644            case SkPath::kQuad_Verb:
3645
3646                reducedVerb = QuadReduceOrder(&pointsPtr[-1], fReducePts);
3647                if (reducedVerb == 0) {
3648                    break; // skip degenerate points
3649                }
3650                if (reducedVerb == 1) {
3651                    *fExtra.append() =
3652                            fCurrentContour->addLine(fReducePts.end() - 2);
3653                    break;
3654                }
3655                fCurrentContour->addQuad(&pointsPtr[-1]);
3656                break;
3657            case SkPath::kCubic_Verb:
3658                reducedVerb = CubicReduceOrder(&pointsPtr[-1], fReducePts);
3659                if (reducedVerb == 0) {
3660                    break; // skip degenerate points
3661                }
3662                if (reducedVerb == 1) {
3663                    *fExtra.append() =
3664                            fCurrentContour->addLine(fReducePts.end() - 2);
3665                    break;
3666                }
3667                if (reducedVerb == 2) {
3668                    *fExtra.append() =
3669                            fCurrentContour->addQuad(fReducePts.end() - 3);
3670                    break;
3671                }
3672                fCurrentContour->addCubic(&pointsPtr[-1]);
3673                break;
3674            case SkPath::kClose_Verb:
3675                SkASSERT(fCurrentContour);
3676                if (finalCurveStart && finalCurveEnd
3677                        && *finalCurveStart != *finalCurveEnd) {
3678                    *fReducePts.append() = *finalCurveStart;
3679                    *fReducePts.append() = *finalCurveEnd;
3680                    *fExtra.append() =
3681                            fCurrentContour->addLine(fReducePts.end() - 2);
3682                }
3683                complete();
3684                continue;
3685            default:
3686                SkDEBUGFAIL("bad verb");
3687                return;
3688        }
3689        finalCurveStart = &pointsPtr[verb - 1];
3690        pointsPtr += verb;
3691        SkASSERT(fCurrentContour);
3692        if (verbPtr == endOfFirstHalf) {
3693            fOperand = true;
3694        }
3695    }
3696}
3697
3698private:
3699    const SkPath* fPath;
3700    SkTDArray<SkPoint> fPathPts; // FIXME: point directly to path pts instead
3701    SkTDArray<uint8_t> fPathVerbs; // FIXME: remove
3702    Contour* fCurrentContour;
3703    SkTArray<Contour>& fContours;
3704    SkTDArray<SkPoint> fReducePts; // segments created on the fly
3705    SkTDArray<int> fExtra; // -1 marks new contour, > 0 offsets into contour
3706    ShapeOpMask fXorMask;
3707    int fSecondHalf;
3708    bool fOperand;
3709};
3710
3711class Work {
3712public:
3713    enum SegmentType {
3714        kHorizontalLine_Segment = -1,
3715        kVerticalLine_Segment = 0,
3716        kLine_Segment = SkPath::kLine_Verb,
3717        kQuad_Segment = SkPath::kQuad_Verb,
3718        kCubic_Segment = SkPath::kCubic_Verb,
3719    };
3720
3721    void addCoincident(Work& other, const Intersections& ts, bool swap) {
3722        fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
3723    }
3724
3725    // FIXME: does it make sense to write otherIndex now if we're going to
3726    // fix it up later?
3727    void addOtherT(int index, double otherT, int otherIndex) {
3728        fContour->addOtherT(fIndex, index, otherT, otherIndex);
3729    }
3730
3731    // Avoid collapsing t values that are close to the same since
3732    // we walk ts to describe consecutive intersections. Since a pair of ts can
3733    // be nearly equal, any problems caused by this should be taken care
3734    // of later.
3735    // On the edge or out of range values are negative; add 2 to get end
3736    int addT(double newT, const Work& other) {
3737        return fContour->addT(fIndex, newT, other.fContour, other.fIndex);
3738    }
3739
3740    bool advance() {
3741        return ++fIndex < fLast;
3742    }
3743
3744    SkScalar bottom() const {
3745        return bounds().fBottom;
3746    }
3747
3748    const Bounds& bounds() const {
3749        return fContour->segments()[fIndex].bounds();
3750    }
3751
3752    const SkPoint* cubic() const {
3753        return fCubic;
3754    }
3755
3756    void init(Contour* contour) {
3757        fContour = contour;
3758        fIndex = 0;
3759        fLast = contour->segments().count();
3760    }
3761
3762    bool isAdjacent(const Work& next) {
3763        return fContour == next.fContour && fIndex + 1 == next.fIndex;
3764    }
3765
3766    bool isFirstLast(const Work& next) {
3767        return fContour == next.fContour && fIndex == 0
3768                && next.fIndex == fLast - 1;
3769    }
3770
3771    SkScalar left() const {
3772        return bounds().fLeft;
3773    }
3774
3775    void promoteToCubic() {
3776        fCubic[0] = pts()[0];
3777        fCubic[2] = pts()[1];
3778        fCubic[3] = pts()[2];
3779        fCubic[1].fX = (fCubic[0].fX + fCubic[2].fX * 2) / 3;
3780        fCubic[1].fY = (fCubic[0].fY + fCubic[2].fY * 2) / 3;
3781        fCubic[2].fX = (fCubic[3].fX + fCubic[2].fX * 2) / 3;
3782        fCubic[2].fY = (fCubic[3].fY + fCubic[2].fY * 2) / 3;
3783    }
3784
3785    const SkPoint* pts() const {
3786        return fContour->segments()[fIndex].pts();
3787    }
3788
3789    SkScalar right() const {
3790        return bounds().fRight;
3791    }
3792
3793    ptrdiff_t segmentIndex() const {
3794        return fIndex;
3795    }
3796
3797    SegmentType segmentType() const {
3798        const Segment& segment = fContour->segments()[fIndex];
3799        SegmentType type = (SegmentType) segment.verb();
3800        if (type != kLine_Segment) {
3801            return type;
3802        }
3803        if (segment.isHorizontal()) {
3804            return kHorizontalLine_Segment;
3805        }
3806        if (segment.isVertical()) {
3807            return kVerticalLine_Segment;
3808        }
3809        return kLine_Segment;
3810    }
3811
3812    bool startAfter(const Work& after) {
3813        fIndex = after.fIndex;
3814        return advance();
3815    }
3816
3817    SkScalar top() const {
3818        return bounds().fTop;
3819    }
3820
3821    SkPath::Verb verb() const {
3822        return fContour->segments()[fIndex].verb();
3823    }
3824
3825    SkScalar x() const {
3826        return bounds().fLeft;
3827    }
3828
3829    bool xFlipped() const {
3830        return x() != pts()[0].fX;
3831    }
3832
3833    SkScalar y() const {
3834        return bounds().fTop;
3835    }
3836
3837    bool yFlipped() const {
3838        return y() != pts()[0].fY;
3839    }
3840
3841protected:
3842    Contour* fContour;
3843    SkPoint fCubic[4];
3844    int fIndex;
3845    int fLast;
3846};
3847
3848#if DEBUG_ADD_INTERSECTING_TS
3849static void debugShowLineIntersection(int pts, const Work& wt,
3850        const Work& wn, const double wtTs[2], const double wnTs[2]) {
3851    return;
3852    if (!pts) {
3853        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g %1.9g,%1.9g)\n",
3854                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
3855                wt.pts()[1].fX, wt.pts()[1].fY, wn.pts()[0].fX, wn.pts()[0].fY,
3856                wn.pts()[1].fX, wn.pts()[1].fY);
3857        return;
3858    }
3859    SkPoint wtOutPt, wnOutPt;
3860    LineXYAtT(wt.pts(), wtTs[0], &wtOutPt);
3861    LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
3862    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3863            __FUNCTION__,
3864            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
3865            wt.pts()[1].fX, wt.pts()[1].fY, wtOutPt.fX, wtOutPt.fY);
3866    if (pts == 2) {
3867        SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
3868    }
3869    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3870            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
3871            wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
3872    if (pts == 2) {
3873        SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
3874    }
3875    SkDebugf("\n");
3876}
3877
3878static void debugShowQuadLineIntersection(int pts, const Work& wt,
3879        const Work& wn, const double wtTs[2], const double wnTs[2]) {
3880    if (!pts) {
3881        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
3882                " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n",
3883                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
3884                wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
3885                wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY,
3886                wt.pts()[2].fX, wt.pts()[2].fY );
3887        return;
3888    }
3889    SkPoint wtOutPt, wnOutPt;
3890    QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
3891    LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
3892    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3893            __FUNCTION__,
3894            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
3895            wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
3896            wtOutPt.fX, wtOutPt.fY);
3897    if (pts == 2) {
3898        SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
3899    }
3900    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3901            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
3902            wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
3903    if (pts == 2) {
3904        SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
3905    }
3906    SkDebugf("\n");
3907}
3908
3909static void debugShowQuadIntersection(int pts, const Work& wt,
3910        const Work& wn, const double wtTs[2], const double wnTs[2]) {
3911    if (!pts) {
3912        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
3913                " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n",
3914                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
3915                wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
3916                wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY,
3917                wt.pts()[2].fX, wt.pts()[2].fY );
3918        return;
3919    }
3920    SkPoint wtOutPt, wnOutPt;
3921    QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
3922    QuadXYAtT(wn.pts(), wnTs[0], &wnOutPt);
3923    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3924            __FUNCTION__,
3925            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
3926            wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
3927            wtOutPt.fX, wtOutPt.fY);
3928    if (pts == 2) {
3929        SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
3930    }
3931    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
3932            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
3933            wn.pts()[1].fX, wn.pts()[1].fY, wn.pts()[2].fX, wn.pts()[2].fY,
3934            wnOutPt.fX, wnOutPt.fY);
3935    if (pts == 2) {
3936        SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
3937    }
3938    SkDebugf("\n");
3939}
3940#else
3941static void debugShowLineIntersection(int , const Work& ,
3942        const Work& , const double [2], const double [2]) {
3943}
3944
3945static void debugShowQuadLineIntersection(int , const Work& ,
3946        const Work& , const double [2], const double [2]) {
3947}
3948
3949static void debugShowQuadIntersection(int , const Work& ,
3950        const Work& , const double [2], const double [2]) {
3951}
3952#endif
3953
3954static bool addIntersectTs(Contour* test, Contour* next) {
3955
3956    if (test != next) {
3957        if (test->bounds().fBottom < next->bounds().fTop) {
3958            return false;
3959        }
3960        if (!Bounds::Intersects(test->bounds(), next->bounds())) {
3961            return true;
3962        }
3963    }
3964    Work wt;
3965    wt.init(test);
3966    bool foundCommonContour = test == next;
3967    do {
3968        Work wn;
3969        wn.init(next);
3970        if (test == next && !wn.startAfter(wt)) {
3971            continue;
3972        }
3973        do {
3974            if (!Bounds::Intersects(wt.bounds(), wn.bounds())) {
3975                continue;
3976            }
3977            int pts;
3978            Intersections ts;
3979            bool swap = false;
3980            switch (wt.segmentType()) {
3981                case Work::kHorizontalLine_Segment:
3982                    swap = true;
3983                    switch (wn.segmentType()) {
3984                        case Work::kHorizontalLine_Segment:
3985                        case Work::kVerticalLine_Segment:
3986                        case Work::kLine_Segment: {
3987                            pts = HLineIntersect(wn.pts(), wt.left(),
3988                                    wt.right(), wt.y(), wt.xFlipped(), ts);
3989                            debugShowLineIntersection(pts, wt, wn,
3990                                    ts.fT[1], ts.fT[0]);
3991                            break;
3992                        }
3993                        case Work::kQuad_Segment: {
3994                            pts = HQuadIntersect(wn.pts(), wt.left(),
3995                                    wt.right(), wt.y(), wt.xFlipped(), ts);
3996                            break;
3997                        }
3998                        case Work::kCubic_Segment: {
3999                            pts = HCubicIntersect(wn.pts(), wt.left(),
4000                                    wt.right(), wt.y(), wt.xFlipped(), ts);
4001                            break;
4002                        }
4003                        default:
4004                            SkASSERT(0);
4005                    }
4006                    break;
4007                case Work::kVerticalLine_Segment:
4008                    swap = true;
4009                    switch (wn.segmentType()) {
4010                        case Work::kHorizontalLine_Segment:
4011                        case Work::kVerticalLine_Segment:
4012                        case Work::kLine_Segment: {
4013                            pts = VLineIntersect(wn.pts(), wt.top(),
4014                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
4015                            debugShowLineIntersection(pts, wt, wn,
4016                                    ts.fT[1], ts.fT[0]);
4017                            break;
4018                        }
4019                        case Work::kQuad_Segment: {
4020                            pts = VQuadIntersect(wn.pts(), wt.top(),
4021                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
4022                            break;
4023                        }
4024                        case Work::kCubic_Segment: {
4025                            pts = VCubicIntersect(wn.pts(), wt.top(),
4026                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
4027                            break;
4028                        }
4029                        default:
4030                            SkASSERT(0);
4031                    }
4032                    break;
4033                case Work::kLine_Segment:
4034                    switch (wn.segmentType()) {
4035                        case Work::kHorizontalLine_Segment:
4036                            pts = HLineIntersect(wt.pts(), wn.left(),
4037                                    wn.right(), wn.y(), wn.xFlipped(), ts);
4038                            debugShowLineIntersection(pts, wt, wn,
4039                                    ts.fT[1], ts.fT[0]);
4040                            break;
4041                        case Work::kVerticalLine_Segment:
4042                            pts = VLineIntersect(wt.pts(), wn.top(),
4043                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
4044                            debugShowLineIntersection(pts, wt, wn,
4045                                    ts.fT[1], ts.fT[0]);
4046                            break;
4047                        case Work::kLine_Segment: {
4048                            pts = LineIntersect(wt.pts(), wn.pts(), ts);
4049                            debugShowLineIntersection(pts, wt, wn,
4050                                    ts.fT[1], ts.fT[0]);
4051                            break;
4052                        }
4053                        case Work::kQuad_Segment: {
4054                            swap = true;
4055                            pts = QuadLineIntersect(wn.pts(), wt.pts(), ts);
4056                            debugShowQuadLineIntersection(pts, wt, wn,
4057                                    ts.fT[1], ts.fT[0]);
4058                            break;
4059                        }
4060                        case Work::kCubic_Segment: {
4061                            swap = true;
4062                            pts = CubicLineIntersect(wn.pts(), wt.pts(), ts);
4063                            break;
4064                        }
4065                        default:
4066                            SkASSERT(0);
4067                    }
4068                    break;
4069                case Work::kQuad_Segment:
4070                    switch (wn.segmentType()) {
4071                        case Work::kHorizontalLine_Segment:
4072                            pts = HQuadIntersect(wt.pts(), wn.left(),
4073                                    wn.right(), wn.y(), wn.xFlipped(), ts);
4074                            break;
4075                        case Work::kVerticalLine_Segment:
4076                            pts = VQuadIntersect(wt.pts(), wn.top(),
4077                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
4078                            break;
4079                        case Work::kLine_Segment: {
4080                            pts = QuadLineIntersect(wt.pts(), wn.pts(), ts);
4081                            debugShowQuadLineIntersection(pts, wt, wn,
4082                                    ts.fT[1], ts.fT[0]);
4083                            break;
4084                        }
4085                        case Work::kQuad_Segment: {
4086                            pts = QuadIntersect(wt.pts(), wn.pts(), ts);
4087                            debugShowQuadIntersection(pts, wt, wn,
4088                                    ts.fT[1], ts.fT[0]);
4089                            break;
4090                        }
4091                        case Work::kCubic_Segment: {
4092                            wt.promoteToCubic();
4093                            pts = CubicIntersect(wt.cubic(), wn.pts(), ts);
4094                            break;
4095                        }
4096                        default:
4097                            SkASSERT(0);
4098                    }
4099                    break;
4100                case Work::kCubic_Segment:
4101                    switch (wn.segmentType()) {
4102                        case Work::kHorizontalLine_Segment:
4103                            pts = HCubicIntersect(wt.pts(), wn.left(),
4104                                    wn.right(), wn.y(), wn.xFlipped(), ts);
4105                            break;
4106                        case Work::kVerticalLine_Segment:
4107                            pts = VCubicIntersect(wt.pts(), wn.top(),
4108                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
4109                            break;
4110                        case Work::kLine_Segment: {
4111                            pts = CubicLineIntersect(wt.pts(), wn.pts(), ts);
4112                            break;
4113                        }
4114                        case Work::kQuad_Segment: {
4115                            wn.promoteToCubic();
4116                            pts = CubicIntersect(wt.pts(), wn.cubic(), ts);
4117                            break;
4118                        }
4119                        case Work::kCubic_Segment: {
4120                            pts = CubicIntersect(wt.pts(), wn.pts(), ts);
4121                            break;
4122                        }
4123                        default:
4124                            SkASSERT(0);
4125                    }
4126                    break;
4127                default:
4128                    SkASSERT(0);
4129            }
4130            if (!foundCommonContour && pts > 0) {
4131                test->addCross(next);
4132                next->addCross(test);
4133                foundCommonContour = true;
4134            }
4135            // in addition to recording T values, record matching segment
4136            if (pts == 2) {
4137                if (wn.segmentType() <= Work::kLine_Segment
4138                        && wt.segmentType() <= Work::kLine_Segment) {
4139                    wt.addCoincident(wn, ts, swap);
4140                    continue;
4141                }
4142                if (wn.segmentType() == Work::kQuad_Segment
4143                        && wt.segmentType() == Work::kQuad_Segment
4144                        && ts.coincidentUsed() == 2) {
4145                    wt.addCoincident(wn, ts, swap);
4146                    continue;
4147                }
4148
4149            }
4150            for (int pt = 0; pt < pts; ++pt) {
4151                SkASSERT(ts.fT[0][pt] >= 0 && ts.fT[0][pt] <= 1);
4152                SkASSERT(ts.fT[1][pt] >= 0 && ts.fT[1][pt] <= 1);
4153                int testTAt = wt.addT(ts.fT[swap][pt], wn);
4154                int nextTAt = wn.addT(ts.fT[!swap][pt], wt);
4155                wt.addOtherT(testTAt, ts.fT[!swap][pt ^ ts.fFlip], nextTAt);
4156                wn.addOtherT(nextTAt, ts.fT[swap][pt ^ ts.fFlip], testTAt);
4157            }
4158        } while (wn.advance());
4159    } while (wt.advance());
4160    return true;
4161}
4162
4163// resolve any coincident pairs found while intersecting, and
4164// see if coincidence is formed by clipping non-concident segments
4165static void coincidenceCheck(SkTDArray<Contour*>& contourList) {
4166    int contourCount = contourList.count();
4167    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
4168        Contour* contour = contourList[cIndex];
4169        contour->resolveCoincidence();
4170    }
4171    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
4172        Contour* contour = contourList[cIndex];
4173        contour->findTooCloseToCall();
4174    }
4175#if 0
4176    // OPTIMIZATION: this check could be folded in with findTooClose -- maybe
4177    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
4178        Contour* contour = contourList[cIndex];
4179        contour->collapseTriangles();
4180    }
4181#endif
4182}
4183
4184// project a ray from the top of the contour up and see if it hits anything
4185// note: when we compute line intersections, we keep track of whether
4186// two contours touch, so we need only look at contours not touching this one.
4187// OPTIMIZATION: sort contourList vertically to avoid linear walk
4188static int innerContourCheck(SkTDArray<Contour*>& contourList,
4189        const Segment* current, int index, int endIndex) {
4190    const SkPoint& basePt = current->xyAtT(endIndex);
4191    int contourCount = contourList.count();
4192    SkScalar bestY = SK_ScalarMin;
4193    const Segment* test = NULL;
4194    int tIndex;
4195    double tHit;
4196 //   bool checkCrosses = true;
4197    for (int cTest = 0; cTest < contourCount; ++cTest) {
4198        Contour* contour = contourList[cTest];
4199        if (basePt.fY < contour->bounds().fTop) {
4200            continue;
4201        }
4202        if (bestY > contour->bounds().fBottom) {
4203            continue;
4204        }
4205#if 0
4206        // even though the contours crossed, if spans cancel through concidence,
4207        // the contours may be not have any span links to chase, and the current
4208        // segment may be isolated. Detect this by seeing if current has
4209        // uninitialized wind sums. If so, project a ray instead of relying on
4210        // previously found intersections.
4211        if (baseContour == contour) {
4212            continue;
4213        }
4214        if (checkCrosses && baseContour->crosses(contour)) {
4215            if (current->isConnected(index, endIndex)) {
4216                continue;
4217            }
4218            checkCrosses = false;
4219        }
4220#endif
4221        const Segment* next = contour->crossedSegment(basePt, bestY, tIndex, tHit);
4222        if (next) {
4223            test = next;
4224        }
4225    }
4226    if (!test) {
4227        return 0;
4228    }
4229    int winding, windValue;
4230    // If the ray hit the end of a span, we need to construct the wheel of
4231    // angles to find the span closest to the ray -- even if there are just
4232    // two spokes on the wheel.
4233    const Angle* angle = NULL;
4234    if (approximately_zero(tHit - test->t(tIndex))) {
4235        SkTDArray<Angle> angles;
4236        int end = test->nextSpan(tIndex, 1);
4237        if (end < 0) {
4238            end = test->nextSpan(tIndex, -1);
4239        }
4240        test->addTwoAngles(end, tIndex, angles);
4241        SkASSERT(angles.count() > 0);
4242        if (angles[0].segment()->yAtT(angles[0].start()) >= basePt.fY) {
4243#if DEBUG_SORT
4244            SkDebugf("%s early return\n", __FUNCTION__);
4245#endif
4246            return 0;
4247        }
4248        test->buildAngles(tIndex, angles);
4249        SkTDArray<Angle*> sorted;
4250        // OPTIMIZATION: call a sort that, if base point is the leftmost,
4251        // returns the first counterclockwise hour before 6 o'clock,
4252        // or if the base point is rightmost, returns the first clockwise
4253        // hour after 6 o'clock
4254        (void) Segment::SortAngles(angles, sorted);
4255#if DEBUG_SORT
4256        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0);
4257#endif
4258        // walk the sorted angle fan to find the lowest angle
4259        // above the base point. Currently, the first angle in the sorted array
4260        // is 12 noon or an earlier hour (the next counterclockwise)
4261        int count = sorted.count();
4262        int left = -1;
4263        int mid = -1;
4264        int right = -1;
4265        bool baseMatches = test->yAtT(tIndex) == basePt.fY;
4266        for (int index = 0; index < count; ++index) {
4267            angle = sorted[index];
4268            if (angle->unsortable()) {
4269                continue;
4270            }
4271            if (baseMatches && angle->isHorizontal()) {
4272                continue;
4273            }
4274            double indexDx = angle->dx();
4275            test = angle->segment();
4276            if (test->verb() > SkPath::kLine_Verb && approximately_zero(indexDx)) {
4277                const SkPoint* pts = test->pts();
4278                indexDx = pts[2].fX - pts[1].fX - indexDx;
4279            }
4280            if (indexDx < 0) {
4281                left = index;
4282            } else if (indexDx > 0) {
4283                right = index;
4284                int previous = index - 1;
4285                if (previous < 0) {
4286                    previous = count - 1;
4287                }
4288                const Angle* prev = sorted[previous];
4289                if (prev->dy() >= 0 && prev->dx() > 0 && angle->dy() < 0) {
4290#if DEBUG_SORT
4291                    SkDebugf("%s use prev\n", __FUNCTION__);
4292#endif
4293                    right = previous;
4294                }
4295                break;
4296            } else {
4297                mid = index;
4298            }
4299        }
4300        if (left < 0 && right < 0) {
4301            left = mid;
4302        }
4303        SkASSERT(left >= 0 || right >= 0);
4304        if (left < 0) {
4305            left = right;
4306        } else if (left >= 0 && mid >= 0 && right >= 0
4307                && sorted[mid]->sign() == sorted[right]->sign()) {
4308            left = right;
4309        }
4310        angle = sorted[left];
4311        test = angle->segment();
4312        winding = test->windSum(angle);
4313        SkASSERT(winding != SK_MinS32);
4314        windValue = test->windValue(angle);
4315#if DEBUG_WINDING
4316        SkDebugf("%s angle winding=%d windValue=%d sign=%d\n", __FUNCTION__, winding,
4317                windValue, angle->sign());
4318#endif
4319    } else {
4320        winding = test->windSum(tIndex);
4321        SkASSERT(winding != SK_MinS32);
4322        windValue = test->windValue(tIndex);
4323#if DEBUG_WINDING
4324        SkDebugf("%s single winding=%d windValue=%d\n", __FUNCTION__, winding,
4325                windValue);
4326#endif
4327    }
4328    // see if a + change in T results in a +/- change in X (compute x'(T))
4329    SkScalar dx = (*SegmentDXAtT[test->verb()])(test->pts(), tHit);
4330    if (test->verb() > SkPath::kLine_Verb && approximately_zero(dx)) {
4331        const SkPoint* pts = test->pts();
4332        dx = pts[2].fX - pts[1].fX - dx;
4333    }
4334#if DEBUG_WINDING
4335    SkDebugf("%s dx=%1.9g\n", __FUNCTION__, dx);
4336#endif
4337    SkASSERT(dx != 0);
4338    if (winding * dx > 0) { // if same signs, result is negative
4339        winding += dx > 0 ? -windValue : windValue;
4340#if DEBUG_WINDING
4341        SkDebugf("%s final winding=%d\n", __FUNCTION__, winding);
4342#endif
4343    }
4344    return winding;
4345}
4346
4347#if SORTABLE_CONTOURS
4348// OPTIMIZATION: not crazy about linear search here to find top active y.
4349// seems like we should break down and do the sort, or maybe sort each
4350// contours' segments?
4351// Once the segment array is built, there's no reason I can think of not to
4352// sort it in Y. hmmm
4353// FIXME: return the contour found to pass to inner contour check
4354static Segment* findTopContour(SkTDArray<Contour*>& contourList) {
4355    int contourCount = contourList.count();
4356    int cIndex = 0;
4357    Segment* topStart;
4358    SkScalar bestY = SK_ScalarMax;
4359    Contour* contour;
4360    do {
4361        contour = contourList[cIndex];
4362        topStart = contour->topSegment(bestY);
4363    } while (!topStart && ++cIndex < contourCount);
4364    if (!topStart) {
4365        return NULL;
4366    }
4367    while (++cIndex < contourCount) {
4368        contour = contourList[cIndex];
4369        if (bestY < contour->bounds().fTop) {
4370            continue;
4371        }
4372        SkScalar testY = SK_ScalarMax;
4373        Segment* test = contour->topSegment(testY);
4374        if (!test || bestY <= testY) {
4375            continue;
4376        }
4377        topStart = test;
4378        bestY = testY;
4379    }
4380    return topStart;
4381}
4382#endif
4383
4384static Segment* findUndone(SkTDArray<Contour*>& contourList, int& start, int& end) {
4385    int contourCount = contourList.count();
4386    Segment* result;
4387    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
4388        Contour* contour = contourList[cIndex];
4389        result = contour->undoneSegment(start, end);
4390        if (result) {
4391            return result;
4392        }
4393    }
4394    return NULL;
4395}
4396
4397
4398
4399static Segment* findChase(SkTDArray<Span*>& chase, int& tIndex, int& endIndex,
4400        int contourWinding) {
4401    while (chase.count()) {
4402        Span* span = chase[chase.count() - 1];
4403        const Span& backPtr = span->fOther->span(span->fOtherIndex);
4404        Segment* segment = backPtr.fOther;
4405        tIndex = backPtr.fOtherIndex;
4406        SkTDArray<Angle> angles;
4407        int done = 0;
4408        if (segment->activeAngle(tIndex, done, angles)) {
4409            Angle* last = angles.end() - 1;
4410            tIndex = last->start();
4411            endIndex = last->end();
4412            return last->segment();
4413        }
4414        if (done == angles.count()) {
4415            chase.pop(&span);
4416            continue;
4417        }
4418        SkTDArray<Angle*> sorted;
4419        bool sortable = Segment::SortAngles(angles, sorted);
4420#if DEBUG_SORT
4421        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0);
4422#endif
4423        if (!sortable) {
4424            chase.pop(&span);
4425            continue;
4426        }
4427        // find first angle, initialize winding to computed fWindSum
4428        int firstIndex = -1;
4429        const Angle* angle;
4430        int winding;
4431        do {
4432            angle = sorted[++firstIndex];
4433            segment = angle->segment();
4434            winding = segment->windSum(angle);
4435        } while (winding == SK_MinS32);
4436        int spanWinding = segment->spanSign(angle->start(), angle->end());
4437    #if DEBUG_WINDING
4438        SkDebugf("%s winding=%d spanWinding=%d contourWinding=%d\n",
4439                __FUNCTION__, winding, spanWinding, contourWinding);
4440    #endif
4441        // turn swinding into contourWinding
4442        if (spanWinding * winding < 0) {
4443            winding += spanWinding;
4444        }
4445    #if DEBUG_SORT
4446        segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding);
4447    #endif
4448        // we care about first sign and whether wind sum indicates this
4449        // edge is inside or outside. Maybe need to pass span winding
4450        // or first winding or something into this function?
4451        // advance to first undone angle, then return it and winding
4452        // (to set whether edges are active or not)
4453        int nextIndex = firstIndex + 1;
4454        int angleCount = sorted.count();
4455        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
4456        angle = sorted[firstIndex];
4457        winding -= angle->segment()->spanSign(angle);
4458        do {
4459            SkASSERT(nextIndex != firstIndex);
4460            if (nextIndex == angleCount) {
4461                nextIndex = 0;
4462            }
4463            angle = sorted[nextIndex];
4464            segment = angle->segment();
4465            int maxWinding = winding;
4466            winding -= segment->spanSign(angle);
4467    #if DEBUG_SORT
4468            SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
4469                    segment->debugID(), maxWinding, winding, angle->sign());
4470    #endif
4471            tIndex = angle->start();
4472            endIndex = angle->end();
4473            int lesser = SkMin32(tIndex, endIndex);
4474            const Span& nextSpan = segment->span(lesser);
4475            if (!nextSpan.fDone) {
4476#if 1
4477            // FIXME: this be wrong. assign startWinding if edge is in
4478            // same direction. If the direction is opposite, winding to
4479            // assign is flipped sign or +/- 1?
4480                if (useInnerWinding(maxWinding, winding)) {
4481                    maxWinding = winding;
4482                }
4483                segment->markWinding(lesser, maxWinding);
4484#endif
4485                break;
4486            }
4487        } while (++nextIndex != lastIndex);
4488        return segment;
4489    }
4490    return NULL;
4491}
4492
4493#if DEBUG_ACTIVE_SPANS
4494static void debugShowActiveSpans(SkTDArray<Contour*>& contourList) {
4495    int index;
4496    for (index = 0; index < contourList.count(); ++ index) {
4497        contourList[index]->debugShowActiveSpans();
4498    }
4499    for (index = 0; index < contourList.count(); ++ index) {
4500        contourList[index]->validateActiveSpans();
4501    }
4502}
4503#endif
4504
4505static bool windingIsActive(int winding, int spanWinding) {
4506    return winding * spanWinding <= 0 && abs(winding) <= abs(spanWinding)
4507            && (!winding || !spanWinding || winding == -spanWinding);
4508}
4509
4510#if !SORTABLE_CONTOURS
4511static Segment* findSortableTop(SkTDArray<Contour*>& contourList, int& index,
4512        int& endIndex) {
4513    Segment* result;
4514    do {
4515        int contourCount = contourList.count();
4516        int cIndex = 0;
4517        Segment* topStart;
4518        SkScalar bestY = SK_ScalarMax;
4519        Contour* contour;
4520        do {
4521            contour = contourList[cIndex];
4522            topStart = contour->topSortableSegment(bestY);
4523        } while (!topStart && ++cIndex < contourCount);
4524        if (!topStart) {
4525            return NULL;
4526        }
4527        while (++cIndex < contourCount) {
4528            contour = contourList[cIndex];
4529            if (bestY < contour->bounds().fTop) {
4530                continue;
4531            }
4532            SkScalar testY = SK_ScalarMax;
4533            Segment* test = contour->topSortableSegment(testY);
4534            if (!test || bestY <= testY) {
4535                continue;
4536            }
4537            topStart = test;
4538            bestY = testY;
4539        }
4540        result = topStart->findTop(index, endIndex);
4541    } while (!result);
4542    return result;
4543}
4544#endif
4545
4546// Each segment may have an inside or an outside. Segments contained within
4547// winding may have insides on either side, and form a contour that should be
4548// ignored. Segments that are coincident with opposing direction segments may
4549// have outsides on either side, and should also disappear.
4550// 'Normal' segments will have one inside and one outside. Subsequent connections
4551// when winding should follow the intersection direction. If more than one edge
4552// is an option, choose first edge that continues the inside.
4553    // since we start with leftmost top edge, we'll traverse through a
4554    // smaller angle counterclockwise to get to the next edge.
4555// returns true if all edges were processed
4556static bool bridgeWinding(SkTDArray<Contour*>& contourList, SkPath& simple) {
4557    bool firstContour = true;
4558    bool unsortable = false;
4559    do {
4560#if SORTABLE_CONTOURS // old way
4561        Segment* topStart = findTopContour(contourList);
4562        if (!topStart) {
4563            break;
4564        }
4565        // Start at the top. Above the top is outside, below is inside.
4566        // follow edges to intersection by changing the index by direction.
4567        int index, endIndex;
4568        Segment* current = topStart->findTop(index, endIndex);
4569#else // new way: iterate while top is unsortable
4570        int index, endIndex;
4571        Segment* current = findSortableTop(contourList, index, endIndex);
4572        if (!current) {
4573            break;
4574        }
4575#endif
4576        int contourWinding;
4577        if (firstContour) {
4578            contourWinding = 0;
4579            firstContour = false;
4580        } else {
4581            int sumWinding = current->windSum(SkMin32(index, endIndex));
4582            // FIXME: don't I have to adjust windSum to get contourWinding?
4583            if (sumWinding == SK_MinS32) {
4584                sumWinding = current->computeSum(index, endIndex);
4585            }
4586            if (sumWinding == SK_MinS32) {
4587                contourWinding = innerContourCheck(contourList, current,
4588                        index, endIndex);
4589            } else {
4590                contourWinding = sumWinding;
4591                int spanWinding = current->spanSign(index, endIndex);
4592                bool inner = useInnerWinding(sumWinding - spanWinding, sumWinding);
4593                if (inner) {
4594                    contourWinding -= spanWinding;
4595                }
4596#if DEBUG_WINDING
4597                SkDebugf("%s sumWinding=%d spanWinding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
4598                        sumWinding, spanWinding, SkSign32(index - endIndex),
4599                        inner, contourWinding);
4600#endif
4601            }
4602#if DEBUG_WINDING
4603         //   SkASSERT(current->debugVerifyWinding(index, endIndex, contourWinding));
4604            SkDebugf("%s contourWinding=%d\n", __FUNCTION__, contourWinding);
4605#endif
4606        }
4607        SkPoint lastPt;
4608        int winding = contourWinding;
4609        int spanWinding = current->spanSign(index, endIndex);
4610        // FIXME: needs work. While it works in limited situations, it does
4611        // not always compute winding correctly. Active should be removed and instead
4612        // the initial winding should be correctly passed in so that if the
4613        // inner contour is wound the same way, it never finds an accumulated
4614        // winding of zero. Inside 'find next', we need to look for transitions
4615        // other than zero when resolving sorted angles.
4616        bool active = windingIsActive(winding, spanWinding);
4617        SkTDArray<Span*> chaseArray;
4618        do {
4619        #if DEBUG_WINDING
4620            SkDebugf("%s active=%s winding=%d spanWinding=%d\n",
4621                    __FUNCTION__, active ? "true" : "false",
4622                    winding, spanWinding);
4623        #endif
4624            const SkPoint* firstPt = NULL;
4625            do {
4626                SkASSERT(unsortable || !current->done());
4627                int nextStart = index;
4628                int nextEnd = endIndex;
4629                Segment* next = current->findNextWinding(chaseArray, active,
4630                        nextStart, nextEnd, winding, spanWinding, unsortable);
4631                if (!next) {
4632                    if (active && firstPt && current->verb() != SkPath::kLine_Verb && *firstPt != lastPt) {
4633                        lastPt = current->addCurveTo(index, endIndex, simple, true);
4634                        SkASSERT(*firstPt == lastPt);
4635                    }
4636                    break;
4637                }
4638                if (!firstPt) {
4639                    firstPt = &current->addMoveTo(index, simple, active);
4640                }
4641                lastPt = current->addCurveTo(index, endIndex, simple, active);
4642                current = next;
4643                index = nextStart;
4644                endIndex = nextEnd;
4645            } while (*firstPt != lastPt && (active || !current->done()));
4646            if (firstPt && active) {
4647        #if DEBUG_PATH_CONSTRUCTION
4648                SkDebugf("path.close();\n");
4649        #endif
4650                simple.close();
4651            }
4652            current = findChase(chaseArray, index, endIndex, contourWinding);
4653        #if DEBUG_ACTIVE_SPANS
4654            debugShowActiveSpans(contourList);
4655        #endif
4656            if (!current) {
4657                break;
4658            }
4659            int lesser = SkMin32(index, endIndex);
4660            spanWinding = current->spanSign(index, endIndex);
4661            winding = current->windSum(lesser);
4662            bool inner = useInnerWinding(winding - spanWinding, winding);
4663        #if DEBUG_WINDING
4664            SkDebugf("%s id=%d t=%1.9g spanWinding=%d winding=%d sign=%d"
4665                    " inner=%d result=%d\n",
4666                    __FUNCTION__, current->debugID(), current->t(lesser),
4667                    spanWinding, winding, SkSign32(index - endIndex),
4668                    useInnerWinding(winding - spanWinding, winding),
4669                    inner ? winding - spanWinding : winding);
4670        #endif
4671            if (inner) {
4672                winding -= spanWinding;
4673            }
4674            active = windingIsActive(winding, spanWinding);
4675        } while (true);
4676    } while (true);
4677    return !unsortable;
4678}
4679
4680// returns true if all edges were processed
4681static bool bridgeXor(SkTDArray<Contour*>& contourList, SkPath& simple) {
4682    Segment* current;
4683    int start, end;
4684    bool unsortable = false;
4685    while ((current = findUndone(contourList, start, end))) {
4686        const SkPoint* firstPt = NULL;
4687        SkPoint lastPt;
4688        do {
4689            SkASSERT(unsortable || !current->done());
4690            int nextStart = start;
4691            int nextEnd = end;
4692            Segment* next = current->findNextXor(nextStart, nextEnd, unsortable);
4693            if (!next) {
4694                if (firstPt && current->verb() != SkPath::kLine_Verb && *firstPt != lastPt) {
4695                    lastPt = current->addCurveTo(start, end, simple, true);
4696                    SkASSERT(*firstPt == lastPt);
4697                }
4698                break;
4699            }
4700            if (!firstPt) {
4701                firstPt = &current->addMoveTo(start, simple, true);
4702            }
4703            lastPt = current->addCurveTo(start, end, simple, true);
4704            current = next;
4705            start = nextStart;
4706            end = nextEnd;
4707        } while (*firstPt != lastPt);
4708        if (firstPt) {
4709    #if DEBUG_PATH_CONSTRUCTION
4710            SkDebugf("%s close\n", __FUNCTION__);
4711    #endif
4712            simple.close();
4713        }
4714    #if DEBUG_ACTIVE_SPANS
4715        debugShowActiveSpans(contourList);
4716    #endif
4717    }
4718    return !unsortable;
4719}
4720
4721static void fixOtherTIndex(SkTDArray<Contour*>& contourList) {
4722    int contourCount = contourList.count();
4723    for (int cTest = 0; cTest < contourCount; ++cTest) {
4724        Contour* contour = contourList[cTest];
4725        contour->fixOtherTIndex();
4726    }
4727}
4728
4729#if !SORTABLE_CONTOURS
4730static void sortSegments(SkTDArray<Contour*>& contourList) {
4731    int contourCount = contourList.count();
4732    for (int cTest = 0; cTest < contourCount; ++cTest) {
4733        Contour* contour = contourList[cTest];
4734        contour->sortSegments();
4735    }
4736}
4737#endif
4738
4739static void makeContourList(SkTArray<Contour>& contours,
4740        SkTDArray<Contour*>& list) {
4741    int count = contours.count();
4742    if (count == 0) {
4743        return;
4744    }
4745    for (int index = 0; index < count; ++index) {
4746        *list.append() = &contours[index];
4747    }
4748    QSort<Contour>(list.begin(), list.end() - 1);
4749}
4750
4751static void assemble(SkPath& simple) {
4752    // TODO: find the non-closed paths and connect them together
4753    SkASSERT(0);
4754}
4755
4756void simplifyx(const SkPath& path, SkPath& simple) {
4757    // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
4758    simple.reset();
4759    simple.setFillType(SkPath::kEvenOdd_FillType);
4760
4761    // turn path into list of segments
4762    SkTArray<Contour> contours;
4763    // FIXME: add self-intersecting cubics' T values to segment
4764    EdgeBuilder builder(path, contours);
4765    builder.finish();
4766    SkTDArray<Contour*> contourList;
4767    makeContourList(contours, contourList);
4768    Contour** currentPtr = contourList.begin();
4769    if (!currentPtr) {
4770        return;
4771    }
4772    Contour** listEnd = contourList.end();
4773    // find all intersections between segments
4774    do {
4775        Contour** nextPtr = currentPtr;
4776        Contour* current = *currentPtr++;
4777        Contour* next;
4778        do {
4779            next = *nextPtr++;
4780        } while (addIntersectTs(current, next) && nextPtr != listEnd);
4781    } while (currentPtr != listEnd);
4782    // eat through coincident edges
4783    coincidenceCheck(contourList);
4784    fixOtherTIndex(contourList);
4785#if !SORTABLE_CONTOURS
4786    sortSegments(contourList);
4787#endif
4788    // construct closed contours
4789    if (builder.xorMask() == kWinding_Mask
4790                ? !bridgeWinding(contourList, simple)
4791                : !bridgeXor(contourList, simple))
4792    { // if some edges could not be resolved, assemble remaining fragments
4793        assemble(simple);
4794    }
4795}
4796
4797