Simplify.cpp revision 7a03d86a3d9adcb13432fbd82039725149487c97
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
27bool gUseOldBridgeWinding = false;
28
29#define PIN_ADD_T 0
30#define TRY_ROTATE 1
31
32#define DEBUG_UNUSED 0 // set to expose unused functions
33#define FORCE_RELEASE 0  // set force release to 1 for multiple thread -- no debugging
34
35#if FORCE_RELEASE || defined SK_RELEASE
36
37const bool gRunTestsInOneThread = false;
38
39#define DEBUG_ACTIVE_SPANS 0
40#define DEBUG_ACTIVE_SPANS_SHORT_FORM 0
41#define DEBUG_ADD_INTERSECTING_TS 0
42#define DEBUG_ADD_T_PAIR 0
43#define DEBUG_ANGLE 0
44#define DEBUG_ASSEMBLE 0
45#define DEBUG_CONCIDENT 0
46#define DEBUG_CROSS 0
47#define DEBUG_FLOW 0
48#define DEBUG_MARK_DONE 0
49#define DEBUG_PATH_CONSTRUCTION 0
50#define DEBUG_SHOW_WINDING 0
51#define DEBUG_SORT 0
52#define DEBUG_WIND_BUMP 0
53#define DEBUG_WINDING 0
54
55#else
56
57const bool gRunTestsInOneThread = true;
58
59#define DEBUG_ACTIVE_SPANS 1
60#define DEBUG_ACTIVE_SPANS_SHORT_FORM 1
61#define DEBUG_ADD_INTERSECTING_TS 1
62#define DEBUG_ADD_T_PAIR 1
63#define DEBUG_ANGLE 1
64#define DEBUG_ASSEMBLE 1
65#define DEBUG_CONCIDENT 1
66#define DEBUG_CROSS 0
67#define DEBUG_FLOW 1
68#define DEBUG_MARK_DONE 1
69#define DEBUG_PATH_CONSTRUCTION 1
70#define DEBUG_SHOW_WINDING 0
71#define DEBUG_SORT 1
72#define DEBUG_WIND_BUMP 0
73#define DEBUG_WINDING 1
74
75#endif
76
77#define DEBUG_DUMP (DEBUG_ACTIVE_SPANS | DEBUG_CONCIDENT | DEBUG_SORT | DEBUG_PATH_CONSTRUCTION)
78
79#if DEBUG_DUMP
80static const char* kLVerbStr[] = {"", "line", "quad", "cubic"};
81// static const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"};
82static int gContourID;
83static int gSegmentID;
84#endif
85
86#ifndef DEBUG_TEST
87#define DEBUG_TEST 0
88#endif
89
90#define MAKE_CONST_LINE(line, pts) \
91    const _Line line = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}}
92#define MAKE_CONST_QUAD(quad, pts) \
93    const Quadratic quad = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
94            {pts[2].fX, pts[2].fY}}
95#define MAKE_CONST_CUBIC(cubic, pts) \
96    const Cubic cubic = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
97            {pts[2].fX, pts[2].fY}, {pts[3].fX, pts[3].fY}}
98
99static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
100        Intersections& intersections) {
101    MAKE_CONST_LINE(aLine, a);
102    MAKE_CONST_LINE(bLine, b);
103    return intersect(aLine, bLine, intersections.fT[0], intersections.fT[1]);
104}
105
106static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
107        Intersections& intersections) {
108    MAKE_CONST_QUAD(aQuad, a);
109    MAKE_CONST_LINE(bLine, b);
110    return intersect(aQuad, bLine, intersections);
111}
112
113static int CubicLineIntersect(const SkPoint a[4], const SkPoint b[2],
114        Intersections& intersections) {
115    MAKE_CONST_CUBIC(aCubic, a);
116    MAKE_CONST_LINE(bLine, b);
117    return intersect(aCubic, bLine, intersections.fT[0], intersections.fT[1]);
118}
119
120static int QuadIntersect(const SkPoint a[3], const SkPoint b[3],
121        Intersections& intersections) {
122    MAKE_CONST_QUAD(aQuad, a);
123    MAKE_CONST_QUAD(bQuad, b);
124#define TRY_QUARTIC_SOLUTION 1
125#if TRY_QUARTIC_SOLUTION
126    intersect2(aQuad, bQuad, intersections);
127#else
128    intersect(aQuad, bQuad, intersections);
129#endif
130    return intersections.fUsed ? intersections.fUsed : intersections.fCoincidentUsed;
131}
132
133static int CubicIntersect(const SkPoint a[4], const SkPoint b[4],
134        Intersections& intersections) {
135    MAKE_CONST_CUBIC(aCubic, a);
136    MAKE_CONST_CUBIC(bCubic, b);
137    intersect(aCubic, bCubic, intersections);
138    return intersections.fUsed;
139}
140
141static int HLineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
142        SkScalar y, bool flipped, Intersections& intersections) {
143    MAKE_CONST_LINE(aLine, a);
144    return horizontalIntersect(aLine, left, right, y, flipped, intersections);
145}
146
147static int HQuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right,
148        SkScalar y, bool flipped, Intersections& intersections) {
149    MAKE_CONST_QUAD(aQuad, a);
150    return horizontalIntersect(aQuad, left, right, y, flipped, intersections);
151}
152
153static int HCubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right,
154        SkScalar y, bool flipped, Intersections& intersections) {
155    MAKE_CONST_CUBIC(aCubic, a);
156    return horizontalIntersect(aCubic, left, right, y, flipped, intersections);
157}
158
159static int (* const HSegmentIntersect[])(const SkPoint [], SkScalar ,
160        SkScalar , SkScalar , bool , Intersections& ) = {
161    NULL,
162    HLineIntersect,
163    HQuadIntersect,
164    HCubicIntersect
165};
166
167static int VLineIntersect(const SkPoint a[2], SkScalar top, SkScalar bottom,
168        SkScalar x, bool flipped, Intersections& intersections) {
169    MAKE_CONST_LINE(aLine, a);
170    return verticalIntersect(aLine, top, bottom, x, flipped, intersections);
171}
172
173static int VQuadIntersect(const SkPoint a[3], SkScalar top, SkScalar bottom,
174        SkScalar x, bool flipped, Intersections& intersections) {
175    MAKE_CONST_QUAD(aQuad, a);
176    return verticalIntersect(aQuad, top, bottom, x, flipped, intersections);
177}
178
179static int VCubicIntersect(const SkPoint a[4], SkScalar top, SkScalar bottom,
180        SkScalar x, bool flipped, Intersections& intersections) {
181    MAKE_CONST_CUBIC(aCubic, a);
182    return verticalIntersect(aCubic, top, bottom, x, flipped, intersections);
183}
184
185static int (* const VSegmentIntersect[])(const SkPoint [], SkScalar ,
186        SkScalar , SkScalar , bool , Intersections& ) = {
187    NULL,
188    VLineIntersect,
189    VQuadIntersect,
190    VCubicIntersect
191};
192
193static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
194    MAKE_CONST_LINE(line, a);
195    double x, y;
196    xy_at_t(line, t, x, y);
197    out->fX = SkDoubleToScalar(x);
198    out->fY = SkDoubleToScalar(y);
199}
200
201static void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) {
202    MAKE_CONST_QUAD(quad, a);
203    double x, y;
204    xy_at_t(quad, t, x, y);
205    out->fX = SkDoubleToScalar(x);
206    out->fY = SkDoubleToScalar(y);
207}
208
209static void QuadXYAtT(const SkPoint a[3], double t, _Point* out) {
210    MAKE_CONST_QUAD(quad, a);
211    xy_at_t(quad, t, out->x, out->y);
212}
213
214static void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) {
215    MAKE_CONST_CUBIC(cubic, a);
216    double x, y;
217    xy_at_t(cubic, t, x, y);
218    out->fX = SkDoubleToScalar(x);
219    out->fY = SkDoubleToScalar(y);
220}
221
222static void (* const SegmentXYAtT[])(const SkPoint [], double , SkPoint* ) = {
223    NULL,
224    LineXYAtT,
225    QuadXYAtT,
226    CubicXYAtT
227};
228
229static SkScalar LineXAtT(const SkPoint a[2], double t) {
230    MAKE_CONST_LINE(aLine, a);
231    double x;
232    xy_at_t(aLine, t, x, *(double*) 0);
233    return SkDoubleToScalar(x);
234}
235
236static SkScalar QuadXAtT(const SkPoint a[3], double t) {
237    MAKE_CONST_QUAD(quad, a);
238    double x;
239    xy_at_t(quad, t, x, *(double*) 0);
240    return SkDoubleToScalar(x);
241}
242
243static SkScalar CubicXAtT(const SkPoint a[4], double t) {
244    MAKE_CONST_CUBIC(cubic, a);
245    double x;
246    xy_at_t(cubic, t, x, *(double*) 0);
247    return SkDoubleToScalar(x);
248}
249
250static SkScalar (* const SegmentXAtT[])(const SkPoint [], double ) = {
251    NULL,
252    LineXAtT,
253    QuadXAtT,
254    CubicXAtT
255};
256
257static SkScalar LineYAtT(const SkPoint a[2], double t) {
258    MAKE_CONST_LINE(aLine, a);
259    double y;
260    xy_at_t(aLine, t, *(double*) 0, y);
261    return SkDoubleToScalar(y);
262}
263
264static SkScalar QuadYAtT(const SkPoint a[3], double t) {
265    MAKE_CONST_QUAD(quad, a);
266    double y;
267    xy_at_t(quad, t, *(double*) 0, y);
268    return SkDoubleToScalar(y);
269}
270
271static SkScalar CubicYAtT(const SkPoint a[4], double t) {
272    MAKE_CONST_CUBIC(cubic, a);
273    double y;
274    xy_at_t(cubic, t, *(double*) 0, y);
275    return SkDoubleToScalar(y);
276}
277
278static SkScalar (* const SegmentYAtT[])(const SkPoint [], double ) = {
279    NULL,
280    LineYAtT,
281    QuadYAtT,
282    CubicYAtT
283};
284
285static SkScalar LineDXAtT(const SkPoint a[2], double ) {
286    return a[1].fX - a[0].fX;
287}
288
289static SkScalar QuadDXAtT(const SkPoint a[3], double t) {
290    MAKE_CONST_QUAD(quad, a);
291    double x;
292    dxdy_at_t(quad, t, x, *(double*) 0);
293    return SkDoubleToScalar(x);
294}
295
296static SkScalar CubicDXAtT(const SkPoint a[4], double t) {
297    MAKE_CONST_CUBIC(cubic, a);
298    double x;
299    dxdy_at_t(cubic, t, x, *(double*) 0);
300    return SkDoubleToScalar(x);
301}
302
303static SkScalar (* const SegmentDXAtT[])(const SkPoint [], double ) = {
304    NULL,
305    LineDXAtT,
306    QuadDXAtT,
307    CubicDXAtT
308};
309
310static SkScalar LineDYAtT(const SkPoint a[2], double ) {
311    return a[1].fY - a[0].fY;
312}
313
314static SkScalar QuadDYAtT(const SkPoint a[3], double t) {
315    MAKE_CONST_QUAD(quad, a);
316    double y;
317    dxdy_at_t(quad, t, *(double*) 0, y);
318    return SkDoubleToScalar(y);
319}
320
321static SkScalar CubicDYAtT(const SkPoint a[4], double t) {
322    MAKE_CONST_CUBIC(cubic, a);
323    double y;
324    dxdy_at_t(cubic, t, *(double*) 0, y);
325    return SkDoubleToScalar(y);
326}
327
328static SkScalar (* const SegmentDYAtT[])(const SkPoint [], double ) = {
329    NULL,
330    LineDYAtT,
331    QuadDYAtT,
332    CubicDYAtT
333};
334
335static void LineSubDivide(const SkPoint a[2], double startT, double endT,
336        SkPoint sub[2]) {
337    MAKE_CONST_LINE(aLine, a);
338    _Line dst;
339    sub_divide(aLine, startT, endT, dst);
340    sub[0].fX = SkDoubleToScalar(dst[0].x);
341    sub[0].fY = SkDoubleToScalar(dst[0].y);
342    sub[1].fX = SkDoubleToScalar(dst[1].x);
343    sub[1].fY = SkDoubleToScalar(dst[1].y);
344}
345
346static void QuadSubDivide(const SkPoint a[3], double startT, double endT,
347        SkPoint sub[3]) {
348    MAKE_CONST_QUAD(aQuad, a);
349    Quadratic dst;
350    sub_divide(aQuad, startT, endT, dst);
351    sub[0].fX = SkDoubleToScalar(dst[0].x);
352    sub[0].fY = SkDoubleToScalar(dst[0].y);
353    sub[1].fX = SkDoubleToScalar(dst[1].x);
354    sub[1].fY = SkDoubleToScalar(dst[1].y);
355    sub[2].fX = SkDoubleToScalar(dst[2].x);
356    sub[2].fY = SkDoubleToScalar(dst[2].y);
357}
358
359static void CubicSubDivide(const SkPoint a[4], double startT, double endT,
360        SkPoint sub[4]) {
361    MAKE_CONST_CUBIC(aCubic, a);
362    Cubic dst;
363    sub_divide(aCubic, startT, endT, dst);
364    sub[0].fX = SkDoubleToScalar(dst[0].x);
365    sub[0].fY = SkDoubleToScalar(dst[0].y);
366    sub[1].fX = SkDoubleToScalar(dst[1].x);
367    sub[1].fY = SkDoubleToScalar(dst[1].y);
368    sub[2].fX = SkDoubleToScalar(dst[2].x);
369    sub[2].fY = SkDoubleToScalar(dst[2].y);
370    sub[3].fX = SkDoubleToScalar(dst[3].x);
371    sub[3].fY = SkDoubleToScalar(dst[3].y);
372}
373
374static void (* const SegmentSubDivide[])(const SkPoint [], double , double ,
375        SkPoint []) = {
376    NULL,
377    LineSubDivide,
378    QuadSubDivide,
379    CubicSubDivide
380};
381
382static void LineSubDivideHD(const SkPoint a[2], double startT, double endT,
383        _Line sub) {
384    MAKE_CONST_LINE(aLine, a);
385    _Line dst;
386    sub_divide(aLine, startT, endT, dst);
387    sub[0] = dst[0];
388    sub[1] = dst[1];
389}
390
391static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT,
392        Quadratic sub) {
393    MAKE_CONST_QUAD(aQuad, a);
394    Quadratic dst;
395    sub_divide(aQuad, startT, endT, dst);
396    sub[0] = dst[0];
397    sub[1] = dst[1];
398    sub[2] = dst[2];
399}
400
401static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT,
402        Cubic sub) {
403    MAKE_CONST_CUBIC(aCubic, a);
404    Cubic dst;
405    sub_divide(aCubic, startT, endT, dst);
406    sub[0] = dst[0];
407    sub[1] = dst[1];
408    sub[2] = dst[2];
409    sub[3] = dst[3];
410}
411
412#if DEBUG_UNUSED
413static void QuadSubBounds(const SkPoint a[3], double startT, double endT,
414        SkRect& bounds) {
415    SkPoint dst[3];
416    QuadSubDivide(a, startT, endT, dst);
417    bounds.fLeft = bounds.fRight = dst[0].fX;
418    bounds.fTop = bounds.fBottom = dst[0].fY;
419    for (int index = 1; index < 3; ++index) {
420        bounds.growToInclude(dst[index].fX, dst[index].fY);
421    }
422}
423
424static void CubicSubBounds(const SkPoint a[4], double startT, double endT,
425        SkRect& bounds) {
426    SkPoint dst[4];
427    CubicSubDivide(a, startT, endT, dst);
428    bounds.fLeft = bounds.fRight = dst[0].fX;
429    bounds.fTop = bounds.fBottom = dst[0].fY;
430    for (int index = 1; index < 4; ++index) {
431        bounds.growToInclude(dst[index].fX, dst[index].fY);
432    }
433}
434#endif
435
436static SkPath::Verb QuadReduceOrder(const SkPoint a[3],
437        SkTDArray<SkPoint>& reducePts) {
438    MAKE_CONST_QUAD(aQuad, a);
439    Quadratic dst;
440    int order = reduceOrder(aQuad, dst);
441    if (order == 2) { // quad became line
442        for (int index = 0; index < order; ++index) {
443            SkPoint* pt = reducePts.append();
444            pt->fX = SkDoubleToScalar(dst[index].x);
445            pt->fY = SkDoubleToScalar(dst[index].y);
446        }
447    }
448    return (SkPath::Verb) (order - 1);
449}
450
451static SkPath::Verb CubicReduceOrder(const SkPoint a[4],
452        SkTDArray<SkPoint>& reducePts) {
453    MAKE_CONST_CUBIC(aCubic, a);
454    Cubic dst;
455    int order = reduceOrder(aCubic, dst, kReduceOrder_QuadraticsAllowed);
456    if (order == 2 || order == 3) { // cubic became line or quad
457        for (int index = 0; index < order; ++index) {
458            SkPoint* pt = reducePts.append();
459            pt->fX = SkDoubleToScalar(dst[index].x);
460            pt->fY = SkDoubleToScalar(dst[index].y);
461        }
462    }
463    return (SkPath::Verb) (order - 1);
464}
465
466static bool QuadIsLinear(const SkPoint a[3]) {
467    MAKE_CONST_QUAD(aQuad, a);
468    return isLinear(aQuad, 0, 2);
469}
470
471static bool CubicIsLinear(const SkPoint a[4]) {
472    MAKE_CONST_CUBIC(aCubic, a);
473    return isLinear(aCubic, 0, 3);
474}
475
476static SkScalar LineLeftMost(const SkPoint a[2], double startT, double endT) {
477    MAKE_CONST_LINE(aLine, a);
478    double x[2];
479    xy_at_t(aLine, startT, x[0], *(double*) 0);
480    xy_at_t(aLine, endT, x[1], *(double*) 0);
481    return SkMinScalar((float) x[0], (float) x[1]);
482}
483
484static SkScalar QuadLeftMost(const SkPoint a[3], double startT, double endT) {
485    MAKE_CONST_QUAD(aQuad, a);
486    return (float) leftMostT(aQuad, startT, endT);
487}
488
489static SkScalar CubicLeftMost(const SkPoint a[4], double startT, double endT) {
490    MAKE_CONST_CUBIC(aCubic, a);
491    return (float) leftMostT(aCubic, startT, endT);
492}
493
494static SkScalar (* const SegmentLeftMost[])(const SkPoint [], double , double) = {
495    NULL,
496    LineLeftMost,
497    QuadLeftMost,
498    CubicLeftMost
499};
500
501#if 0 // currently unused
502static int QuadRayIntersect(const SkPoint a[3], const SkPoint b[2],
503        Intersections& intersections) {
504    MAKE_CONST_QUAD(aQuad, a);
505    MAKE_CONST_LINE(bLine, b);
506    return intersectRay(aQuad, bLine, intersections);
507}
508#endif
509
510static int QuadRayIntersect(const SkPoint a[3], const _Line& bLine,
511        Intersections& intersections) {
512    MAKE_CONST_QUAD(aQuad, a);
513    return intersectRay(aQuad, bLine, intersections);
514}
515
516class Segment;
517
518struct Span {
519    Segment* fOther;
520    mutable SkPoint fPt; // lazily computed as needed
521    double fT;
522    double fOtherT; // value at fOther[fOtherIndex].fT
523    int fOtherIndex;  // can't be used during intersection
524    int fWindSum; // accumulated from contours surrounding this one.
525    int fOppSum; // for binary operators: the opposite winding sum
526    int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
527    int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
528    bool fDone; // if set, this span to next higher T has been processed
529    bool fUnsortableStart; // set when start is part of an unsortable pair
530    bool fUnsortableEnd; // set when end is part of an unsortable pair
531    bool fTiny; // if set, span may still be considered once for edge following
532};
533
534// sorting angles
535// given angles of {dx dy ddx ddy dddx dddy} sort them
536class Angle {
537public:
538    // FIXME: this is bogus for quads and cubics
539    // if the quads and cubics' line from end pt to ctrl pt are coincident,
540    // there's no obvious way to determine the curve ordering from the
541    // derivatives alone. In particular, if one quadratic's coincident tangent
542    // is longer than the other curve, the final control point can place the
543    // longer curve on either side of the shorter one.
544    // Using Bezier curve focus http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
545    // may provide some help, but nothing has been figured out yet.
546
547    /*(
548    for quads and cubics, set up a parameterized line (e.g. LineParameters )
549    for points [0] to [1]. See if point [2] is on that line, or on one side
550    or the other. If it both quads' end points are on the same side, choose
551    the shorter tangent. If the tangents are equal, choose the better second
552    tangent angle
553
554    maybe I could set up LineParameters lazily
555    */
556    bool operator<(const Angle& rh) const {
557        double y = dy();
558        double ry = rh.dy();
559        if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
560            return y < 0;
561        }
562        double x = dx();
563        double rx = rh.dx();
564        if (y == 0 && ry == 0 && x * rx < 0) {
565            return x < rx;
566        }
567        double x_ry = x * ry;
568        double rx_y = rx * y;
569        double cmp = x_ry - rx_y;
570        if (!approximately_zero(cmp)) {
571            return cmp < 0;
572        }
573        if (approximately_zero(x_ry) && approximately_zero(rx_y)
574                && !approximately_zero_squared(cmp)) {
575            return cmp < 0;
576        }
577        // at this point, the initial tangent line is coincident
578        if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide)
579                || !approximately_zero(rh.fSide))) {
580            // FIXME: running demo will trigger this assertion
581            // (don't know if commenting out will trigger further assertion or not)
582            // commenting it out allows demo to run in release, though
583     //       SkASSERT(fSide != rh.fSide);
584            return fSide < rh.fSide;
585        }
586        // see if either curve can be lengthened and try the tangent compare again
587        if (cmp && (*fSpans)[fEnd].fOther != rh.fSegment // tangents not absolutely identical
588                && (*rh.fSpans)[rh.fEnd].fOther != fSegment) { // and not intersecting
589            Angle longer = *this;
590            Angle rhLonger = rh;
591            if (longer.lengthen() | rhLonger.lengthen()) {
592                return longer < rhLonger;
593            }
594            // what if we extend in the other direction?
595            longer = *this;
596            rhLonger = rh;
597            if (longer.reverseLengthen() | rhLonger.reverseLengthen()) {
598                return longer < rhLonger;
599            }
600        }
601        if ((fVerb == SkPath::kLine_Verb && approximately_zero(x) && approximately_zero(y))
602                || (rh.fVerb == SkPath::kLine_Verb
603                && approximately_zero(rx) && approximately_zero(ry))) {
604            // See general unsortable comment below. This case can happen when
605            // one line has a non-zero change in t but no change in x and y.
606            fUnsortable = true;
607            rh.fUnsortable = true;
608            return this < &rh; // even with no solution, return a stable sort
609        }
610        if ((*rh.fSpans)[SkMin32(rh.fStart, rh.fEnd)].fTiny
611                || (*fSpans)[SkMin32(fStart, fEnd)].fTiny) {
612            fUnsortable = true;
613            rh.fUnsortable = true;
614            return this < &rh; // even with no solution, return a stable sort
615        }
616        SkASSERT(fVerb == SkPath::kQuad_Verb); // worry about cubics later
617        SkASSERT(rh.fVerb == SkPath::kQuad_Verb);
618        // FIXME: until I can think of something better, project a ray from the
619        // end of the shorter tangent to midway between the end points
620        // through both curves and use the resulting angle to sort
621        // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive
622        double len = fTangent1.normalSquared();
623        double rlen = rh.fTangent1.normalSquared();
624        _Line ray;
625        Intersections i, ri;
626        int roots, rroots;
627        bool flip = false;
628        do {
629            const Quadratic& q = (len < rlen) ^ flip ? fQ : rh.fQ;
630            double midX = (q[0].x + q[2].x) / 2;
631            double midY = (q[0].y + q[2].y) / 2;
632            ray[0] = q[1];
633            ray[1].x = midX;
634            ray[1].y = midY;
635            SkASSERT(ray[0] != ray[1]);
636            roots = QuadRayIntersect(fPts, ray, i);
637            rroots = QuadRayIntersect(rh.fPts, ray, ri);
638        } while ((roots == 0 || rroots == 0) && (flip ^= true));
639        if (roots == 0 || rroots == 0) {
640            // FIXME: we don't have a solution in this case. The interim solution
641            // is to mark the edges as unsortable, exclude them from this and
642            // future computations, and allow the returned path to be fragmented
643            fUnsortable = true;
644            rh.fUnsortable = true;
645            return this < &rh; // even with no solution, return a stable sort
646        }
647        _Point loc;
648        double best = SK_ScalarInfinity;
649        double dx, dy, dist;
650        int index;
651        for (index = 0; index < roots; ++index) {
652            QuadXYAtT(fPts, i.fT[0][index], &loc);
653            dx = loc.x - ray[0].x;
654            dy = loc.y - ray[0].y;
655            dist = dx * dx + dy * dy;
656            if (best > dist) {
657                best = dist;
658            }
659        }
660        for (index = 0; index < rroots; ++index) {
661            QuadXYAtT(rh.fPts, ri.fT[0][index], &loc);
662            dx = loc.x - ray[0].x;
663            dy = loc.y - ray[0].y;
664            dist = dx * dx + dy * dy;
665            if (best > dist) {
666                return fSide < 0;
667            }
668        }
669        return fSide > 0;
670    }
671
672    double dx() const {
673        return fTangent1.dx();
674    }
675
676    double dy() const {
677        return fTangent1.dy();
678    }
679
680    int end() const {
681        return fEnd;
682    }
683
684    bool isHorizontal() const {
685        return dy() == 0 && fVerb == SkPath::kLine_Verb;
686    }
687
688    bool lengthen() {
689        int newEnd = fEnd;
690        if (fStart < fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
691            fEnd = newEnd;
692            setSpans();
693            return true;
694        }
695        return false;
696    }
697
698    bool reverseLengthen() {
699        if (fReversed) {
700            return false;
701        }
702        int newEnd = fStart;
703        if (fStart > fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
704            fEnd = newEnd;
705            fReversed = true;
706            setSpans();
707            return true;
708        }
709        return false;
710    }
711
712    void set(const SkPoint* orig, SkPath::Verb verb, const Segment* segment,
713            int start, int end, const SkTDArray<Span>& spans) {
714        fSegment = segment;
715        fStart = start;
716        fEnd = end;
717        fPts = orig;
718        fVerb = verb;
719        fSpans = &spans;
720        fReversed = false;
721        fUnsortable = false;
722        setSpans();
723    }
724
725    void setSpans() {
726        double startT = (*fSpans)[fStart].fT;
727        double endT = (*fSpans)[fEnd].fT;
728        switch (fVerb) {
729        case SkPath::kLine_Verb:
730            _Line l;
731            LineSubDivideHD(fPts, startT, endT, l);
732            // OPTIMIZATION: for pure line compares, we never need fTangent1.c
733            fTangent1.lineEndPoints(l);
734            fUnsortable = dx() == 0 && dy() == 0;
735            fSide = 0;
736            break;
737        case SkPath::kQuad_Verb:
738            QuadSubDivideHD(fPts, startT, endT, fQ);
739            fTangent1.quadEndPoints(fQ, 0, 1);
740            fSide = -fTangent1.pointDistance(fQ[2]); // not normalized -- compare sign only
741            break;
742        case SkPath::kCubic_Verb:
743            Cubic c;
744            CubicSubDivideHD(fPts, startT, endT, c);
745            fTangent1.cubicEndPoints(c, 0, 1);
746            fSide = -fTangent1.pointDistance(c[2]); // not normalized -- compare sign only
747            break;
748        default:
749            SkASSERT(0);
750        }
751        if (fUnsortable) {
752            return;
753        }
754        SkASSERT(fStart != fEnd);
755        int step = fStart < fEnd ? 1 : -1; // OPTIMIZE: worth fStart - fEnd >> 31 type macro?
756        for (int index = fStart; index != fEnd; index += step) {
757            if ((*fSpans)[index].fUnsortableStart) {
758                fUnsortable = true;
759                return;
760            }
761#if 0
762            if (index != fStart && (*fSpans)[index].fUnsortableEnd) {
763                SkASSERT(0);
764                fUnsortable = true;
765                return;
766            }
767#endif
768        }
769    }
770
771    Segment* segment() const {
772        return const_cast<Segment*>(fSegment);
773    }
774
775    int sign() const {
776        return SkSign32(fStart - fEnd);
777    }
778
779    const SkTDArray<Span>* spans() const {
780        return fSpans;
781    }
782
783    int start() const {
784        return fStart;
785    }
786
787    bool unsortable() const {
788        return fUnsortable;
789    }
790
791#if DEBUG_ANGLE
792    const SkPoint* pts() const {
793        return fPts;
794    }
795
796    SkPath::Verb verb() const {
797        return fVerb;
798    }
799
800    void debugShow(const SkPoint& a) const {
801        SkDebugf("    d=(%1.9g,%1.9g) side=%1.9g\n", dx(), dy(), fSide);
802    }
803#endif
804
805private:
806    const SkPoint* fPts;
807    Quadratic fQ;
808    SkPath::Verb fVerb;
809    double fSide;
810    LineParameters fTangent1;
811    const SkTDArray<Span>* fSpans;
812    const Segment* fSegment;
813    int fStart;
814    int fEnd;
815    bool fReversed;
816    mutable bool fUnsortable; // this alone is editable by the less than operator
817};
818
819// Bounds, unlike Rect, does not consider a line to be empty.
820struct Bounds : public SkRect {
821    static bool Intersects(const Bounds& a, const Bounds& b) {
822        return a.fLeft <= b.fRight && b.fLeft <= a.fRight &&
823                a.fTop <= b.fBottom && b.fTop <= a.fBottom;
824    }
825
826    void add(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
827        if (left < fLeft) {
828            fLeft = left;
829        }
830        if (top < fTop) {
831            fTop = top;
832        }
833        if (right > fRight) {
834            fRight = right;
835        }
836        if (bottom > fBottom) {
837            fBottom = bottom;
838        }
839    }
840
841    void add(const Bounds& toAdd) {
842        add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom);
843    }
844
845    void add(const SkPoint& pt) {
846        if (pt.fX < fLeft) fLeft = pt.fX;
847        if (pt.fY < fTop) fTop = pt.fY;
848        if (pt.fX > fRight) fRight = pt.fX;
849        if (pt.fY > fBottom) fBottom = pt.fY;
850    }
851
852    bool isEmpty() {
853        return fLeft > fRight || fTop > fBottom
854                || (fLeft == fRight && fTop == fBottom)
855                || isnan(fLeft) || isnan(fRight)
856                || isnan(fTop) || isnan(fBottom);
857    }
858
859    void setCubicBounds(const SkPoint a[4]) {
860        _Rect dRect;
861        MAKE_CONST_CUBIC(cubic, a);
862        dRect.setBounds(cubic);
863        set((float) dRect.left, (float) dRect.top, (float) dRect.right,
864                (float) dRect.bottom);
865    }
866
867    void setQuadBounds(const SkPoint a[3]) {
868        MAKE_CONST_QUAD(quad, a);
869        _Rect dRect;
870        dRect.setBounds(quad);
871        set((float) dRect.left, (float) dRect.top, (float) dRect.right,
872                (float) dRect.bottom);
873    }
874
875    void setPoint(const SkPoint& pt) {
876        fLeft = fRight = pt.fX;
877        fTop = fBottom = pt.fY;
878    }
879};
880
881// OPTIMIZATION: does the following also work, and is it any faster?
882// return outerWinding * innerWinding > 0
883//      || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
884static bool useInnerWinding(int outerWinding, int innerWinding) {
885  //  SkASSERT(outerWinding != innerWinding);
886    int absOut = abs(outerWinding);
887    int absIn = abs(innerWinding);
888    bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
889    if (outerWinding * innerWinding < 0) {
890#if DEBUG_WINDING
891        SkDebugf("%s outer=%d inner=%d result=%s\n", __FUNCTION__,
892                outerWinding, innerWinding, result ? "true" : "false");
893#endif
894    }
895    return result;
896}
897
898#define F (false)      // discard the edge
899#define T (true)       // keep the edge
900
901static const bool gUnaryActiveEdge[2][2] = {
902//  from=0  from=1
903//  to=0,1  to=0,1
904    {F, T}, {T, F},
905};
906
907static const bool gActiveEdge[kShapeOp_Count][2][2][2][2] = {
908//                 miFrom=0                              miFrom=1
909//         miTo=0            miTo=1              miTo=0             miTo=1
910//    suFrom=0    1     suFrom=0     1      suFrom=0    1      suFrom=0    1
911//   suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1  suTo=0,1 suTo=0,1
912    {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su
913    {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su
914    {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su
915    {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su
916};
917
918#undef F
919#undef T
920
921// wrap path to keep track of whether the contour is initialized and non-empty
922class PathWrapper {
923public:
924    PathWrapper(SkPath& path)
925        : fPathPtr(&path)
926        , fCloses(0)
927        , fMoves(0)
928    {
929        init();
930    }
931
932    void close() {
933        if (!fHasMove) {
934            return;
935        }
936        bool callClose = isClosed();
937        lineTo();
938        if (fEmpty) {
939            return;
940        }
941        if (callClose) {
942    #if DEBUG_PATH_CONSTRUCTION
943            SkDebugf("path.close();\n");
944    #endif
945            fPathPtr->close();
946            fCloses++;
947        }
948        init();
949    }
950
951    void cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
952        lineTo();
953        moveTo();
954#if DEBUG_PATH_CONSTRUCTION
955        SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
956                pt1.fX, pt1.fY, pt2.fX, pt2.fY, pt3.fX, pt3.fY);
957#endif
958        fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, pt3.fX, pt3.fY);
959        fDefer[0] = fDefer[1] = pt3;
960        fEmpty = false;
961    }
962
963    void deferredLine(const SkPoint& pt) {
964        if (pt == fDefer[1]) {
965            return;
966        }
967        if (changedSlopes(pt)) {
968            lineTo();
969            fDefer[0] = fDefer[1];
970        }
971        fDefer[1] = pt;
972    }
973
974    void deferredMove(const SkPoint& pt) {
975        fMoved = true;
976        fHasMove = true;
977        fEmpty = true;
978        fDefer[0] = fDefer[1] = pt;
979    }
980
981    void deferredMoveLine(const SkPoint& pt) {
982        if (!fHasMove) {
983            deferredMove(pt);
984        }
985        deferredLine(pt);
986    }
987
988    bool hasMove() const {
989        return fHasMove;
990    }
991
992    void init() {
993        fEmpty = true;
994        fHasMove = false;
995        fMoved = false;
996    }
997
998    bool isClosed() const {
999        return !fEmpty && fFirstPt == fDefer[1];
1000    }
1001
1002    void lineTo() {
1003        if (fDefer[0] == fDefer[1]) {
1004            return;
1005        }
1006        moveTo();
1007        fEmpty = false;
1008#if DEBUG_PATH_CONSTRUCTION
1009        SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
1010#endif
1011        fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
1012        fDefer[0] = fDefer[1];
1013    }
1014
1015    const SkPath* nativePath() const {
1016        return fPathPtr;
1017    }
1018
1019    void quadTo(const SkPoint& pt1, const SkPoint& pt2) {
1020        lineTo();
1021        moveTo();
1022#if DEBUG_PATH_CONSTRUCTION
1023        SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
1024                pt1.fX, pt1.fY, pt2.fX, pt2.fY);
1025#endif
1026        fPathPtr->quadTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY);
1027        fDefer[0] = fDefer[1] = pt2;
1028        fEmpty = false;
1029    }
1030
1031    bool someAssemblyRequired() const {
1032        return fCloses < fMoves;
1033    }
1034
1035protected:
1036    bool changedSlopes(const SkPoint& pt) const {
1037        if (fDefer[0] == fDefer[1]) {
1038            return false;
1039        }
1040        SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
1041        SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
1042        SkScalar lineDx = pt.fX - fDefer[1].fX;
1043        SkScalar lineDy = pt.fY - fDefer[1].fY;
1044        return deferDx * lineDy != deferDy * lineDx;
1045    }
1046
1047    void moveTo() {
1048        if (!fMoved) {
1049            return;
1050        }
1051        fFirstPt = fDefer[0];
1052#if DEBUG_PATH_CONSTRUCTION
1053        SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
1054#endif
1055        fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
1056        fMoved = false;
1057        fMoves++;
1058    }
1059
1060private:
1061    SkPath* fPathPtr;
1062    SkPoint fDefer[2];
1063    SkPoint fFirstPt;
1064    int fCloses;
1065    int fMoves;
1066    bool fEmpty;
1067    bool fHasMove;
1068    bool fMoved;
1069};
1070
1071class Segment {
1072public:
1073    Segment() {
1074#if DEBUG_DUMP
1075        fID = ++gSegmentID;
1076#endif
1077    }
1078
1079    bool operator<(const Segment& rh) const {
1080        return fBounds.fTop < rh.fBounds.fTop;
1081    }
1082
1083    bool activeAngle(int index, int& done, SkTDArray<Angle>& angles) {
1084        if (activeAngleInner(index, done, angles)) {
1085            return true;
1086        }
1087        double referenceT = fTs[index].fT;
1088        int lesser = index;
1089        while (--lesser >= 0 && approximately_negative(referenceT - fTs[lesser].fT)) {
1090            if (activeAngleOther(lesser, done, angles)) {
1091                return true;
1092            }
1093        }
1094        do {
1095            if (activeAngleOther(index, done, angles)) {
1096                return true;
1097            }
1098        } while (++index < fTs.count() && approximately_negative(fTs[index].fT - referenceT));
1099        return false;
1100    }
1101
1102    bool activeAngleOther(int index, int& done, SkTDArray<Angle>& angles) {
1103        Span* span = &fTs[index];
1104        Segment* other = span->fOther;
1105        int oIndex = span->fOtherIndex;
1106        return other->activeAngleInner(oIndex, done, angles);
1107    }
1108
1109    bool activeAngleInner(int index, int& done, SkTDArray<Angle>& angles) {
1110        int next = nextExactSpan(index, 1);
1111        if (next > 0) {
1112            Span& upSpan = fTs[index];
1113            if (upSpan.fWindValue || upSpan.fOppValue) {
1114                addAngle(angles, index, next);
1115                if (upSpan.fDone || upSpan.fUnsortableEnd) {
1116                    done++;
1117                } else if (upSpan.fWindSum != SK_MinS32) {
1118                    return true;
1119                }
1120            } else if (!upSpan.fDone) {
1121                upSpan.fDone = true;
1122                fDoneSpans++;
1123            }
1124        }
1125        int prev = nextExactSpan(index, -1);
1126        // edge leading into junction
1127        if (prev >= 0) {
1128            Span& downSpan = fTs[prev];
1129            if (downSpan.fWindValue || downSpan.fOppValue) {
1130                addAngle(angles, index, prev);
1131                if (downSpan.fDone) {
1132                    done++;
1133                 } else if (downSpan.fWindSum != SK_MinS32) {
1134                    return true;
1135                }
1136            } else if (!downSpan.fDone) {
1137                downSpan.fDone = true;
1138                fDoneSpans++;
1139            }
1140        }
1141        return false;
1142    }
1143
1144    void activeLeftTop(SkPoint& result) const {
1145        SkASSERT(!done());
1146        int count = fTs.count();
1147        result.fY = SK_ScalarMax;
1148        bool lastDone = true;
1149        bool lastUnsortable = false;
1150        for (int index = 0; index < count; ++index) {
1151            const Span& span = fTs[index];
1152            if (span.fUnsortableStart | lastUnsortable) {
1153                goto next;
1154            }
1155            if (!span.fDone | !lastDone) {
1156                const SkPoint& xy = xyAtT(index);
1157                if (result.fY < xy.fY) {
1158                    goto next;
1159                }
1160                if (result.fY == xy.fY && result.fX < xy.fX) {
1161                    goto next;
1162                }
1163                result = xy;
1164            }
1165    next:
1166            lastDone = span.fDone;
1167            lastUnsortable = span.fUnsortableEnd;
1168        }
1169        SkASSERT(result.fY < SK_ScalarMax);
1170    }
1171
1172    bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, ShapeOp op) {
1173        int sumMiWinding = updateWinding(endIndex, index);
1174        int sumSuWinding = updateOppWinding(endIndex, index);
1175        if (fOperand) {
1176            SkTSwap<int>(sumMiWinding, sumSuWinding);
1177        }
1178        int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
1179        return activeOp(xorMiMask, xorSuMask, index, endIndex, op, sumMiWinding, sumSuWinding,
1180                maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
1181    }
1182
1183    bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, ShapeOp op,
1184            int& sumMiWinding, int& sumSuWinding,
1185            int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding) {
1186        setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
1187                maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
1188        bool miFrom;
1189        bool miTo;
1190        bool suFrom;
1191        bool suTo;
1192        if (operand()) {
1193            miFrom = (oppMaxWinding & xorMiMask) != 0;
1194            miTo = (oppSumWinding & xorMiMask) != 0;
1195            suFrom = (maxWinding & xorSuMask) != 0;
1196            suTo = (sumWinding & xorSuMask) != 0;
1197        } else {
1198            miFrom = (maxWinding & xorMiMask) != 0;
1199            miTo = (sumWinding & xorMiMask) != 0;
1200            suFrom = (oppMaxWinding & xorSuMask) != 0;
1201            suTo = (oppSumWinding & xorSuMask) != 0;
1202        }
1203        bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
1204        SkASSERT(result != -1);
1205        return result;
1206    }
1207
1208    bool activeWinding(int index, int endIndex) {
1209        int sumWinding = updateWinding(endIndex, index);
1210        int maxWinding;
1211        return activeWinding(index, endIndex, maxWinding, sumWinding);
1212    }
1213
1214    bool activeWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
1215        setUpWinding(index, endIndex, maxWinding, sumWinding);
1216        bool from = maxWinding != 0;
1217        bool to = sumWinding  != 0;
1218        bool result = gUnaryActiveEdge[from][to];
1219        SkASSERT(result != -1);
1220        return result;
1221    }
1222
1223    void addAngle(SkTDArray<Angle>& angles, int start, int end) const {
1224        SkASSERT(start != end);
1225        Angle* angle = angles.append();
1226#if DEBUG_ANGLE
1227        if (angles.count() > 1 && !fTs[start].fTiny) {
1228            SkPoint angle0Pt, newPt;
1229            (*SegmentXYAtT[angles[0].verb()])(angles[0].pts(),
1230                    (*angles[0].spans())[angles[0].start()].fT, &angle0Pt);
1231            (*SegmentXYAtT[fVerb])(fPts, fTs[start].fT, &newPt);
1232            SkASSERT(approximately_equal(angle0Pt.fX, newPt.fX));
1233            SkASSERT(approximately_equal(angle0Pt.fY, newPt.fY));
1234        }
1235#endif
1236        angle->set(fPts, fVerb, this, start, end, fTs);
1237    }
1238
1239    void addCancelOutsides(double tStart, double oStart, Segment& other,
1240            double oEnd) {
1241        int tIndex = -1;
1242        int tCount = fTs.count();
1243        int oIndex = -1;
1244        int oCount = other.fTs.count();
1245        do {
1246            ++tIndex;
1247        } while (!approximately_negative(tStart - fTs[tIndex].fT) && tIndex < tCount);
1248        int tIndexStart = tIndex;
1249        do {
1250            ++oIndex;
1251        } while (!approximately_negative(oStart - other.fTs[oIndex].fT) && oIndex < oCount);
1252        int oIndexStart = oIndex;
1253        double nextT;
1254        do {
1255            nextT = fTs[++tIndex].fT;
1256        } while (nextT < 1 && approximately_negative(nextT - tStart));
1257        double oNextT;
1258        do {
1259            oNextT = other.fTs[++oIndex].fT;
1260        } while (oNextT < 1 && approximately_negative(oNextT - oStart));
1261        // at this point, spans before and after are at:
1262        //  fTs[tIndexStart - 1], fTs[tIndexStart], fTs[tIndex]
1263        // if tIndexStart == 0, no prior span
1264        // if nextT == 1, no following span
1265
1266        // advance the span with zero winding
1267        // if the following span exists (not past the end, non-zero winding)
1268        // connect the two edges
1269        if (!fTs[tIndexStart].fWindValue) {
1270            if (tIndexStart > 0 && fTs[tIndexStart - 1].fWindValue) {
1271    #if DEBUG_CONCIDENT
1272                SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
1273                        __FUNCTION__, fID, other.fID, tIndexStart - 1,
1274                        fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
1275                        xyAtT(tIndexStart).fY);
1276    #endif
1277                addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT, false);
1278            }
1279            if (nextT < 1 && fTs[tIndex].fWindValue) {
1280    #if DEBUG_CONCIDENT
1281                SkDebugf("%s 2 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
1282                        __FUNCTION__, fID, other.fID, tIndex,
1283                        fTs[tIndex].fT, xyAtT(tIndex).fX,
1284                        xyAtT(tIndex).fY);
1285    #endif
1286                addTPair(fTs[tIndex].fT, other, other.fTs[oIndexStart].fT, false);
1287            }
1288        } else {
1289            SkASSERT(!other.fTs[oIndexStart].fWindValue);
1290            if (oIndexStart > 0 && other.fTs[oIndexStart - 1].fWindValue) {
1291    #if DEBUG_CONCIDENT
1292                SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
1293                        __FUNCTION__, fID, other.fID, oIndexStart - 1,
1294                        other.fTs[oIndexStart].fT, other.xyAtT(oIndexStart).fX,
1295                        other.xyAtT(oIndexStart).fY);
1296                other.debugAddTPair(other.fTs[oIndexStart].fT, *this, fTs[tIndex].fT);
1297    #endif
1298            }
1299            if (oNextT < 1 && other.fTs[oIndex].fWindValue) {
1300    #if DEBUG_CONCIDENT
1301                SkDebugf("%s 4 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
1302                        __FUNCTION__, fID, other.fID, oIndex,
1303                        other.fTs[oIndex].fT, other.xyAtT(oIndex).fX,
1304                        other.xyAtT(oIndex).fY);
1305                other.debugAddTPair(other.fTs[oIndex].fT, *this, fTs[tIndexStart].fT);
1306    #endif
1307            }
1308        }
1309    }
1310
1311    void addCoinOutsides(const SkTDArray<double>& outsideTs, Segment& other,
1312            double oEnd) {
1313        // walk this to outsideTs[0]
1314        // walk other to outsideTs[1]
1315        // if either is > 0, add a pointer to the other, copying adjacent winding
1316        int tIndex = -1;
1317        int oIndex = -1;
1318        double tStart = outsideTs[0];
1319        double oStart = outsideTs[1];
1320        do {
1321            ++tIndex;
1322        } while (!approximately_negative(tStart - fTs[tIndex].fT));
1323        do {
1324            ++oIndex;
1325        } while (!approximately_negative(oStart - other.fTs[oIndex].fT));
1326        if (tIndex > 0 || oIndex > 0 || fOperand != other.fOperand) {
1327            addTPair(tStart, other, oStart, false);
1328        }
1329        tStart = fTs[tIndex].fT;
1330        oStart = other.fTs[oIndex].fT;
1331        do {
1332            double nextT;
1333            do {
1334                nextT = fTs[++tIndex].fT;
1335            } while (approximately_negative(nextT - tStart));
1336            tStart = nextT;
1337            do {
1338                nextT = other.fTs[++oIndex].fT;
1339            } while (approximately_negative(nextT - oStart));
1340            oStart = nextT;
1341            if (tStart == 1 && oStart == 1 && fOperand == other.fOperand) {
1342                break;
1343            }
1344            addTPair(tStart, other, oStart, false);
1345        } while (tStart < 1 && oStart < 1 && !approximately_negative(oEnd - oStart));
1346    }
1347
1348    void addCubic(const SkPoint pts[4], bool operand, bool evenOdd) {
1349        init(pts, SkPath::kCubic_Verb, operand, evenOdd);
1350        fBounds.setCubicBounds(pts);
1351    }
1352
1353    /* SkPoint */ void addCurveTo(int start, int end, PathWrapper& path, bool active) const {
1354        SkPoint edge[4];
1355        const SkPoint* ePtr;
1356        int lastT = fTs.count() - 1;
1357        if (lastT < 0 || (start == 0 && end == lastT) || (start == lastT && end == 0)) {
1358            ePtr = fPts;
1359        } else {
1360        // OPTIMIZE? if not active, skip remainder and return xy_at_t(end)
1361            (*SegmentSubDivide[fVerb])(fPts, fTs[start].fT, fTs[end].fT, edge);
1362            ePtr = edge;
1363        }
1364        if (active) {
1365            bool reverse = ePtr == fPts && start != 0;
1366            if (reverse) {
1367                path.deferredMoveLine(ePtr[fVerb]);
1368                switch (fVerb) {
1369                    case SkPath::kLine_Verb:
1370                        path.deferredLine(ePtr[0]);
1371                        break;
1372                    case SkPath::kQuad_Verb:
1373                        path.quadTo(ePtr[1], ePtr[0]);
1374                        break;
1375                    case SkPath::kCubic_Verb:
1376                        path.cubicTo(ePtr[2], ePtr[1], ePtr[0]);
1377                        break;
1378                    default:
1379                        SkASSERT(0);
1380                }
1381       //         return ePtr[0];
1382           } else {
1383                path.deferredMoveLine(ePtr[0]);
1384                switch (fVerb) {
1385                    case SkPath::kLine_Verb:
1386                        path.deferredLine(ePtr[1]);
1387                        break;
1388                    case SkPath::kQuad_Verb:
1389                        path.quadTo(ePtr[1], ePtr[2]);
1390                        break;
1391                    case SkPath::kCubic_Verb:
1392                        path.cubicTo(ePtr[1], ePtr[2], ePtr[3]);
1393                        break;
1394                    default:
1395                        SkASSERT(0);
1396                }
1397            }
1398        }
1399      //  return ePtr[fVerb];
1400    }
1401
1402    void addLine(const SkPoint pts[2], bool operand, bool evenOdd) {
1403        init(pts, SkPath::kLine_Verb, operand, evenOdd);
1404        fBounds.set(pts, 2);
1405    }
1406
1407#if 0
1408    const SkPoint& addMoveTo(int tIndex, PathWrapper& path, bool active) const {
1409        const SkPoint& pt = xyAtT(tIndex);
1410        if (active) {
1411            path.deferredMove(pt);
1412        }
1413        return pt;
1414    }
1415#endif
1416
1417    // add 2 to edge or out of range values to get T extremes
1418    void addOtherT(int index, double otherT, int otherIndex) {
1419        Span& span = fTs[index];
1420    #if PIN_ADD_T
1421        if (precisely_less_than_zero(otherT)) {
1422            otherT = 0;
1423        } else if (precisely_greater_than_one(otherT)) {
1424            otherT = 1;
1425        }
1426    #endif
1427        span.fOtherT = otherT;
1428        span.fOtherIndex = otherIndex;
1429    }
1430
1431    void addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
1432        init(pts, SkPath::kQuad_Verb, operand, evenOdd);
1433        fBounds.setQuadBounds(pts);
1434    }
1435
1436    // Defer all coincident edge processing until
1437    // after normal intersections have been computed
1438
1439// no need to be tricky; insert in normal T order
1440// resolve overlapping ts when considering coincidence later
1441
1442    // add non-coincident intersection. Resulting edges are sorted in T.
1443    int addT(double newT, Segment* other) {
1444        // FIXME: in the pathological case where there is a ton of intercepts,
1445        //  binary search?
1446        int insertedAt = -1;
1447        size_t tCount = fTs.count();
1448    #if PIN_ADD_T
1449        // FIXME: only do this pinning here (e.g. this is done also in quad/line intersect)
1450        if (precisely_less_than_zero(newT)) {
1451            newT = 0;
1452        } else if (precisely_greater_than_one(newT)) {
1453            newT = 1;
1454        }
1455    #endif
1456        for (size_t index = 0; index < tCount; ++index) {
1457            // OPTIMIZATION: if there are three or more identical Ts, then
1458            // the fourth and following could be further insertion-sorted so
1459            // that all the edges are clockwise or counterclockwise.
1460            // This could later limit segment tests to the two adjacent
1461            // neighbors, although it doesn't help with determining which
1462            // circular direction to go in.
1463            if (newT < fTs[index].fT) {
1464                insertedAt = index;
1465                break;
1466            }
1467        }
1468        Span* span;
1469        if (insertedAt >= 0) {
1470            span = fTs.insert(insertedAt);
1471        } else {
1472            insertedAt = tCount;
1473            span = fTs.append();
1474        }
1475        span->fT = newT;
1476        span->fOther = other;
1477        span->fPt.fX = SK_ScalarNaN;
1478        span->fWindSum = SK_MinS32;
1479        span->fOppSum = SK_MinS32;
1480        span->fWindValue = 1;
1481        span->fOppValue = 0;
1482        span->fTiny = false;
1483        if ((span->fDone = newT == 1)) {
1484            ++fDoneSpans;
1485        }
1486        span->fUnsortableStart = false;
1487        span->fUnsortableEnd = false;
1488        if (span - fTs.begin() > 0 && !span[-1].fDone
1489                && !precisely_negative(newT - span[-1].fT)
1490 //               && approximately_negative(newT - span[-1].fT)
1491                && xyAtT(&span[-1]) == xyAtT(span)) {
1492            span[-1].fTiny = true;
1493            span[-1].fDone = true;
1494            if (approximately_negative(newT - span[-1].fT)) {
1495                if (approximately_greater_than_one(newT)) {
1496                    span[-1].fUnsortableStart = true;
1497                    span[-2].fUnsortableEnd = true;
1498                }
1499                if (approximately_less_than_zero(span[-1].fT)) {
1500                    span->fUnsortableStart = true;
1501                    span[-1].fUnsortableEnd = true;
1502                }
1503            }
1504            ++fDoneSpans;
1505        }
1506        if (fTs.end() - span > 1 && !span->fDone
1507                && !precisely_negative(span[1].fT - newT)
1508 //               && approximately_negative(span[1].fT - newT)
1509                && xyAtT(&span[1]) == xyAtT(span)) {
1510            span->fTiny = true;
1511            span->fDone = true;
1512            if (approximately_negative(span[1].fT - newT)) {
1513                if (approximately_greater_than_one(span[1].fT)) {
1514                    span->fUnsortableStart = true;
1515                    span[-1].fUnsortableEnd = true;
1516                }
1517                if (approximately_less_than_zero(newT)) {
1518                    span[1].fUnsortableStart = true;
1519                    span->fUnsortableEnd = true;
1520                }
1521            }
1522            ++fDoneSpans;
1523        }
1524        return insertedAt;
1525    }
1526
1527    // set spans from start to end to decrement by one
1528    // note this walks other backwards
1529    // FIMXE: there's probably an edge case that can be constructed where
1530    // two span in one segment are separated by float epsilon on one span but
1531    // not the other, if one segment is very small. For this
1532    // case the counts asserted below may or may not be enough to separate the
1533    // spans. Even if the counts work out, what if the spans aren't correctly
1534    // sorted? It feels better in such a case to match the span's other span
1535    // pointer since both coincident segments must contain the same spans.
1536    void addTCancel(double startT, double endT, Segment& other,
1537            double oStartT, double oEndT) {
1538        SkASSERT(!approximately_negative(endT - startT));
1539        SkASSERT(!approximately_negative(oEndT - oStartT));
1540        bool binary = fOperand != other.fOperand;
1541        int index = 0;
1542        while (!approximately_negative(startT - fTs[index].fT)) {
1543            ++index;
1544        }
1545        int oIndex = other.fTs.count();
1546        while (approximately_positive(other.fTs[--oIndex].fT - oEndT))
1547            ;
1548        double tRatio = (oEndT - oStartT) / (endT - startT);
1549        Span* test = &fTs[index];
1550        Span* oTest = &other.fTs[oIndex];
1551        SkTDArray<double> outsideTs;
1552        SkTDArray<double> oOutsideTs;
1553        do {
1554            bool decrement = test->fWindValue && oTest->fWindValue && !binary;
1555            bool track = test->fWindValue || oTest->fWindValue;
1556            double testT = test->fT;
1557            double oTestT = oTest->fT;
1558            Span* span = test;
1559            do {
1560                if (decrement) {
1561                    decrementSpan(span);
1562                } else if (track && span->fT < 1 && oTestT < 1) {
1563                    TrackOutside(outsideTs, span->fT, oTestT);
1564                }
1565                span = &fTs[++index];
1566            } while (approximately_negative(span->fT - testT));
1567            Span* oSpan = oTest;
1568            double otherTMatchStart = oEndT - (span->fT - startT) * tRatio;
1569            double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio;
1570            SkDEBUGCODE(int originalWindValue = oSpan->fWindValue);
1571            while (approximately_negative(otherTMatchStart - oSpan->fT)
1572                    && !approximately_negative(otherTMatchEnd - oSpan->fT)) {
1573        #ifdef SK_DEBUG
1574                SkASSERT(originalWindValue == oSpan->fWindValue);
1575        #endif
1576                if (decrement) {
1577                    other.decrementSpan(oSpan);
1578                } else if (track && oSpan->fT < 1 && testT < 1) {
1579                    TrackOutside(oOutsideTs, oSpan->fT, testT);
1580                }
1581                if (!oIndex) {
1582                    break;
1583                }
1584                oSpan = &other.fTs[--oIndex];
1585            }
1586            test = span;
1587            oTest = oSpan;
1588        } while (!approximately_negative(endT - test->fT));
1589        SkASSERT(!oIndex || approximately_negative(oTest->fT - oStartT));
1590        // FIXME: determine if canceled edges need outside ts added
1591        if (!done() && outsideTs.count()) {
1592            double tStart = outsideTs[0];
1593            double oStart = outsideTs[1];
1594            addCancelOutsides(tStart, oStart, other, oEndT);
1595            int count = outsideTs.count();
1596            if (count > 2) {
1597                double tStart = outsideTs[count - 2];
1598                double oStart = outsideTs[count - 1];
1599                addCancelOutsides(tStart, oStart, other, oEndT);
1600            }
1601        }
1602        if (!other.done() && oOutsideTs.count()) {
1603            double tStart = oOutsideTs[0];
1604            double oStart = oOutsideTs[1];
1605            other.addCancelOutsides(tStart, oStart, *this, endT);
1606        }
1607    }
1608
1609    int bumpCoincidentThis(const Span* oTest, bool opp, int index,
1610            SkTDArray<double>& outsideTs) {
1611        int oWindValue = oTest->fWindValue;
1612        int oOppValue = oTest->fOppValue;
1613        if (opp) {
1614            SkTSwap<int>(oWindValue, oOppValue);
1615        }
1616        Span* const test = &fTs[index];
1617        Span* end = test;
1618        const double oStartT = oTest->fT;
1619        do {
1620            if (bumpSpan(end, oWindValue, oOppValue)) {
1621                TrackOutside(outsideTs, end->fT, oStartT);
1622            }
1623            end = &fTs[++index];
1624        } while (approximately_negative(end->fT - test->fT));
1625        return index;
1626    }
1627
1628    // because of the order in which coincidences are resolved, this and other
1629    // may not have the same intermediate points. Compute the corresponding
1630    // intermediate T values (using this as the master, other as the follower)
1631    // and walk other conditionally -- hoping that it catches up in the end
1632    int bumpCoincidentOther(const Span* test, double oEndT, int& oIndex,
1633            SkTDArray<double>& oOutsideTs) {
1634        Span* const oTest = &fTs[oIndex];
1635        Span* oEnd = oTest;
1636        const double startT = test->fT;
1637        const double oStartT = oTest->fT;
1638        while (!approximately_negative(oEndT - oEnd->fT)
1639                && approximately_negative(oEnd->fT - oStartT)) {
1640            zeroSpan(oEnd);
1641            TrackOutside(oOutsideTs, oEnd->fT, startT);
1642            oEnd = &fTs[++oIndex];
1643        }
1644        return oIndex;
1645    }
1646
1647    // FIXME: need to test this case:
1648    // contourA has two segments that are coincident
1649    // contourB has two segments that are coincident in the same place
1650    // each ends up with +2/0 pairs for winding count
1651    // since logic below doesn't transfer count (only increments/decrements) can this be
1652    // resolved to +4/0 ?
1653
1654    // set spans from start to end to increment the greater by one and decrement
1655    // the lesser
1656    void addTCoincident(double startT, double endT, Segment& other, double oStartT, double oEndT) {
1657        SkASSERT(!approximately_negative(endT - startT));
1658        SkASSERT(!approximately_negative(oEndT - oStartT));
1659        bool opp = fOperand ^ other.fOperand;
1660        int index = 0;
1661        while (!approximately_negative(startT - fTs[index].fT)) {
1662            ++index;
1663        }
1664        int oIndex = 0;
1665        while (!approximately_negative(oStartT - other.fTs[oIndex].fT)) {
1666            ++oIndex;
1667        }
1668        Span* test = &fTs[index];
1669        Span* oTest = &other.fTs[oIndex];
1670        SkTDArray<double> outsideTs;
1671        SkTDArray<double> oOutsideTs;
1672        do {
1673            // if either span has an opposite value and the operands don't match, resolve first
1674     //       SkASSERT(!test->fDone || !oTest->fDone);
1675            if (test->fDone || oTest->fDone) {
1676                index = advanceCoincidentThis(oTest, opp, index);
1677                oIndex = other.advanceCoincidentOther(test, oEndT, oIndex);
1678            } else {
1679                index = bumpCoincidentThis(oTest, opp, index, outsideTs);
1680                oIndex = other.bumpCoincidentOther(test, oEndT, oIndex, oOutsideTs);
1681            }
1682            test = &fTs[index];
1683            oTest = &other.fTs[oIndex];
1684        } while (!approximately_negative(endT - test->fT));
1685        SkASSERT(approximately_negative(oTest->fT - oEndT));
1686        SkASSERT(approximately_negative(oEndT - oTest->fT));
1687        if (!done() && outsideTs.count()) {
1688            addCoinOutsides(outsideTs, other, oEndT);
1689        }
1690        if (!other.done() && oOutsideTs.count()) {
1691            other.addCoinOutsides(oOutsideTs, *this, endT);
1692        }
1693    }
1694
1695    // FIXME: this doesn't prevent the same span from being added twice
1696    // fix in caller, assert here?
1697    void addTPair(double t, Segment& other, double otherT, bool borrowWind) {
1698        int tCount = fTs.count();
1699        for (int tIndex = 0; tIndex < tCount; ++tIndex) {
1700            const Span& span = fTs[tIndex];
1701            if (!approximately_negative(span.fT - t)) {
1702                break;
1703            }
1704            if (approximately_negative(span.fT - t) && span.fOther == &other
1705                    && approximately_equal(span.fOtherT, otherT)) {
1706#if DEBUG_ADD_T_PAIR
1707                SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
1708                        __FUNCTION__, fID, t, other.fID, otherT);
1709#endif
1710                return;
1711            }
1712        }
1713#if DEBUG_ADD_T_PAIR
1714        SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
1715                __FUNCTION__, fID, t, other.fID, otherT);
1716#endif
1717        int insertedAt = addT(t, &other);
1718        int otherInsertedAt = other.addT(otherT, this);
1719        addOtherT(insertedAt, otherT, otherInsertedAt);
1720        other.addOtherT(otherInsertedAt, t, insertedAt);
1721        matchWindingValue(insertedAt, t, borrowWind);
1722        other.matchWindingValue(otherInsertedAt, otherT, borrowWind);
1723    }
1724
1725    void addTwoAngles(int start, int end, SkTDArray<Angle>& angles) const {
1726        // add edge leading into junction
1727        int min = SkMin32(end, start);
1728        if (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0) {
1729            addAngle(angles, end, start);
1730        }
1731        // add edge leading away from junction
1732        int step = SkSign32(end - start);
1733        int tIndex = nextExactSpan(end, step);
1734        min = SkMin32(end, tIndex);
1735        if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0)) {
1736            addAngle(angles, end, tIndex);
1737        }
1738    }
1739
1740    int advanceCoincidentThis(const Span* oTest, bool opp, int index) {
1741        Span* const test = &fTs[index];
1742        Span* end = test;
1743        do {
1744            end = &fTs[++index];
1745        } while (approximately_negative(end->fT - test->fT));
1746        return index;
1747    }
1748
1749    int advanceCoincidentOther(const Span* test, double oEndT, int& oIndex) {
1750        Span* const oTest = &fTs[oIndex];
1751        Span* oEnd = oTest;
1752        const double oStartT = oTest->fT;
1753        while (!approximately_negative(oEndT - oEnd->fT)
1754                && approximately_negative(oEnd->fT - oStartT)) {
1755            oEnd = &fTs[++oIndex];
1756        }
1757        return oIndex;
1758    }
1759
1760    const Bounds& bounds() const {
1761        return fBounds;
1762    }
1763
1764    void buildAngles(int index, SkTDArray<Angle>& angles, bool includeOpp) const {
1765        double referenceT = fTs[index].fT;
1766        int lesser = index;
1767        while (--lesser >= 0 && (includeOpp || fTs[lesser].fOther->fOperand == fOperand)
1768                && precisely_negative(referenceT - fTs[lesser].fT)) {
1769            buildAnglesInner(lesser, angles);
1770        }
1771        do {
1772            buildAnglesInner(index, angles);
1773        } while (++index < fTs.count() && (includeOpp || fTs[index].fOther->fOperand == fOperand)
1774                && precisely_negative(fTs[index].fT - referenceT));
1775    }
1776
1777    void buildAnglesInner(int index, SkTDArray<Angle>& angles) const {
1778        Span* span = &fTs[index];
1779        Segment* other = span->fOther;
1780    // if there is only one live crossing, and no coincidence, continue
1781    // in the same direction
1782    // if there is coincidence, the only choice may be to reverse direction
1783        // find edge on either side of intersection
1784        int oIndex = span->fOtherIndex;
1785        // if done == -1, prior span has already been processed
1786        int step = 1;
1787        int next = other->nextExactSpan(oIndex, step);
1788       if (next < 0) {
1789            step = -step;
1790            next = other->nextExactSpan(oIndex, step);
1791        }
1792        // add candidate into and away from junction
1793        other->addTwoAngles(next, oIndex, angles);
1794    }
1795
1796    int computeSum(int startIndex, int endIndex, bool binary) {
1797        SkTDArray<Angle> angles;
1798        addTwoAngles(startIndex, endIndex, angles);
1799        buildAngles(endIndex, angles, false);
1800        // OPTIMIZATION: check all angles to see if any have computed wind sum
1801        // before sorting (early exit if none)
1802        SkTDArray<Angle*> sorted;
1803        bool sortable = SortAngles(angles, sorted);
1804#if DEBUG_SORT
1805        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
1806#endif
1807        if (!sortable) {
1808            return SK_MinS32;
1809        }
1810        int angleCount = angles.count();
1811        const Angle* angle;
1812        const Segment* base;
1813        int winding;
1814        int oWinding;
1815        int firstIndex = 0;
1816        do {
1817            angle = sorted[firstIndex];
1818            base = angle->segment();
1819            winding = base->windSum(angle);
1820            if (winding != SK_MinS32) {
1821                oWinding = base->oppSum(angle);
1822                break;
1823            }
1824            if (++firstIndex == angleCount) {
1825                return SK_MinS32;
1826            }
1827        } while (true);
1828        // turn winding into contourWinding
1829        int spanWinding = base->spanSign(angle);
1830        bool inner = useInnerWinding(winding + spanWinding, winding);
1831    #if DEBUG_WINDING
1832        SkDebugf("%s spanWinding=%d winding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
1833            spanWinding, winding, angle->sign(), inner,
1834            inner ? winding + spanWinding : winding);
1835    #endif
1836        if (inner) {
1837            winding += spanWinding;
1838        }
1839    #if DEBUG_SORT
1840        base->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, oWinding);
1841    #endif
1842        int nextIndex = firstIndex + 1;
1843        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
1844        winding -= base->spanSign(angle);
1845        oWinding -= base->oppSign(angle);
1846        do {
1847            if (nextIndex == angleCount) {
1848                nextIndex = 0;
1849            }
1850            angle = sorted[nextIndex];
1851            Segment* segment = angle->segment();
1852            bool opp = base->fOperand ^ segment->fOperand;
1853            int maxWinding, oMaxWinding;
1854            int spanSign = segment->spanSign(angle);
1855            int oppoSign = segment->oppSign(angle);
1856            if (opp) {
1857                oMaxWinding = oWinding;
1858                oWinding -= spanSign;
1859                maxWinding = winding;
1860                if (oppoSign) {
1861                    winding -= oppoSign;
1862                }
1863            } else {
1864                maxWinding = winding;
1865                winding -= spanSign;
1866                oMaxWinding = oWinding;
1867                if (oppoSign) {
1868                    oWinding -= oppoSign;
1869                }
1870            }
1871            if (segment->windSum(angle) == SK_MinS32) {
1872                if (opp) {
1873                    if (useInnerWinding(oMaxWinding, oWinding)) {
1874                        oMaxWinding = oWinding;
1875                    }
1876                    if (oppoSign && useInnerWinding(maxWinding, winding)) {
1877                        maxWinding = winding;
1878                    }
1879                    (void) segment->markAndChaseWinding(angle, oMaxWinding, maxWinding);
1880                } else {
1881                    if (useInnerWinding(maxWinding, winding)) {
1882                        maxWinding = winding;
1883                    }
1884                    if (oppoSign && useInnerWinding(oMaxWinding, oWinding)) {
1885                        oMaxWinding = oWinding;
1886                    }
1887                    (void) segment->markAndChaseWinding(angle, maxWinding,
1888                            binary ? oMaxWinding : 0);
1889                }
1890            }
1891        } while (++nextIndex != lastIndex);
1892        int minIndex = SkMin32(startIndex, endIndex);
1893        return windSum(minIndex);
1894    }
1895
1896    int crossedSpanX(const SkPoint& basePt, SkScalar& bestX, double& hitT, bool opp) const {
1897        int bestT = -1;
1898        SkScalar left = bounds().fLeft;
1899        SkScalar right = bounds().fRight;
1900        int end = 0;
1901        do {
1902            int start = end;
1903            end = nextSpan(start, 1);
1904            if ((opp ? fTs[start].fOppValue : fTs[start].fWindValue) == 0) {
1905                continue;
1906            }
1907            SkPoint edge[4];
1908            double startT = fTs[start].fT;
1909            double endT = fTs[end].fT;
1910            (*SegmentSubDivide[fVerb])(fPts, startT, endT, edge);
1911            // intersect ray starting at basePt with edge
1912            Intersections intersections;
1913            // FIXME: always use original and limit results to T values within
1914            // start t and end t.
1915            // OPTIMIZE: use specialty function that intersects ray with curve,
1916            // returning t values only for curve (we don't care about t on ray)
1917            int pts = (*HSegmentIntersect[fVerb])(edge, left, right, basePt.fY,
1918                    false, intersections);
1919            if (pts == 0) {
1920                continue;
1921            }
1922            if (pts > 1 && fVerb == SkPath::kLine_Verb) {
1923            // if the intersection is edge on, wait for another one
1924                continue;
1925            }
1926            for (int index = 0; index < pts; ++index) {
1927                double foundT = intersections.fT[0][index];
1928                double testT = startT + (endT - startT) * foundT;
1929                SkScalar testX = (*SegmentXAtT[fVerb])(fPts, testT);
1930                if (bestX < testX && testX < basePt.fX) {
1931                    if (fVerb > SkPath::kLine_Verb
1932                            && !approximately_less_than_zero(foundT)
1933                            && !approximately_greater_than_one(foundT)) {
1934                        SkScalar dy = (*SegmentDYAtT[fVerb])(fPts, testT);
1935                        if (approximately_zero(dy)) {
1936                            continue;
1937                        }
1938                    }
1939                    bestX = testX;
1940                    bestT = foundT < 1 ? start : end;
1941                    hitT = testT;
1942                }
1943            }
1944        } while (fTs[end].fT != 1);
1945        return bestT;
1946    }
1947
1948    int crossedSpanY(const SkPoint& basePt, SkScalar& bestY, double& hitT, bool opp) const {
1949        int bestT = -1;
1950        SkScalar top = bounds().fTop;
1951        SkScalar bottom = bounds().fBottom;
1952        int end = 0;
1953        do {
1954            int start = end;
1955            end = nextSpan(start, 1);
1956            if ((opp ? fTs[start].fOppValue : fTs[start].fWindValue) == 0) {
1957                continue;
1958            }
1959            SkPoint edge[4];
1960            double startT = fTs[start].fT;
1961            double endT = fTs[end].fT;
1962            (*SegmentSubDivide[fVerb])(fPts, startT, endT, edge);
1963            // intersect ray starting at basePt with edge
1964            Intersections intersections;
1965            // FIXME: always use original and limit results to T values within
1966            // start t and end t.
1967            // OPTIMIZE: use specialty function that intersects ray with curve,
1968            // returning t values only for curve (we don't care about t on ray)
1969            int pts = (*VSegmentIntersect[fVerb])(edge, top, bottom, basePt.fX,
1970                    false, intersections);
1971            if (pts == 0) {
1972                continue;
1973            }
1974            if (pts > 1 && fVerb == SkPath::kLine_Verb) {
1975            // if the intersection is edge on, wait for another one
1976                continue;
1977            }
1978            for (int index = 0; index < pts; ++index) {
1979                double foundT = intersections.fT[0][index];
1980                double testT = startT + (endT - startT) * foundT;
1981                SkScalar testY = (*SegmentYAtT[fVerb])(fPts, testT);
1982                if (bestY < testY && testY < basePt.fY) {
1983                    if (fVerb > SkPath::kLine_Verb
1984                            && !approximately_less_than_zero(foundT)
1985                            && !approximately_greater_than_one(foundT)) {
1986                        SkScalar dx = (*SegmentDXAtT[fVerb])(fPts, testT);
1987                        if (approximately_zero(dx)) {
1988                            continue;
1989                        }
1990                    }
1991                    bestY = testY;
1992                    bestT = foundT < 1 ? start : end;
1993                    hitT = testT;
1994                }
1995            }
1996        } while (fTs[end].fT != 1);
1997        return bestT;
1998    }
1999
2000    void decrementSpan(Span* span) {
2001        SkASSERT(span->fWindValue > 0);
2002        if (--(span->fWindValue) == 0) {
2003            if (!span->fOppValue && !span->fDone) {
2004                span->fDone = true;
2005                ++fDoneSpans;
2006            }
2007        }
2008    }
2009
2010    bool bumpSpan(Span* span, int windDelta, int oppDelta) {
2011        SkASSERT(!span->fDone);
2012        span->fWindValue += windDelta;
2013        SkASSERT(span->fWindValue >= 0);
2014        span->fOppValue += oppDelta;
2015        SkASSERT(span->fOppValue >= 0);
2016        if (fXor) {
2017            span->fWindValue &= 1;
2018        }
2019        if (fOppXor) {
2020            span->fOppValue &= 1;
2021        }
2022        if (!span->fWindValue && !span->fOppValue) {
2023            span->fDone = true;
2024            ++fDoneSpans;
2025            return true;
2026        }
2027        return false;
2028    }
2029
2030    // OPTIMIZE
2031    // when the edges are initially walked, they don't automatically get the prior and next
2032    // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
2033    // and would additionally remove the need for similar checks in condition edges. It would
2034    // also allow intersection code to assume end of segment intersections (maybe?)
2035    bool complete() const {
2036        int count = fTs.count();
2037        return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
2038    }
2039
2040    bool done() const {
2041        SkASSERT(fDoneSpans <= fTs.count());
2042        return fDoneSpans == fTs.count();
2043    }
2044
2045    bool done(int min) const {
2046        return fTs[min].fDone;
2047    }
2048
2049    bool done(const Angle* angle) const {
2050        return done(SkMin32(angle->start(), angle->end()));
2051    }
2052
2053    /*
2054     The M and S variable name parts stand for the operators.
2055       Mi stands for Minuend (see wiki subtraction, analogous to difference)
2056       Su stands for Subtrahend
2057     The Opp variable name part designates that the value is for the Opposite operator.
2058     Opposite values result from combining coincident spans.
2059     */
2060
2061    Segment* findNextOp(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd,
2062            bool& unsortable, ShapeOp op, const int xorMiMask, const int xorSuMask) {
2063        const int startIndex = nextStart;
2064        const int endIndex = nextEnd;
2065        SkASSERT(startIndex != endIndex);
2066        const int count = fTs.count();
2067        SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
2068        const int step = SkSign32(endIndex - startIndex);
2069        const int end = nextExactSpan(startIndex, step);
2070        SkASSERT(end >= 0);
2071        Span* endSpan = &fTs[end];
2072        Segment* other;
2073        if (isSimple(end)) {
2074        // mark the smaller of startIndex, endIndex done, and all adjacent
2075        // spans with the same T value (but not 'other' spans)
2076    #if DEBUG_WINDING
2077            SkDebugf("%s simple\n", __FUNCTION__);
2078    #endif
2079            int min = SkMin32(startIndex, endIndex);
2080            if (fTs[min].fDone) {
2081                return NULL;
2082            }
2083            markDoneBinary(min);
2084            other = endSpan->fOther;
2085            nextStart = endSpan->fOtherIndex;
2086            double startT = other->fTs[nextStart].fT;
2087            nextEnd = nextStart;
2088            do {
2089                nextEnd += step;
2090            }
2091            while (precisely_zero(startT - other->fTs[nextEnd].fT));
2092            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
2093            return other;
2094        }
2095        // more than one viable candidate -- measure angles to find best
2096        SkTDArray<Angle> angles;
2097        SkASSERT(startIndex - endIndex != 0);
2098        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2099        addTwoAngles(startIndex, end, angles);
2100        buildAngles(end, angles, true);
2101        SkTDArray<Angle*> sorted;
2102        bool sortable = SortAngles(angles, sorted);
2103        int angleCount = angles.count();
2104        int firstIndex = findStartingEdge(sorted, startIndex, end);
2105        SkASSERT(firstIndex >= 0);
2106    #if DEBUG_SORT
2107        debugShowSort(__FUNCTION__, sorted, firstIndex);
2108    #endif
2109        if (!sortable) {
2110            unsortable = true;
2111            return NULL;
2112        }
2113        SkASSERT(sorted[firstIndex]->segment() == this);
2114    #if DEBUG_WINDING
2115        SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
2116                sorted[firstIndex]->sign());
2117    #endif
2118        int sumMiWinding = updateWinding(endIndex, startIndex);
2119        int sumSuWinding = updateOppWinding(endIndex, startIndex);
2120        if (operand()) {
2121            SkTSwap<int>(sumMiWinding, sumSuWinding);
2122        }
2123        int nextIndex = firstIndex + 1;
2124        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
2125        const Angle* foundAngle = NULL;
2126        bool foundDone = false;
2127        // iterate through the angle, and compute everyone's winding
2128        Segment* nextSegment;
2129        do {
2130            SkASSERT(nextIndex != firstIndex);
2131            if (nextIndex == angleCount) {
2132                nextIndex = 0;
2133            }
2134            const Angle* nextAngle = sorted[nextIndex];
2135            nextSegment = nextAngle->segment();
2136            int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
2137            bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
2138                    nextAngle->end(), op, sumMiWinding, sumSuWinding,
2139                    maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
2140            if (activeAngle && (!foundAngle || foundDone)) {
2141                foundAngle = nextAngle;
2142                foundDone = nextSegment->done(nextAngle) && !nextSegment->tiny(nextAngle);
2143            }
2144            if (nextSegment->done()) {
2145                continue;
2146            }
2147            if (nextSegment->windSum(nextAngle) != SK_MinS32) {
2148                continue;
2149            }
2150            Span* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding,
2151                    oppSumWinding, activeAngle, nextAngle);
2152            if (last) {
2153                *chase.append() = last;
2154#if DEBUG_WINDING
2155                SkDebugf("%s chase.append id=%d\n", __FUNCTION__,
2156                        last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2157#endif
2158            }
2159        } while (++nextIndex != lastIndex);
2160        markDoneBinary(SkMin32(startIndex, endIndex));
2161        if (!foundAngle) {
2162            return NULL;
2163        }
2164        nextStart = foundAngle->start();
2165        nextEnd = foundAngle->end();
2166        nextSegment = foundAngle->segment();
2167
2168    #if DEBUG_WINDING
2169        SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
2170                __FUNCTION__, debugID(), nextSegment->debugID(), nextStart, nextEnd);
2171     #endif
2172        return nextSegment;
2173    }
2174
2175    // so the span needs to contain the pairing info found here
2176    // this should include the winding computed for the edge, and
2177    //  what edge it connects to, and whether it is discarded
2178    //  (maybe discarded == abs(winding) > 1) ?
2179    // only need derivatives for duration of sorting, add a new struct
2180    // for pairings, remove extra spans that have zero length and
2181    //  reference an unused other
2182    // for coincident, the last span on the other may be marked done
2183    //  (always?)
2184
2185    // if loop is exhausted, contour may be closed.
2186    // FIXME: pass in close point so we can check for closure
2187
2188    // given a segment, and a sense of where 'inside' is, return the next
2189    // segment. If this segment has an intersection, or ends in multiple
2190    // segments, find the mate that continues the outside.
2191    // note that if there are multiples, but no coincidence, we can limit
2192    // choices to connections in the correct direction
2193
2194    // mark found segments as done
2195
2196    // start is the index of the beginning T of this edge
2197    // it is guaranteed to have an end which describes a non-zero length (?)
2198    // winding -1 means ccw, 1 means cw
2199    Segment* findNextWinding(SkTDArray<Span*>& chase, bool active,
2200            int& nextStart, int& nextEnd, int& winding, int& spanWinding,
2201            bool& unsortable) {
2202        const int startIndex = nextStart;
2203        const int endIndex = nextEnd;
2204        int outerWinding = winding;
2205        int innerWinding = winding + spanWinding;
2206    #if DEBUG_WINDING
2207        SkDebugf("%s winding=%d spanWinding=%d outerWinding=%d innerWinding=%d\n",
2208                __FUNCTION__, winding, spanWinding, outerWinding, innerWinding);
2209    #endif
2210        if (useInnerWinding(outerWinding, innerWinding)) {
2211            outerWinding = innerWinding;
2212        }
2213        SkASSERT(startIndex != endIndex);
2214        int count = fTs.count();
2215        SkASSERT(startIndex < endIndex ? startIndex < count - 1
2216                : startIndex > 0);
2217        int step = SkSign32(endIndex - startIndex);
2218        int end = nextExactSpan(startIndex, step);
2219        SkASSERT(end >= 0);
2220        Span* endSpan = &fTs[end];
2221        Segment* other;
2222        if (isSimple(end)) {
2223        // mark the smaller of startIndex, endIndex done, and all adjacent
2224        // spans with the same T value (but not 'other' spans)
2225    #if DEBUG_WINDING
2226            SkDebugf("%s simple\n", __FUNCTION__);
2227    #endif
2228            int min = SkMin32(startIndex, endIndex);
2229            if (fTs[min].fDone) {
2230                return NULL;
2231            }
2232            markDone(min, outerWinding);
2233            other = endSpan->fOther;
2234            nextStart = endSpan->fOtherIndex;
2235            double startT = other->fTs[nextStart].fT;
2236            nextEnd = nextStart;
2237            do {
2238                nextEnd += step;
2239            }
2240             while (precisely_zero(startT - other->fTs[nextEnd].fT));
2241            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
2242            return other;
2243        }
2244        // more than one viable candidate -- measure angles to find best
2245        SkTDArray<Angle> angles;
2246        SkASSERT(startIndex - endIndex != 0);
2247        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2248        addTwoAngles(startIndex, end, angles);
2249        buildAngles(end, angles, false);
2250        SkTDArray<Angle*> sorted;
2251        bool sortable = SortAngles(angles, sorted);
2252        int angleCount = angles.count();
2253        int firstIndex = findStartingEdge(sorted, startIndex, end);
2254        SkASSERT(firstIndex >= 0);
2255    #if DEBUG_SORT
2256        debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0);
2257    #endif
2258        if (!sortable) {
2259            unsortable = true;
2260            return NULL;
2261        }
2262        SkASSERT(sorted[firstIndex]->segment() == this);
2263    #if DEBUG_WINDING
2264        SkDebugf("%s [%d] sign=%d\n", __FUNCTION__, firstIndex, sorted[firstIndex]->sign());
2265    #endif
2266        int sumWinding = winding - spanSign(sorted[firstIndex]);
2267        int nextIndex = firstIndex + 1;
2268        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
2269        const Angle* foundAngle = NULL;
2270        // FIXME: found done logic probably fails if there are more than 4
2271        // sorted angles. It should bias towards the first and last undone
2272        // edges -- but not sure that it won't choose a middle (incorrect)
2273        // edge if one is undone
2274        bool foundDone = false;
2275        bool foundDone2 = false;
2276        // iterate through the angle, and compute everyone's winding
2277        bool altFlipped = false;
2278        bool foundFlipped = false;
2279        int foundSum = SK_MinS32;
2280        Segment* nextSegment;
2281        int lastNonZeroSum = winding;
2282        do {
2283            if (nextIndex == angleCount) {
2284                nextIndex = 0;
2285            }
2286            const Angle* nextAngle = sorted[nextIndex];
2287            int maxWinding = sumWinding;
2288            if (sumWinding) {
2289                lastNonZeroSum = sumWinding;
2290            }
2291            nextSegment = nextAngle->segment();
2292            bool nextDone = nextSegment->done(nextAngle);
2293            bool nextTiny = nextSegment->tiny(nextAngle);
2294            sumWinding -= nextSegment->spanSign(nextAngle);
2295            altFlipped ^= lastNonZeroSum * sumWinding < 0; // flip if different signs
2296    #if 0 && DEBUG_WINDING
2297            SkASSERT(abs(sumWinding) <= gDebugMaxWindSum);
2298            SkDebugf("%s [%d] maxWinding=%d sumWinding=%d sign=%d altFlipped=%d\n", __FUNCTION__,
2299                    nextIndex, maxWinding, sumWinding, nextAngle->sign(), altFlipped);
2300    #endif
2301           if (!sumWinding) {
2302                if (!active) {
2303                    // FIXME: shouldn't this call mark and chase done ?
2304                    markDone(SkMin32(startIndex, endIndex), outerWinding);
2305                    // FIXME: shouldn't this call mark and chase winding ?
2306                    nextSegment->markWinding(SkMin32(nextAngle->start(),
2307                                nextAngle->end()), maxWinding);
2308    #if DEBUG_WINDING
2309                    SkDebugf("%s [%d] inactive\n", __FUNCTION__, nextIndex);
2310    #endif
2311                    return NULL;
2312                }
2313                if (!foundAngle || foundDone) {
2314                    foundAngle = nextAngle;
2315                    foundDone = nextDone && !nextTiny;
2316                    foundFlipped = altFlipped;
2317                }
2318                continue;
2319            }
2320
2321            if (!maxWinding && (!foundAngle || foundDone2)) {
2322        #if DEBUG_WINDING
2323                if (foundAngle && foundDone2) {
2324                    SkDebugf("%s [%d] !foundAngle && foundDone2\n", __FUNCTION__, nextIndex);
2325                }
2326        #endif
2327                foundAngle = nextAngle;
2328                foundDone2 = nextDone && !nextTiny;
2329                foundFlipped = altFlipped;
2330                foundSum = sumWinding;
2331            }
2332            if (nextSegment->done()) {
2333                continue;
2334            }
2335            // if the winding is non-zero, nextAngle does not connect to
2336            // current chain. If we haven't done so already, mark the angle
2337            // as done, record the winding value, and mark connected unambiguous
2338            // segments as well.
2339            if (nextSegment->windSum(nextAngle) == SK_MinS32) {
2340                if (useInnerWinding(maxWinding, sumWinding)) {
2341                    maxWinding = sumWinding;
2342                }
2343                Span* last;
2344                if (foundAngle) {
2345                    last = nextSegment->markAndChaseWinding(nextAngle, maxWinding);
2346                } else {
2347                    last = nextSegment->markAndChaseDone(nextAngle, maxWinding);
2348                }
2349                if (last) {
2350                    *chase.append() = last;
2351    #if DEBUG_WINDING
2352                    SkDebugf("%s chase.append id=%d\n", __FUNCTION__,
2353                            last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2354    #endif
2355                }
2356            }
2357        } while (++nextIndex != lastIndex);
2358        markDone(SkMin32(startIndex, endIndex), outerWinding);
2359        if (!foundAngle) {
2360            return NULL;
2361        }
2362        nextStart = foundAngle->start();
2363        nextEnd = foundAngle->end();
2364        nextSegment = foundAngle->segment();
2365        int flipped = foundFlipped ? -1 : 1;
2366        spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue(
2367                SkMin32(nextStart, nextEnd));
2368        if (winding) {
2369    #if DEBUG_WINDING
2370            SkDebugf("%s ---6 winding=%d foundSum=", __FUNCTION__, winding);
2371            if (foundSum == SK_MinS32) {
2372                SkDebugf("?");
2373            } else {
2374                SkDebugf("%d", foundSum);
2375            }
2376            SkDebugf("\n");
2377     #endif
2378            winding = foundSum;
2379        }
2380    #if DEBUG_WINDING
2381        SkDebugf("%s spanWinding=%d flipped=%d\n", __FUNCTION__, spanWinding, flipped);
2382    #endif
2383        return nextSegment;
2384    }
2385
2386    Segment* findNextWinding(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd,
2387            bool& unsortable) {
2388        const int startIndex = nextStart;
2389        const int endIndex = nextEnd;
2390        SkASSERT(startIndex != endIndex);
2391        const int count = fTs.count();
2392        SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
2393        const int step = SkSign32(endIndex - startIndex);
2394        const int end = nextExactSpan(startIndex, step);
2395        SkASSERT(end >= 0);
2396        Span* endSpan = &fTs[end];
2397        Segment* other;
2398        if (isSimple(end)) {
2399        // mark the smaller of startIndex, endIndex done, and all adjacent
2400        // spans with the same T value (but not 'other' spans)
2401    #if DEBUG_WINDING
2402            SkDebugf("%s simple\n", __FUNCTION__);
2403    #endif
2404            int min = SkMin32(startIndex, endIndex);
2405            if (fTs[min].fDone) {
2406                return NULL;
2407            }
2408            markDoneUnary(min);
2409            other = endSpan->fOther;
2410            nextStart = endSpan->fOtherIndex;
2411            double startT = other->fTs[nextStart].fT;
2412            nextEnd = nextStart;
2413            do {
2414                nextEnd += step;
2415            }
2416            while (precisely_zero(startT - other->fTs[nextEnd].fT));
2417            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
2418            return other;
2419        }
2420        // more than one viable candidate -- measure angles to find best
2421        SkTDArray<Angle> angles;
2422        SkASSERT(startIndex - endIndex != 0);
2423        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2424        addTwoAngles(startIndex, end, angles);
2425        buildAngles(end, angles, true);
2426        SkTDArray<Angle*> sorted;
2427        bool sortable = SortAngles(angles, sorted);
2428        int angleCount = angles.count();
2429        int firstIndex = findStartingEdge(sorted, startIndex, end);
2430        SkASSERT(firstIndex >= 0);
2431    #if DEBUG_SORT
2432        debugShowSort(__FUNCTION__, sorted, firstIndex);
2433    #endif
2434        if (!sortable) {
2435            unsortable = true;
2436            return NULL;
2437        }
2438        SkASSERT(sorted[firstIndex]->segment() == this);
2439    #if DEBUG_WINDING
2440        SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
2441                sorted[firstIndex]->sign());
2442    #endif
2443        int sumWinding = updateWinding(endIndex, startIndex);
2444        int outside = sumWinding & 1; // associate pairs together to avoid figure eights
2445        int nextIndex = firstIndex + 1;
2446        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
2447        const Angle* foundAngle = NULL;
2448        bool foundDone = false;
2449        // iterate through the angle, and compute everyone's winding
2450        Segment* nextSegment;
2451        do {
2452            SkASSERT(nextIndex != firstIndex);
2453            if (nextIndex == angleCount) {
2454                nextIndex = 0;
2455            }
2456            const Angle* nextAngle = sorted[nextIndex];
2457            nextSegment = nextAngle->segment();
2458            int maxWinding;
2459            bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
2460                    maxWinding, sumWinding);
2461            if (activeAngle && (!foundAngle || foundDone) && outside != (sumWinding & 1)) {
2462                foundAngle = nextAngle;
2463                foundDone = nextSegment->done(nextAngle) && !nextSegment->tiny(nextAngle);
2464            }
2465            if (nextSegment->done()) {
2466                continue;
2467            }
2468            if (nextSegment->windSum(nextAngle) != SK_MinS32) {
2469                continue;
2470            }
2471            Span* last = nextSegment->markAngle(maxWinding, sumWinding, activeAngle, nextAngle);
2472            if (last) {
2473                *chase.append() = last;
2474#if DEBUG_WINDING
2475                SkDebugf("%s chase.append id=%d\n", __FUNCTION__,
2476                        last->fOther->fTs[last->fOtherIndex].fOther->debugID());
2477#endif
2478            }
2479        } while (++nextIndex != lastIndex);
2480        markDoneUnary(SkMin32(startIndex, endIndex));
2481        if (!foundAngle) {
2482            return NULL;
2483        }
2484        nextStart = foundAngle->start();
2485        nextEnd = foundAngle->end();
2486        nextSegment = foundAngle->segment();
2487
2488    #if DEBUG_WINDING
2489        SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
2490                __FUNCTION__, debugID(), nextSegment->debugID(), nextStart, nextEnd);
2491     #endif
2492        return nextSegment;
2493    }
2494
2495    Segment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable) {
2496        const int startIndex = nextStart;
2497        const int endIndex = nextEnd;
2498        SkASSERT(startIndex != endIndex);
2499        int count = fTs.count();
2500        SkASSERT(startIndex < endIndex ? startIndex < count - 1
2501                : startIndex > 0);
2502        int step = SkSign32(endIndex - startIndex);
2503        int end = nextExactSpan(startIndex, step);
2504        SkASSERT(end >= 0);
2505        Span* endSpan = &fTs[end];
2506        Segment* other;
2507        if (isSimple(end)) {
2508    #if DEBUG_WINDING
2509            SkDebugf("%s simple\n", __FUNCTION__);
2510    #endif
2511            int min = SkMin32(startIndex, endIndex);
2512            if (fTs[min].fDone) {
2513                return NULL;
2514            }
2515            markDone(min, 1);
2516            other = endSpan->fOther;
2517            nextStart = endSpan->fOtherIndex;
2518            double startT = other->fTs[nextStart].fT;
2519            SkDEBUGCODE(bool firstLoop = true;)
2520            if ((approximately_less_than_zero(startT) && step < 0)
2521                    || (approximately_greater_than_one(startT) && step > 0)) {
2522                step = -step;
2523                SkDEBUGCODE(firstLoop = false;)
2524            }
2525            do {
2526                nextEnd = nextStart;
2527                do {
2528                    nextEnd += step;
2529                }
2530                 while (precisely_zero(startT - other->fTs[nextEnd].fT));
2531                if (other->fTs[SkMin32(nextStart, nextEnd)].fWindValue) {
2532                    break;
2533                }
2534 #ifdef SK_DEBUG
2535                SkASSERT(firstLoop);
2536 #endif
2537                SkDEBUGCODE(firstLoop = false;)
2538                step = -step;
2539            } while (true);
2540            SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
2541            return other;
2542        }
2543        SkTDArray<Angle> angles;
2544        SkASSERT(startIndex - endIndex != 0);
2545        SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
2546        addTwoAngles(startIndex, end, angles);
2547        buildAngles(end, angles, false);
2548        SkTDArray<Angle*> sorted;
2549        bool sortable = SortAngles(angles, sorted);
2550        if (!sortable) {
2551            unsortable = true;
2552            return NULL;
2553        }
2554        int angleCount = angles.count();
2555        int firstIndex = findStartingEdge(sorted, startIndex, end);
2556        SkASSERT(firstIndex >= 0);
2557    #if DEBUG_SORT
2558        debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0);
2559    #endif
2560        SkASSERT(sorted[firstIndex]->segment() == this);
2561        int nextIndex = firstIndex + 1;
2562        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
2563        const Angle* nextAngle;
2564        Segment* nextSegment;
2565        bool foundAngle = false;
2566        do {
2567            if (nextIndex == angleCount) {
2568                nextIndex = 0;
2569            }
2570            nextAngle = sorted[nextIndex];
2571            nextSegment = nextAngle->segment();
2572            if (!nextSegment->done(nextAngle) || nextSegment->tiny(nextAngle)) {
2573                foundAngle = true;
2574                break;
2575            }
2576        } while (++nextIndex != lastIndex);
2577        markDone(SkMin32(startIndex, endIndex), 1);
2578        if (!foundAngle) {
2579            nextIndex = firstIndex + 1 == angleCount ? 0 : firstIndex + 1;
2580            nextAngle = sorted[nextIndex];
2581        }
2582        nextStart = nextAngle->start();
2583        nextEnd = nextAngle->end();
2584        return nextSegment;
2585    }
2586
2587    int findStartingEdge(SkTDArray<Angle*>& sorted, int start, int end) {
2588        int angleCount = sorted.count();
2589        int firstIndex = -1;
2590        for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
2591            const Angle* angle = sorted[angleIndex];
2592            if (angle->segment() == this && angle->start() == end &&
2593                    angle->end() == start) {
2594                firstIndex = angleIndex;
2595                break;
2596            }
2597        }
2598        return firstIndex;
2599    }
2600
2601    // FIXME: this is tricky code; needs its own unit test
2602    void findTooCloseToCall() {
2603        int count = fTs.count();
2604        if (count < 3) { // require t=0, x, 1 at minimum
2605            return;
2606        }
2607        int matchIndex = 0;
2608        int moCount;
2609        Span* match;
2610        Segment* mOther;
2611        do {
2612            match = &fTs[matchIndex];
2613            mOther = match->fOther;
2614            // FIXME: allow quads, cubics to be near coincident?
2615            if (mOther->fVerb == SkPath::kLine_Verb) {
2616                moCount = mOther->fTs.count();
2617                if (moCount >= 3) {
2618                    break;
2619                }
2620            }
2621            if (++matchIndex >= count) {
2622                return;
2623            }
2624        } while (true); // require t=0, x, 1 at minimum
2625        // OPTIMIZATION: defer matchPt until qualifying toCount is found?
2626        const SkPoint* matchPt = &xyAtT(match);
2627        // look for a pair of nearby T values that map to the same (x,y) value
2628        // if found, see if the pair of other segments share a common point. If
2629        // so, the span from here to there is coincident.
2630        for (int index = matchIndex + 1; index < count; ++index) {
2631            Span* test = &fTs[index];
2632            if (test->fDone) {
2633                continue;
2634            }
2635            Segment* tOther = test->fOther;
2636            if (tOther->fVerb != SkPath::kLine_Verb) {
2637                continue; // FIXME: allow quads, cubics to be near coincident?
2638            }
2639            int toCount = tOther->fTs.count();
2640            if (toCount < 3) { // require t=0, x, 1 at minimum
2641                continue;
2642            }
2643            const SkPoint* testPt = &xyAtT(test);
2644            if (*matchPt != *testPt) {
2645                matchIndex = index;
2646                moCount = toCount;
2647                match = test;
2648                mOther = tOther;
2649                matchPt = testPt;
2650                continue;
2651            }
2652            int moStart = -1;
2653            int moEnd = -1;
2654            double moStartT, moEndT;
2655            for (int moIndex = 0; moIndex < moCount; ++moIndex) {
2656                Span& moSpan = mOther->fTs[moIndex];
2657                if (moSpan.fDone) {
2658                    continue;
2659                }
2660                if (moSpan.fOther == this) {
2661                    if (moSpan.fOtherT == match->fT) {
2662                        moStart = moIndex;
2663                        moStartT = moSpan.fT;
2664                    }
2665                    continue;
2666                }
2667                if (moSpan.fOther == tOther) {
2668                    if (tOther->fTs[moSpan.fOtherIndex].fWindValue == 0) {
2669                        moStart = -1;
2670                        break;
2671                    }
2672                    SkASSERT(moEnd == -1);
2673                    moEnd = moIndex;
2674                    moEndT = moSpan.fT;
2675                }
2676            }
2677            if (moStart < 0 || moEnd < 0) {
2678                continue;
2679            }
2680            // FIXME: if moStartT, moEndT are initialized to NaN, can skip this test
2681            if (approximately_equal(moStartT, moEndT)) {
2682                continue;
2683            }
2684            int toStart = -1;
2685            int toEnd = -1;
2686            double toStartT, toEndT;
2687            for (int toIndex = 0; toIndex < toCount; ++toIndex) {
2688                Span& toSpan = tOther->fTs[toIndex];
2689                if (toSpan.fDone) {
2690                    continue;
2691                }
2692                if (toSpan.fOther == this) {
2693                    if (toSpan.fOtherT == test->fT) {
2694                        toStart = toIndex;
2695                        toStartT = toSpan.fT;
2696                    }
2697                    continue;
2698                }
2699                if (toSpan.fOther == mOther && toSpan.fOtherT == moEndT) {
2700                    if (mOther->fTs[toSpan.fOtherIndex].fWindValue == 0) {
2701                        moStart = -1;
2702                        break;
2703                    }
2704                    SkASSERT(toEnd == -1);
2705                    toEnd = toIndex;
2706                    toEndT = toSpan.fT;
2707                }
2708            }
2709            // FIXME: if toStartT, toEndT are initialized to NaN, can skip this test
2710            if (toStart <= 0 || toEnd <= 0) {
2711                continue;
2712            }
2713            if (approximately_equal(toStartT, toEndT)) {
2714                continue;
2715            }
2716            // test to see if the segment between there and here is linear
2717            if (!mOther->isLinear(moStart, moEnd)
2718                    || !tOther->isLinear(toStart, toEnd)) {
2719                continue;
2720            }
2721            bool flipped = (moStart - moEnd) * (toStart - toEnd) < 1;
2722            if (flipped) {
2723                mOther->addTCancel(moStartT, moEndT, *tOther, toEndT, toStartT);
2724            } else {
2725                mOther->addTCoincident(moStartT, moEndT, *tOther, toStartT, toEndT);
2726            }
2727        }
2728    }
2729
2730 //   start here;
2731    // either:
2732    // a) mark spans with either end unsortable as done, or
2733    // b) rewrite findTop / findTopSegment / findTopContour to iterate further
2734    //    when encountering an unsortable span
2735
2736    // OPTIMIZATION : for a pair of lines, can we compute points at T (cached)
2737    // and use more concise logic like the old edge walker code?
2738    // FIXME: this needs to deal with coincident edges
2739    Segment* findTop(int& tIndex, int& endIndex, bool& unsortable, bool onlySortable) {
2740        // iterate through T intersections and return topmost
2741        // topmost tangent from y-min to first pt is closer to horizontal
2742        SkASSERT(!done());
2743        int firstT = -1;
2744        SkPoint topPt;
2745        topPt.fY = SK_ScalarMax;
2746        int count = fTs.count();
2747        // see if either end is not done since we want smaller Y of the pair
2748        bool lastDone = true;
2749        bool lastUnsortable = false;
2750        for (int index = 0; index < count; ++index) {
2751            const Span& span = fTs[index];
2752            if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
2753                goto next;
2754            }
2755            if (!span.fDone | !lastDone) {
2756                const SkPoint& intercept = xyAtT(&span);
2757                if (topPt.fY > intercept.fY || (topPt.fY == intercept.fY
2758                        && topPt.fX > intercept.fX)) {
2759                    topPt = intercept;
2760                    firstT = index;
2761                }
2762            }
2763    next:
2764            lastDone = span.fDone;
2765            lastUnsortable = span.fUnsortableEnd;
2766        }
2767        SkASSERT(firstT >= 0);
2768        // sort the edges to find the leftmost
2769        int step = 1;
2770        int end = nextSpan(firstT, step);
2771        if (end == -1) {
2772            step = -1;
2773            end = nextSpan(firstT, step);
2774            SkASSERT(end != -1);
2775        }
2776        // if the topmost T is not on end, or is three-way or more, find left
2777        // look for left-ness from tLeft to firstT (matching y of other)
2778        SkTDArray<Angle> angles;
2779        SkASSERT(firstT - end != 0);
2780        addTwoAngles(end, firstT, angles);
2781        buildAngles(firstT, angles, true);
2782        SkTDArray<Angle*> sorted;
2783        bool sortable = SortAngles(angles, sorted);
2784    #if DEBUG_SORT
2785        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
2786    #endif
2787        if (onlySortable && !sortable) {
2788            unsortable = true;
2789            return NULL;
2790        }
2791        // skip edges that have already been processed
2792        firstT = -1;
2793        Segment* leftSegment;
2794        do {
2795            const Angle* angle = sorted[++firstT];
2796            SkASSERT(!onlySortable || !angle->unsortable());
2797            leftSegment = angle->segment();
2798            tIndex = angle->end();
2799            endIndex = angle->start();
2800        } while (leftSegment->fTs[SkMin32(tIndex, endIndex)].fDone);
2801        SkASSERT(!leftSegment->fTs[SkMin32(tIndex, endIndex)].fTiny);
2802        return leftSegment;
2803    }
2804
2805    // FIXME: not crazy about this
2806    // when the intersections are performed, the other index is into an
2807    // incomplete array. as the array grows, the indices become incorrect
2808    // while the following fixes the indices up again, it isn't smart about
2809    // skipping segments whose indices are already correct
2810    // assuming we leave the code that wrote the index in the first place
2811    void fixOtherTIndex() {
2812        int iCount = fTs.count();
2813        for (int i = 0; i < iCount; ++i) {
2814            Span& iSpan = fTs[i];
2815            double oT = iSpan.fOtherT;
2816            Segment* other = iSpan.fOther;
2817            int oCount = other->fTs.count();
2818            for (int o = 0; o < oCount; ++o) {
2819                Span& oSpan = other->fTs[o];
2820                if (oT == oSpan.fT && this == oSpan.fOther) {
2821                    iSpan.fOtherIndex = o;
2822                    break;
2823                }
2824            }
2825        }
2826    }
2827
2828    void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) {
2829        fDoneSpans = 0;
2830        fOperand = operand;
2831        fXor = evenOdd;
2832        fPts = pts;
2833        fVerb = verb;
2834    }
2835
2836    void initWinding(int start, int end, int winding, int oppWinding) {
2837        int local = spanSign(start, end);
2838        if (local * winding >= 0) {
2839            winding += local;
2840        }
2841        local = oppSign(start, end);
2842        if (local * oppWinding >= 0) {
2843            oppWinding += local;
2844        }
2845        (void) markAndChaseWinding(start, end, winding, oppWinding);
2846    }
2847
2848    bool intersected() const {
2849        return fTs.count() > 0;
2850    }
2851
2852    bool isConnected(int startIndex, int endIndex) const {
2853        return fTs[startIndex].fWindSum != SK_MinS32
2854                || fTs[endIndex].fWindSum != SK_MinS32;
2855    }
2856
2857    bool isHorizontal() const {
2858        return fBounds.fTop == fBounds.fBottom;
2859    }
2860
2861    bool isLinear(int start, int end) const {
2862        if (fVerb == SkPath::kLine_Verb) {
2863            return true;
2864        }
2865        if (fVerb == SkPath::kQuad_Verb) {
2866            SkPoint qPart[3];
2867            QuadSubDivide(fPts, fTs[start].fT, fTs[end].fT, qPart);
2868            return QuadIsLinear(qPart);
2869        } else {
2870            SkASSERT(fVerb == SkPath::kCubic_Verb);
2871            SkPoint cPart[4];
2872            CubicSubDivide(fPts, fTs[start].fT, fTs[end].fT, cPart);
2873            return CubicIsLinear(cPart);
2874        }
2875    }
2876
2877    // OPTIMIZE: successive calls could start were the last leaves off
2878    // or calls could specialize to walk forwards or backwards
2879    bool isMissing(double startT) const {
2880        size_t tCount = fTs.count();
2881        for (size_t index = 0; index < tCount; ++index) {
2882            if (approximately_zero(startT - fTs[index].fT)) {
2883                return false;
2884            }
2885        }
2886        return true;
2887    }
2888
2889    bool isSimple(int end) const {
2890        int count = fTs.count();
2891        if (count == 2) {
2892            return true;
2893        }
2894        double t = fTs[end].fT;
2895        if (approximately_less_than_zero(t)) {
2896            return !approximately_less_than_zero(fTs[1].fT);
2897        }
2898        if (approximately_greater_than_one(t)) {
2899            return !approximately_greater_than_one(fTs[count - 2].fT);
2900        }
2901        return false;
2902    }
2903
2904    bool isVertical() const {
2905        return fBounds.fLeft == fBounds.fRight;
2906    }
2907
2908    SkScalar leftMost(int start, int end) const {
2909        return (*SegmentLeftMost[fVerb])(fPts, fTs[start].fT, fTs[end].fT);
2910    }
2911
2912    // this span is excluded by the winding rule -- chase the ends
2913    // as long as they are unambiguous to mark connections as done
2914    // and give them the same winding value
2915    Span* markAndChaseDone(const Angle* angle, int winding) {
2916        int index = angle->start();
2917        int endIndex = angle->end();
2918        return markAndChaseDone(index, endIndex, winding);
2919    }
2920
2921    Span* markAndChaseDone(int index, int endIndex, int winding) {
2922        int step = SkSign32(endIndex - index);
2923        int min = SkMin32(index, endIndex);
2924        markDone(min, winding);
2925        Span* last;
2926        Segment* other = this;
2927        while ((other = other->nextChase(index, step, min, last))) {
2928            other->markDone(min, winding);
2929        }
2930        return last;
2931    }
2932
2933    Span* markAndChaseDoneBinary(const Angle* angle, int winding, int oppWinding) {
2934        int index = angle->start();
2935        int endIndex = angle->end();
2936        int step = SkSign32(endIndex - index);
2937        int min = SkMin32(index, endIndex);
2938        markDoneBinary(min, winding, oppWinding);
2939        Span* last;
2940        Segment* other = this;
2941        while ((other = other->nextChase(index, step, min, last))) {
2942            other->markDoneBinary(min, winding, oppWinding);
2943        }
2944        return last;
2945    }
2946
2947    Span* markAndChaseDoneBinary(int index, int endIndex) {
2948        int step = SkSign32(endIndex - index);
2949        int min = SkMin32(index, endIndex);
2950        markDoneBinary(min);
2951        Span* last;
2952        Segment* other = this;
2953        while ((other = other->nextChase(index, step, min, last))) {
2954            if (other->done()) {
2955                return NULL;
2956            }
2957            other->markDoneBinary(min);
2958        }
2959        return last;
2960    }
2961
2962    Span* markAndChaseDoneUnary(const Angle* angle, int winding) {
2963        int index = angle->start();
2964        int endIndex = angle->end();
2965        return markAndChaseDone(index, endIndex, winding);
2966    }
2967
2968    Span* markAndChaseWinding(const Angle* angle, const int winding) {
2969        int index = angle->start();
2970        int endIndex = angle->end();
2971        int step = SkSign32(endIndex - index);
2972        int min = SkMin32(index, endIndex);
2973        markWinding(min, winding);
2974        Span* last;
2975        Segment* other = this;
2976        while ((other = other->nextChase(index, step, min, last))) {
2977            if (other->fTs[min].fWindSum != SK_MinS32) {
2978                SkASSERT(other->fTs[min].fWindSum == winding);
2979                return NULL;
2980            }
2981            other->markWinding(min, winding);
2982        }
2983        return last;
2984    }
2985
2986    Span* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) {
2987        int min = SkMin32(index, endIndex);
2988        int step = SkSign32(endIndex - index);
2989        markWinding(min, winding, oppWinding);
2990        Span* last;
2991        Segment* other = this;
2992        while ((other = other->nextChase(index, step, min, last))) {
2993            if (other->fTs[min].fWindSum != SK_MinS32) {
2994                SkASSERT(other->fTs[min].fWindSum == winding);
2995                return NULL;
2996            }
2997            other->markWinding(min, winding, oppWinding);
2998        }
2999        return last;
3000    }
3001
3002    Span* markAndChaseWinding(const Angle* angle, int winding, int oppWinding) {
3003        int start = angle->start();
3004        int end = angle->end();
3005        return markAndChaseWinding(start, end, winding, oppWinding);
3006    }
3007
3008    Span* markAngle(int maxWinding, int sumWinding, bool activeAngle, const Angle* angle) {
3009        SkASSERT(angle->segment() == this);
3010        if (useInnerWinding(maxWinding, sumWinding)) {
3011            maxWinding = sumWinding;
3012        }
3013        Span* last;
3014        if (activeAngle) {
3015            last = markAndChaseWinding(angle, maxWinding);
3016        } else {
3017            last = markAndChaseDoneUnary(angle, maxWinding);
3018        }
3019        return last;
3020    }
3021
3022    Span* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
3023            bool activeAngle, const Angle* angle) {
3024        SkASSERT(angle->segment() == this);
3025        if (useInnerWinding(maxWinding, sumWinding)) {
3026            maxWinding = sumWinding;
3027        }
3028        if (oppMaxWinding != oppSumWinding && useInnerWinding(oppMaxWinding, oppSumWinding)) {
3029            oppMaxWinding = oppSumWinding;
3030        }
3031        Span* last;
3032        if (activeAngle) {
3033            last = markAndChaseWinding(angle, maxWinding, oppMaxWinding);
3034        } else {
3035            last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding);
3036        }
3037        return last;
3038    }
3039
3040    // FIXME: this should also mark spans with equal (x,y)
3041    // This may be called when the segment is already marked done. While this
3042    // wastes time, it shouldn't do any more than spin through the T spans.
3043    // OPTIMIZATION: abort on first done found (assuming that this code is
3044    // always called to mark segments done).
3045    void markDone(int index, int winding) {
3046      //  SkASSERT(!done());
3047        SkASSERT(winding);
3048        double referenceT = fTs[index].fT;
3049        int lesser = index;
3050        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3051            markOneDone(__FUNCTION__, lesser, winding);
3052        }
3053        do {
3054            markOneDone(__FUNCTION__, index, winding);
3055        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3056    }
3057
3058    void markDoneBinary(int index, int winding, int oppWinding) {
3059      //  SkASSERT(!done());
3060        SkASSERT(winding || oppWinding);
3061        double referenceT = fTs[index].fT;
3062        int lesser = index;
3063        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3064            markOneDoneBinary(__FUNCTION__, lesser, winding, oppWinding);
3065        }
3066        do {
3067            markOneDoneBinary(__FUNCTION__, index, winding, oppWinding);
3068        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3069    }
3070
3071    void markDoneBinary(int index) {
3072        double referenceT = fTs[index].fT;
3073        int lesser = index;
3074        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3075            markOneDoneBinary(__FUNCTION__, lesser);
3076        }
3077        do {
3078            markOneDoneBinary(__FUNCTION__, index);
3079        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3080    }
3081
3082    void markDoneUnary(int index, int winding) {
3083      //  SkASSERT(!done());
3084        SkASSERT(winding);
3085        double referenceT = fTs[index].fT;
3086        int lesser = index;
3087        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3088            markOneDoneUnary(__FUNCTION__, lesser, winding);
3089        }
3090        do {
3091            markOneDoneUnary(__FUNCTION__, index, winding);
3092        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3093    }
3094
3095    void markDoneUnary(int index) {
3096        double referenceT = fTs[index].fT;
3097        int lesser = index;
3098        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3099            markOneDoneUnary(__FUNCTION__, lesser);
3100        }
3101        do {
3102            markOneDoneUnary(__FUNCTION__, index);
3103        } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3104    }
3105
3106    void markOneDone(const char* funName, int tIndex, int winding) {
3107        Span* span = markOneWinding(funName, tIndex, winding);
3108        if (!span) {
3109            return;
3110        }
3111        span->fDone = true;
3112        fDoneSpans++;
3113    }
3114
3115    void markOneDoneBinary(const char* funName, int tIndex) {
3116        Span* span = verifyOneWinding(funName, tIndex);
3117        if (!span) {
3118            return;
3119        }
3120        span->fDone = true;
3121        fDoneSpans++;
3122    }
3123
3124    void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding) {
3125        Span* span = markOneWinding(funName, tIndex, winding, oppWinding);
3126        if (!span) {
3127            return;
3128        }
3129        span->fDone = true;
3130        fDoneSpans++;
3131    }
3132
3133    void markOneDoneUnary(const char* funName, int tIndex) {
3134        Span* span = verifyOneWindingU(funName, tIndex);
3135        if (!span) {
3136            return;
3137        }
3138        span->fDone = true;
3139        fDoneSpans++;
3140    }
3141
3142    void markOneDoneUnary(const char* funName, int tIndex, int winding) {
3143        Span* span = markOneWinding(funName, tIndex, winding);
3144        if (!span) {
3145            return;
3146        }
3147        span->fDone = true;
3148        fDoneSpans++;
3149    }
3150
3151    Span* markOneWinding(const char* funName, int tIndex, int winding) {
3152        Span& span = fTs[tIndex];
3153        if (span.fDone) {
3154            return NULL;
3155        }
3156    #if DEBUG_MARK_DONE
3157        debugShowNewWinding(funName, span, winding);
3158    #endif
3159        SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
3160   #ifdef SK_DEBUG
3161        SkASSERT(abs(winding) <= gDebugMaxWindSum);
3162   #endif
3163        span.fWindSum = winding;
3164        return &span;
3165    }
3166
3167    Span* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding) {
3168        Span& span = fTs[tIndex];
3169        if (span.fDone) {
3170            return NULL;
3171        }
3172    #if DEBUG_MARK_DONE
3173        debugShowNewWinding(funName, span, winding, oppWinding);
3174    #endif
3175        SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
3176   #ifdef SK_DEBUG
3177        SkASSERT(abs(winding) <= gDebugMaxWindSum);
3178   #endif
3179        span.fWindSum = winding;
3180        SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
3181   #ifdef SK_DEBUG
3182        SkASSERT(abs(oppWinding) <= gDebugMaxWindSum);
3183   #endif
3184        span.fOppSum = oppWinding;
3185        return &span;
3186    }
3187
3188    Span* verifyOneWinding(const char* funName, int tIndex) {
3189        Span& span = fTs[tIndex];
3190        if (span.fDone) {
3191            return NULL;
3192        }
3193    #if DEBUG_MARK_DONE
3194        debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum);
3195    #endif
3196        SkASSERT(span.fWindSum != SK_MinS32);
3197        SkASSERT(span.fOppSum != SK_MinS32);
3198        return &span;
3199    }
3200
3201    Span* verifyOneWindingU(const char* funName, int tIndex) {
3202        Span& span = fTs[tIndex];
3203        if (span.fDone) {
3204            return NULL;
3205        }
3206    #if DEBUG_MARK_DONE
3207        debugShowNewWinding(funName, span, span.fWindSum);
3208    #endif
3209        SkASSERT(span.fWindSum != SK_MinS32);
3210        return &span;
3211    }
3212
3213    // note that just because a span has one end that is unsortable, that's
3214    // not enough to mark it done. The other end may be sortable, allowing the
3215    // span to be added.
3216    void markUnsortable(int start, int end) {
3217        Span* span = &fTs[start];
3218        if (start < end) {
3219            span->fUnsortableStart = true;
3220        } else {
3221            --span;
3222            span->fUnsortableEnd = true;
3223        }
3224        if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) {
3225            return;
3226        }
3227        span->fDone = true;
3228        fDoneSpans++;
3229    }
3230
3231    void markWinding(int index, int winding) {
3232    //    SkASSERT(!done());
3233        SkASSERT(winding);
3234        double referenceT = fTs[index].fT;
3235        int lesser = index;
3236        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3237            markOneWinding(__FUNCTION__, lesser, winding);
3238        }
3239        do {
3240            markOneWinding(__FUNCTION__, index, winding);
3241       } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3242    }
3243
3244    void markWinding(int index, int winding, int oppWinding) {
3245    //    SkASSERT(!done());
3246        SkASSERT(winding || oppWinding);
3247        double referenceT = fTs[index].fT;
3248        int lesser = index;
3249        while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
3250            markOneWinding(__FUNCTION__, lesser, winding, oppWinding);
3251        }
3252        do {
3253            markOneWinding(__FUNCTION__, index, winding, oppWinding);
3254       } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
3255    }
3256
3257    void matchWindingValue(int tIndex, double t, bool borrowWind) {
3258        int nextDoorWind = SK_MaxS32;
3259        int nextOppWind = SK_MaxS32;
3260        if (tIndex > 0) {
3261            const Span& below = fTs[tIndex - 1];
3262            if (approximately_negative(t - below.fT)) {
3263                nextDoorWind = below.fWindValue;
3264                nextOppWind = below.fOppValue;
3265            }
3266        }
3267        if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
3268            const Span& above = fTs[tIndex + 1];
3269            if (approximately_negative(above.fT - t)) {
3270                nextDoorWind = above.fWindValue;
3271                nextOppWind = above.fOppValue;
3272            }
3273        }
3274        if (nextDoorWind == SK_MaxS32 && borrowWind && tIndex > 0 && t < 1) {
3275            const Span& below = fTs[tIndex - 1];
3276            nextDoorWind = below.fWindValue;
3277            nextOppWind = below.fOppValue;
3278        }
3279        if (nextDoorWind != SK_MaxS32) {
3280            Span& newSpan = fTs[tIndex];
3281            newSpan.fWindValue = nextDoorWind;
3282            newSpan.fOppValue = nextOppWind;
3283            if (!nextDoorWind && !nextOppWind && !newSpan.fDone) {
3284                newSpan.fDone = true;
3285                ++fDoneSpans;
3286            }
3287        }
3288    }
3289
3290    // return span if when chasing, two or more radiating spans are not done
3291    // OPTIMIZATION: ? multiple spans is detected when there is only one valid
3292    // candidate and the remaining spans have windValue == 0 (canceled by
3293    // coincidence). The coincident edges could either be removed altogether,
3294    // or this code could be more complicated in detecting this case. Worth it?
3295    bool multipleSpans(int end) const {
3296        return end > 0 && end < fTs.count() - 1;
3297    }
3298
3299    Segment* nextChase(int& index, const int step, int& min, Span*& last) const {
3300        int end = nextExactSpan(index, step);
3301        SkASSERT(end >= 0);
3302        if (multipleSpans(end)) {
3303            last = &fTs[end];
3304            return NULL;
3305        }
3306        const Span& endSpan = fTs[end];
3307        Segment* other = endSpan.fOther;
3308        index = endSpan.fOtherIndex;
3309        int otherEnd = other->nextExactSpan(index, step);
3310        min = SkMin32(index, otherEnd);
3311        return other;
3312    }
3313
3314    // This has callers for two different situations: one establishes the end
3315    // of the current span, and one establishes the beginning of the next span
3316    // (thus the name). When this is looking for the end of the current span,
3317    // coincidence is found when the beginning Ts contain -step and the end
3318    // contains step. When it is looking for the beginning of the next, the
3319    // first Ts found can be ignored and the last Ts should contain -step.
3320    // OPTIMIZATION: probably should split into two functions
3321    int nextSpan(int from, int step) const {
3322        const Span& fromSpan = fTs[from];
3323        int count = fTs.count();
3324        int to = from;
3325        while (step > 0 ? ++to < count : --to >= 0) {
3326            const Span& span = fTs[to];
3327            if (approximately_zero(span.fT - fromSpan.fT)) {
3328                continue;
3329            }
3330            return to;
3331        }
3332        return -1;
3333    }
3334
3335    // FIXME
3336    // this returns at any difference in T, vs. a preset minimum. It may be
3337    // that all callers to nextSpan should use this instead.
3338    // OPTIMIZATION splitting this into separate loops for up/down steps
3339    // would allow using precisely_negative instead of precisely_zero
3340    int nextExactSpan(int from, int step) const {
3341        const Span& fromSpan = fTs[from];
3342        int count = fTs.count();
3343        int to = from;
3344        while (step > 0 ? ++to < count : --to >= 0) {
3345            const Span& span = fTs[to];
3346            if (precisely_zero(span.fT - fromSpan.fT)) {
3347                continue;
3348            }
3349            return to;
3350        }
3351        return -1;
3352    }
3353
3354    bool operand() const {
3355        return fOperand;
3356    }
3357
3358    int oppSign(const Angle* angle) const {
3359        SkASSERT(angle->segment() == this);
3360        return oppSign(angle->start(), angle->end());
3361    }
3362
3363    int oppSign(int startIndex, int endIndex) const {
3364        int result = startIndex < endIndex ? -fTs[startIndex].fOppValue
3365                : fTs[endIndex].fOppValue;
3366#if DEBUG_WIND_BUMP
3367        SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
3368#endif
3369        return result;
3370    }
3371
3372    int oppSum(int tIndex) const {
3373        return fTs[tIndex].fOppSum;
3374    }
3375
3376    int oppSum(const Angle* angle) const {
3377        int lesser = SkMin32(angle->start(), angle->end());
3378        return fTs[lesser].fOppSum;
3379    }
3380
3381    int oppValue(int tIndex) const {
3382        return fTs[tIndex].fOppValue;
3383    }
3384
3385    int oppValue(const Angle* angle) const {
3386        int lesser = SkMin32(angle->start(), angle->end());
3387        return fTs[lesser].fOppValue;
3388    }
3389
3390    const SkPoint* pts() const {
3391        return fPts;
3392    }
3393
3394    void reset() {
3395        init(NULL, (SkPath::Verb) -1, false, false);
3396        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
3397        fTs.reset();
3398    }
3399
3400    void setOppXor(bool isOppXor) {
3401        fOppXor = isOppXor;
3402    }
3403
3404    void setUpWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
3405        int deltaSum = spanSign(index, endIndex);
3406        maxWinding = sumWinding;
3407        sumWinding = sumWinding -= deltaSum;
3408    }
3409
3410    void setUpWindings(int index, int endIndex, int& sumMiWinding, int& sumSuWinding,
3411            int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding) {
3412        int deltaSum = spanSign(index, endIndex);
3413        int oppDeltaSum = oppSign(index, endIndex);
3414        if (operand()) {
3415            maxWinding = sumSuWinding;
3416            sumWinding = sumSuWinding -= deltaSum;
3417            oppMaxWinding = sumMiWinding;
3418            oppSumWinding = sumMiWinding -= oppDeltaSum;
3419        } else {
3420            maxWinding = sumMiWinding;
3421            sumWinding = sumMiWinding -= deltaSum;
3422            oppMaxWinding = sumSuWinding;
3423            oppSumWinding = sumSuWinding -= oppDeltaSum;
3424        }
3425    }
3426
3427    // This marks all spans unsortable so that this info is available for early
3428    // exclusion in find top and others. This could be optimized to only mark
3429    // adjacent spans that unsortable. However, this makes it difficult to later
3430    // determine starting points for edge detection in find top and the like.
3431    static bool SortAngles(SkTDArray<Angle>& angles, SkTDArray<Angle*>& angleList) {
3432        bool sortable = true;
3433        int angleCount = angles.count();
3434        int angleIndex;
3435        angleList.setReserve(angleCount);
3436        for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
3437            Angle& angle = angles[angleIndex];
3438            *angleList.append() = &angle;
3439            sortable &= !angle.unsortable();
3440        }
3441        if (sortable) {
3442            QSort<Angle>(angleList.begin(), angleList.end() - 1);
3443            for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
3444                if (angles[angleIndex].unsortable()) {
3445                    sortable = false;
3446                    break;
3447                }
3448            }
3449        }
3450        if (!sortable) {
3451            for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
3452                Angle& angle = angles[angleIndex];
3453                angle.segment()->markUnsortable(angle.start(), angle.end());
3454            }
3455        }
3456        return sortable;
3457    }
3458
3459    // OPTIMIZATION: mark as debugging only if used solely by tests
3460    const Span& span(int tIndex) const {
3461        return fTs[tIndex];
3462    }
3463
3464    int spanSign(const Angle* angle) const {
3465        SkASSERT(angle->segment() == this);
3466        return spanSign(angle->start(), angle->end());
3467    }
3468
3469    int spanSign(int startIndex, int endIndex) const {
3470        int result = startIndex < endIndex ? -fTs[startIndex].fWindValue
3471                : fTs[endIndex].fWindValue;
3472#if DEBUG_WIND_BUMP
3473        SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
3474#endif
3475        return result;
3476    }
3477
3478    // OPTIMIZATION: mark as debugging only if used solely by tests
3479    double t(int tIndex) const {
3480        return fTs[tIndex].fT;
3481    }
3482
3483    bool tiny(const Angle* angle) const {
3484        int start = angle->start();
3485        int end = angle->end();
3486        const Span& mSpan = fTs[SkMin32(start, end)];
3487        return mSpan.fTiny;
3488    }
3489
3490    static void TrackOutside(SkTDArray<double>& outsideTs, double end,
3491            double start) {
3492        int outCount = outsideTs.count();
3493        if (outCount == 0 || !approximately_negative(end - outsideTs[outCount - 2])) {
3494            *outsideTs.append() = end;
3495            *outsideTs.append() = start;
3496        }
3497    }
3498
3499    void undoneSpan(int& start, int& end) {
3500        size_t tCount = fTs.count();
3501        size_t index;
3502        for (index = 0; index < tCount; ++index) {
3503            if (!fTs[index].fDone) {
3504                break;
3505            }
3506        }
3507        SkASSERT(index < tCount - 1);
3508        start = index;
3509        double startT = fTs[index].fT;
3510        while (approximately_negative(fTs[++index].fT - startT))
3511            SkASSERT(index < tCount);
3512        SkASSERT(index < tCount);
3513        end = index;
3514    }
3515
3516    bool unsortable(int index) const {
3517        return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
3518    }
3519
3520    void updatePts(const SkPoint pts[]) {
3521        fPts = pts;
3522    }
3523
3524    int updateOppWinding(int index, int endIndex) const {
3525        int lesser = SkMin32(index, endIndex);
3526        int oppWinding = oppSum(lesser);
3527        int oppSpanWinding = oppSign(index, endIndex);
3528        if (oppSpanWinding && useInnerWinding(oppWinding - oppSpanWinding, oppWinding)) {
3529            oppWinding -= oppSpanWinding;
3530        }
3531        return oppWinding;
3532    }
3533
3534    int updateOppWinding(const Angle* angle) const {
3535        int startIndex = angle->start();
3536        int endIndex = angle->end();
3537        return updateOppWinding(endIndex, startIndex);
3538    }
3539
3540    int updateOppWindingReverse(const Angle* angle) const {
3541        int startIndex = angle->start();
3542        int endIndex = angle->end();
3543        return updateOppWinding(startIndex, endIndex);
3544    }
3545
3546    int updateWinding(int index, int endIndex) const {
3547        int lesser = SkMin32(index, endIndex);
3548        int winding = windSum(lesser);
3549        int spanWinding = spanSign(index, endIndex);
3550        if (winding && useInnerWinding(winding - spanWinding, winding)) {
3551            winding -= spanWinding;
3552        }
3553        return winding;
3554    }
3555
3556    int updateWinding(const Angle* angle) const {
3557        int startIndex = angle->start();
3558        int endIndex = angle->end();
3559        return updateWinding(endIndex, startIndex);
3560    }
3561
3562    int updateWindingReverse(const Angle* angle) const {
3563        int startIndex = angle->start();
3564        int endIndex = angle->end();
3565        return updateWinding(startIndex, endIndex);
3566    }
3567
3568    SkPath::Verb verb() const {
3569        return fVerb;
3570    }
3571
3572    int windingAtT(double tHit, int tIndex, bool crossOpp) const {
3573        if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span, disregard
3574            return SK_MinS32;
3575        }
3576        int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex);
3577        SkASSERT(winding != SK_MinS32);
3578        int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex);
3579    #if DEBUG_WINDING
3580        SkDebugf("%s single winding=%d windValue=%d\n", __FUNCTION__, winding,
3581                windVal);
3582    #endif
3583        // see if a + change in T results in a +/- change in X (compute x'(T))
3584        SkScalar dx = (*SegmentDXAtT[fVerb])(fPts, tHit);
3585        if (fVerb > SkPath::kLine_Verb && approximately_zero(dx)) {
3586            dx = fPts[2].fX - fPts[1].fX - dx;
3587        }
3588    #if DEBUG_WINDING
3589        SkDebugf("%s dx=%1.9g\n", __FUNCTION__, dx);
3590    #endif
3591        SkASSERT(dx != 0);
3592        if (winding * dx > 0) { // if same signs, result is negative
3593            winding += dx > 0 ? -windVal : windVal;
3594    #if DEBUG_WINDING
3595            SkDebugf("%s final winding=%d\n", __FUNCTION__, winding);
3596    #endif
3597        }
3598        return winding;
3599    }
3600
3601    int windSum(int tIndex) const {
3602        return fTs[tIndex].fWindSum;
3603    }
3604
3605    int windSum(const Angle* angle) const {
3606        int start = angle->start();
3607        int end = angle->end();
3608        int index = SkMin32(start, end);
3609        return windSum(index);
3610    }
3611
3612    int windValue(int tIndex) const {
3613        return fTs[tIndex].fWindValue;
3614    }
3615
3616    int windValue(const Angle* angle) const {
3617        int start = angle->start();
3618        int end = angle->end();
3619        int index = SkMin32(start, end);
3620        return windValue(index);
3621    }
3622
3623    SkScalar xAtT(const Span* span) const {
3624        return xyAtT(span).fX;
3625    }
3626
3627    const SkPoint& xyAtT(int index) const {
3628        return xyAtT(&fTs[index]);
3629    }
3630
3631    const SkPoint& xyAtT(const Span* span) const {
3632        if (SkScalarIsNaN(span->fPt.fX)) {
3633            if (span->fT == 0) {
3634                span->fPt = fPts[0];
3635            } else if (span->fT == 1) {
3636                span->fPt = fPts[fVerb];
3637            } else {
3638                (*SegmentXYAtT[fVerb])(fPts, span->fT, &span->fPt);
3639            }
3640        }
3641        return span->fPt;
3642    }
3643
3644    SkScalar yAtT(int index) const {
3645        return yAtT(&fTs[index]);
3646    }
3647
3648    SkScalar yAtT(const Span* span) const {
3649        return xyAtT(span).fY;
3650    }
3651
3652    void zeroCoincidentOpp(Span* oTest, int index) {
3653        Span* const test = &fTs[index];
3654        Span* end = test;
3655        do {
3656            end->fOppValue = 0;
3657            end = &fTs[++index];
3658        } while (approximately_negative(end->fT - test->fT));
3659    }
3660
3661    void zeroCoincidentOther(Span* test, const double tRatio, const double oEndT, int oIndex) {
3662        Span* const oTest = &fTs[oIndex];
3663        Span* oEnd = oTest;
3664        const double startT = test->fT;
3665        const double oStartT = oTest->fT;
3666        double otherTMatch = (test->fT - startT) * tRatio + oStartT;
3667        while (!approximately_negative(oEndT - oEnd->fT)
3668                && approximately_negative(oEnd->fT - otherTMatch)) {
3669            oEnd->fOppValue = 0;
3670            oEnd = &fTs[++oIndex];
3671        }
3672    }
3673
3674    void zeroSpan(Span* span) {
3675        SkASSERT(span->fWindValue > 0 || span->fOppValue > 0);
3676        span->fWindValue = 0;
3677        span->fOppValue = 0;
3678        SkASSERT(!span->fDone);
3679        span->fDone = true;
3680        ++fDoneSpans;
3681    }
3682
3683#if DEBUG_DUMP
3684    void dump() const {
3685        const char className[] = "Segment";
3686        const int tab = 4;
3687        for (int i = 0; i < fTs.count(); ++i) {
3688            SkPoint out;
3689            (*SegmentXYAtT[fVerb])(fPts, t(i), &out);
3690            SkDebugf("%*s [%d] %s.fTs[%d]=%1.9g (%1.9g,%1.9g) other=%d"
3691                    " otherT=%1.9g windSum=%d\n",
3692                    tab + sizeof(className), className, fID,
3693                    kLVerbStr[fVerb], i, fTs[i].fT, out.fX, out.fY,
3694                    fTs[i].fOther->fID, fTs[i].fOtherT, fTs[i].fWindSum);
3695        }
3696        SkDebugf("%*s [%d] fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)",
3697                tab + sizeof(className), className, fID,
3698                fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
3699    }
3700#endif
3701
3702#if DEBUG_CONCIDENT
3703    // assert if pair has not already been added
3704     void debugAddTPair(double t, const Segment& other, double otherT) const {
3705        for (int i = 0; i < fTs.count(); ++i) {
3706            if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
3707                return;
3708            }
3709        }
3710        SkASSERT(0);
3711     }
3712#endif
3713
3714#if DEBUG_DUMP
3715    int debugID() const {
3716        return fID;
3717    }
3718#endif
3719
3720#if DEBUG_WINDING
3721    void debugShowSums() const {
3722        SkDebugf("%s id=%d (%1.9g,%1.9g %1.9g,%1.9g)", __FUNCTION__, fID,
3723            fPts[0].fX, fPts[0].fY, fPts[fVerb].fX, fPts[fVerb].fY);
3724        for (int i = 0; i < fTs.count(); ++i) {
3725            const Span& span = fTs[i];
3726            SkDebugf(" [t=%1.3g %1.9g,%1.9g w=", span.fT, xAtT(&span), yAtT(&span));
3727            if (span.fWindSum == SK_MinS32) {
3728                SkDebugf("?");
3729            } else {
3730                SkDebugf("%d", span.fWindSum);
3731            }
3732            SkDebugf("]");
3733        }
3734        SkDebugf("\n");
3735    }
3736#endif
3737
3738#if DEBUG_CONCIDENT
3739    void debugShowTs() const {
3740        SkDebugf("%s id=%d", __FUNCTION__, fID);
3741        int lastWind = -1;
3742        int lastOpp = -1;
3743        double lastT = -1;
3744        int i;
3745        for (i = 0; i < fTs.count(); ++i) {
3746            bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
3747                    || lastOpp != fTs[i].fOppValue;
3748            if (change && lastWind >= 0) {
3749                SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
3750                        lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
3751            }
3752            if (change) {
3753                SkDebugf(" [o=%d", fTs[i].fOther->fID);
3754                lastWind = fTs[i].fWindValue;
3755                lastOpp = fTs[i].fOppValue;
3756                lastT = fTs[i].fT;
3757            } else {
3758                SkDebugf(",%d", fTs[i].fOther->fID);
3759            }
3760        }
3761        if (i <= 0) {
3762            return;
3763        }
3764        SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
3765                lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
3766        if (fOperand) {
3767            SkDebugf(" operand");
3768        }
3769        if (done()) {
3770            SkDebugf(" done");
3771        }
3772        SkDebugf("\n");
3773    }
3774#endif
3775
3776#if DEBUG_ACTIVE_SPANS
3777    void debugShowActiveSpans() const {
3778        if (done()) {
3779            return;
3780        }
3781#if DEBUG_ACTIVE_SPANS_SHORT_FORM
3782        int lastId = -1;
3783        double lastT = -1;
3784#endif
3785        for (int i = 0; i < fTs.count(); ++i) {
3786            if (fTs[i].fDone) {
3787                continue;
3788            }
3789#if DEBUG_ACTIVE_SPANS_SHORT_FORM
3790            if (lastId == fID && lastT == fTs[i].fT) {
3791                continue;
3792            }
3793            lastId = fID;
3794            lastT = fTs[i].fT;
3795#endif
3796            SkDebugf("%s id=%d", __FUNCTION__, fID);
3797            SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3798            for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
3799                SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3800            }
3801            const Span* span = &fTs[i];
3802            SkDebugf(") t=%1.9g (%1.9g,%1.9g)", fTs[i].fT,
3803                     xAtT(span), yAtT(span));
3804            const Segment* other = fTs[i].fOther;
3805            SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
3806                    other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
3807            if (fTs[i].fWindSum == SK_MinS32) {
3808                SkDebugf("?");
3809            } else {
3810                SkDebugf("%d", fTs[i].fWindSum);
3811            }
3812            SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
3813        }
3814    }
3815
3816    // This isn't useful yet -- but leaving it in for now in case i think of something
3817    // to use it for
3818    void validateActiveSpans() const {
3819        if (done()) {
3820            return;
3821        }
3822        int tCount = fTs.count();
3823        for (int index = 0; index < tCount; ++index) {
3824            if (fTs[index].fDone) {
3825                continue;
3826            }
3827            // count number of connections which are not done
3828            int first = index;
3829            double baseT = fTs[index].fT;
3830            while (first > 0 && approximately_equal(fTs[first - 1].fT, baseT)) {
3831                --first;
3832            }
3833            int last = index;
3834            while (last < tCount - 1 && approximately_equal(fTs[last + 1].fT, baseT)) {
3835                ++last;
3836            }
3837            int connections = 0;
3838            connections += first > 0 && !fTs[first - 1].fDone;
3839            for (int test = first; test <= last; ++test) {
3840                connections += !fTs[test].fDone;
3841                const Segment* other = fTs[test].fOther;
3842                int oIndex = fTs[test].fOtherIndex;
3843                connections += !other->fTs[oIndex].fDone;
3844                connections += oIndex > 0 && !other->fTs[oIndex - 1].fDone;
3845            }
3846      //      SkASSERT(!(connections & 1));
3847        }
3848    }
3849#endif
3850
3851#if DEBUG_MARK_DONE
3852    void debugShowNewWinding(const char* fun, const Span& span, int winding) {
3853        const SkPoint& pt = xyAtT(&span);
3854        SkDebugf("%s id=%d", fun, fID);
3855        SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3856        for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
3857            SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3858        }
3859        SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
3860                fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
3861        SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) newWindSum=%d windSum=",
3862                span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY, winding);
3863        if (span.fWindSum == SK_MinS32) {
3864            SkDebugf("?");
3865        } else {
3866            SkDebugf("%d", span.fWindSum);
3867        }
3868        SkDebugf(" windValue=%d\n", span.fWindValue);
3869    }
3870
3871    void debugShowNewWinding(const char* fun, const Span& span, int winding, int oppWinding) {
3872        const SkPoint& pt = xyAtT(&span);
3873        SkDebugf("%s id=%d", fun, fID);
3874        SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
3875        for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
3876            SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
3877        }
3878        SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
3879                fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
3880        SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) newWindSum=%d newOppSum=%d oppSum=",
3881                span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
3882                winding, oppWinding);
3883        if (span.fOppSum == SK_MinS32) {
3884            SkDebugf("?");
3885        } else {
3886            SkDebugf("%d", span.fOppSum);
3887        }
3888        SkDebugf(" windSum=");
3889        if (span.fWindSum == SK_MinS32) {
3890            SkDebugf("?");
3891        } else {
3892            SkDebugf("%d", span.fWindSum);
3893        }
3894        SkDebugf(" windValue=%d\n", span.fWindValue);
3895    }
3896#endif
3897
3898#if DEBUG_SORT
3899    void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first,
3900            const int contourWinding, const int oppContourWinding) const {
3901        SkASSERT(angles[first]->segment() == this);
3902        SkASSERT(angles.count() > 1);
3903        int lastSum = contourWinding;
3904        int oppLastSum = oppContourWinding;
3905        const Angle* firstAngle = angles[first];
3906        int windSum = lastSum - spanSign(firstAngle);
3907        int oppoSign = oppSign(firstAngle);
3908        int oppWindSum = oppLastSum - oppoSign;
3909        SkDebugf("%s %s contourWinding=%d oppContourWinding=%d sign=%d\n", fun, __FUNCTION__,
3910                contourWinding, oppContourWinding, spanSign(angles[first]));
3911        int index = first;
3912        bool firstTime = true;
3913        do {
3914            const Angle& angle = *angles[index];
3915            const Segment& segment = *angle.segment();
3916            int start = angle.start();
3917            int end = angle.end();
3918            const Span& sSpan = segment.fTs[start];
3919            const Span& eSpan = segment.fTs[end];
3920            const Span& mSpan = segment.fTs[SkMin32(start, end)];
3921            bool opp = segment.fOperand ^ fOperand;
3922            if (!firstTime) {
3923                oppoSign = segment.oppSign(&angle);
3924                if (opp) {
3925                    oppLastSum = oppWindSum;
3926                    oppWindSum -= segment.spanSign(&angle);
3927                    if (oppoSign) {
3928                        lastSum = windSum;
3929                        windSum -= oppoSign;
3930                    }
3931                } else {
3932                    lastSum = windSum;
3933                    windSum -= segment.spanSign(&angle);
3934                    if (oppoSign) {
3935                        oppLastSum = oppWindSum;
3936                        oppWindSum -= oppoSign;
3937                    }
3938                }
3939            }
3940            SkDebugf("%s [%d] %sid=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)"
3941                    " sign=%d windValue=%d windSum=",
3942                    __FUNCTION__, index, angle.unsortable() ? "*** UNSORTABLE *** " : "",
3943                    segment.fID, kLVerbStr[segment.fVerb],
3944                    start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
3945                    segment.xAtT(&eSpan), segment.yAtT(&eSpan), angle.sign(),
3946                    mSpan.fWindValue);
3947            if (mSpan.fWindSum == SK_MinS32) {
3948                SkDebugf("?");
3949            } else {
3950                SkDebugf("%d", mSpan.fWindSum);
3951            }
3952            int last, wind;
3953            if (opp) {
3954                last = oppLastSum;
3955                wind = oppWindSum;
3956            } else {
3957                last = lastSum;
3958                wind = windSum;
3959            }
3960            if (!oppoSign) {
3961                SkDebugf(" %d->%d (max=%d)", last, wind,
3962                        useInnerWinding(last, wind) ? wind : last);
3963            } else {
3964                SkDebugf(" %d->%d (%d->%d)", last, wind, opp ? lastSum : oppLastSum,
3965                        opp ? windSum : oppWindSum);
3966            }
3967            SkDebugf(" done=%d tiny=%d opp=%d\n", mSpan.fDone, mSpan.fTiny, opp);
3968#if false && DEBUG_ANGLE
3969            angle.debugShow(segment.xyAtT(&sSpan));
3970#endif
3971            ++index;
3972            if (index == angles.count()) {
3973                index = 0;
3974            }
3975            if (firstTime) {
3976                firstTime = false;
3977            }
3978        } while (index != first);
3979    }
3980
3981    void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first) {
3982        const Angle* firstAngle = angles[first];
3983        const Segment* segment = firstAngle->segment();
3984        int winding = segment->updateWinding(firstAngle);
3985        int oppWinding = segment->updateOppWinding(firstAngle);
3986        debugShowSort(fun, angles, first, winding, oppWinding);
3987    }
3988
3989#endif
3990
3991#if DEBUG_WINDING
3992    static char as_digit(int value) {
3993        return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
3994    }
3995#endif
3996
3997#if DEBUG_SHOW_WINDING
3998    int debugShowWindingValues(int slotCount, int ofInterest) const {
3999        if (!(1 << fID & ofInterest)) {
4000            return 0;
4001        }
4002        int sum = 0;
4003        SkTDArray<char> slots;
4004        slots.setCount(slotCount * 2);
4005        memset(slots.begin(), ' ', slotCount * 2);
4006        for (int i = 0; i < fTs.count(); ++i) {
4007       //     if (!(1 << fTs[i].fOther->fID & ofInterest)) {
4008       //         continue;
4009       //     }
4010            sum += fTs[i].fWindValue;
4011            slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
4012            sum += fTs[i].fOppValue;
4013            slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
4014        }
4015        SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
4016                slots.begin() + slotCount);
4017        return sum;
4018    }
4019#endif
4020
4021private:
4022    const SkPoint* fPts;
4023    Bounds fBounds;
4024    SkTDArray<Span> fTs; // two or more (always includes t=0 t=1)
4025    // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
4026    int fDoneSpans; // quick check that segment is finished
4027    // OPTIMIZATION: force the following to be byte-sized
4028    SkPath::Verb fVerb;
4029    bool fOperand;
4030    bool fXor; // set if original contour had even-odd fill
4031    bool fOppXor; // set if opposite operand had even-odd fill
4032#if DEBUG_DUMP
4033    int fID;
4034#endif
4035};
4036
4037class Contour;
4038
4039struct Coincidence {
4040    Contour* fContours[2];
4041    int fSegments[2];
4042    double fTs[2][2];
4043};
4044
4045class Contour {
4046public:
4047    Contour() {
4048        reset();
4049#if DEBUG_DUMP
4050        fID = ++gContourID;
4051#endif
4052    }
4053
4054    bool operator<(const Contour& rh) const {
4055        return fBounds.fTop == rh.fBounds.fTop
4056                ? fBounds.fLeft < rh.fBounds.fLeft
4057                : fBounds.fTop < rh.fBounds.fTop;
4058    }
4059
4060    void addCoincident(int index, Contour* other, int otherIndex,
4061            const Intersections& ts, bool swap) {
4062        Coincidence& coincidence = *fCoincidences.append();
4063        coincidence.fContours[0] = this; // FIXME: no need to store
4064        coincidence.fContours[1] = other;
4065        coincidence.fSegments[0] = index;
4066        coincidence.fSegments[1] = otherIndex;
4067        if (fSegments[index].verb() == SkPath::kLine_Verb &&
4068                other->fSegments[otherIndex].verb() == SkPath::kLine_Verb) {
4069            // FIXME: coincident lines use legacy Ts instead of coincident Ts
4070            coincidence.fTs[swap][0] = ts.fT[0][0];
4071            coincidence.fTs[swap][1] = ts.fT[0][1];
4072            coincidence.fTs[!swap][0] = ts.fT[1][0];
4073            coincidence.fTs[!swap][1] = ts.fT[1][1];
4074        } else if (fSegments[index].verb() == SkPath::kQuad_Verb &&
4075                other->fSegments[otherIndex].verb() == SkPath::kQuad_Verb) {
4076            coincidence.fTs[swap][0] = ts.fCoincidentT[0][0];
4077            coincidence.fTs[swap][1] = ts.fCoincidentT[0][1];
4078            coincidence.fTs[!swap][0] = ts.fCoincidentT[1][0];
4079            coincidence.fTs[!swap][1] = ts.fCoincidentT[1][1];
4080        }
4081    }
4082
4083    void addCross(const Contour* crosser) {
4084#ifdef DEBUG_CROSS
4085        for (int index = 0; index < fCrosses.count(); ++index) {
4086            SkASSERT(fCrosses[index] != crosser);
4087        }
4088#endif
4089        *fCrosses.append() = crosser;
4090    }
4091
4092    void addCubic(const SkPoint pts[4]) {
4093        fSegments.push_back().addCubic(pts, fOperand, fXor);
4094        fContainsCurves = true;
4095    }
4096
4097    int addLine(const SkPoint pts[2]) {
4098        fSegments.push_back().addLine(pts, fOperand, fXor);
4099        return fSegments.count();
4100    }
4101
4102    void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
4103        fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
4104    }
4105
4106    int addQuad(const SkPoint pts[3]) {
4107        fSegments.push_back().addQuad(pts, fOperand, fXor);
4108        fContainsCurves = true;
4109        return fSegments.count();
4110    }
4111
4112    int addT(int segIndex, double newT, Contour* other, int otherIndex) {
4113        containsIntercepts();
4114        return fSegments[segIndex].addT(newT, &other->fSegments[otherIndex]);
4115    }
4116
4117    const Bounds& bounds() const {
4118        return fBounds;
4119    }
4120
4121    void complete() {
4122        setBounds();
4123        fContainsIntercepts = false;
4124    }
4125
4126    void containsIntercepts() {
4127        fContainsIntercepts = true;
4128    }
4129
4130    const Segment* crossedSegmentX(const SkPoint& basePt, SkScalar& bestX,
4131            int& tIndex, double& hitT, bool opp) {
4132        int segmentCount = fSegments.count();
4133        const Segment* bestSegment = NULL;
4134        for (int test = 0; test < segmentCount; ++test) {
4135            Segment* testSegment = &fSegments[test];
4136            const SkRect& bounds = testSegment->bounds();
4137            if (bounds.fRight <= bestX) {
4138                continue;
4139            }
4140            if (bounds.fLeft >= basePt.fX) {
4141                continue;
4142            }
4143            if (bounds.fTop > basePt.fY) {
4144                continue;
4145            }
4146            if (bounds.fBottom < basePt.fY) {
4147                continue;
4148            }
4149            if (bounds.fTop == bounds.fBottom) {
4150                continue;
4151            }
4152            double testHitT;
4153            int testT = testSegment->crossedSpanX(basePt, bestX, testHitT, opp);
4154            if (testT >= 0) {
4155                bestSegment = testSegment;
4156                tIndex = testT;
4157                hitT = testHitT;
4158            }
4159        }
4160        return bestSegment;
4161    }
4162
4163    const Segment* crossedSegmentY(const SkPoint& basePt, SkScalar& bestY,
4164            int &tIndex, double& hitT, bool opp) {
4165        int segmentCount = fSegments.count();
4166        const Segment* bestSegment = NULL;
4167        for (int test = 0; test < segmentCount; ++test) {
4168            Segment* testSegment = &fSegments[test];
4169            const SkRect& bounds = testSegment->bounds();
4170            if (bounds.fBottom <= bestY) {
4171                continue;
4172            }
4173            if (bounds.fTop >= basePt.fY) {
4174                continue;
4175            }
4176            if (bounds.fLeft > basePt.fX) {
4177                continue;
4178            }
4179            if (bounds.fRight < basePt.fX) {
4180                continue;
4181            }
4182            if (bounds.fLeft == bounds.fRight) {
4183                continue;
4184            }
4185            double testHitT;
4186            int testT = testSegment->crossedSpanY(basePt, bestY, testHitT, opp);
4187            if (testT >= 0) {
4188                bestSegment = testSegment;
4189                tIndex = testT;
4190                hitT = testHitT;
4191            }
4192        }
4193        return bestSegment;
4194    }
4195
4196    bool crosses(const Contour* crosser) const {
4197        for (int index = 0; index < fCrosses.count(); ++index) {
4198            if (fCrosses[index] == crosser) {
4199                return true;
4200            }
4201        }
4202        return false;
4203    }
4204
4205    const SkPoint& end() const {
4206        const Segment& segment = fSegments.back();
4207        return segment.pts()[segment.verb()];
4208    }
4209
4210    void findTooCloseToCall() {
4211        int segmentCount = fSegments.count();
4212        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
4213            fSegments[sIndex].findTooCloseToCall();
4214        }
4215    }
4216
4217    void fixOtherTIndex() {
4218        int segmentCount = fSegments.count();
4219        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
4220            fSegments[sIndex].fixOtherTIndex();
4221        }
4222    }
4223
4224    bool operand() const {
4225        return fOperand;
4226    }
4227
4228    void reset() {
4229        fSegments.reset();
4230        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
4231        fContainsCurves = fContainsIntercepts = false;
4232    }
4233
4234    void resolveCoincidence(SkTDArray<Contour*>& contourList) {
4235        int count = fCoincidences.count();
4236        for (int index = 0; index < count; ++index) {
4237            Coincidence& coincidence = fCoincidences[index];
4238            SkASSERT(coincidence.fContours[0] == this);
4239            int thisIndex = coincidence.fSegments[0];
4240            Segment& thisOne = fSegments[thisIndex];
4241            Contour* otherContour = coincidence.fContours[1];
4242            int otherIndex = coincidence.fSegments[1];
4243            Segment& other = otherContour->fSegments[otherIndex];
4244            if ((thisOne.done() || other.done()) && thisOne.complete() && other.complete()) {
4245                continue;
4246            }
4247        #if DEBUG_CONCIDENT
4248            thisOne.debugShowTs();
4249            other.debugShowTs();
4250        #endif
4251            double startT = coincidence.fTs[0][0];
4252            double endT = coincidence.fTs[0][1];
4253            bool cancelers = false;
4254            if (startT > endT) {
4255                SkTSwap<double>(startT, endT);
4256                cancelers ^= true; // FIXME: just assign true
4257            }
4258            SkASSERT(!approximately_negative(endT - startT));
4259            double oStartT = coincidence.fTs[1][0];
4260            double oEndT = coincidence.fTs[1][1];
4261            if (oStartT > oEndT) {
4262                SkTSwap<double>(oStartT, oEndT);
4263                cancelers ^= true;
4264            }
4265            SkASSERT(!approximately_negative(oEndT - oStartT));
4266            bool opp = fOperand ^ otherContour->fOperand;
4267            if (cancelers && !opp) {
4268                // make sure startT and endT have t entries
4269                if (startT > 0 || oEndT < 1
4270                        || thisOne.isMissing(startT) || other.isMissing(oEndT)) {
4271                    thisOne.addTPair(startT, other, oEndT, true);
4272                }
4273                if (oStartT > 0 || endT < 1
4274                        || thisOne.isMissing(endT) || other.isMissing(oStartT)) {
4275                    other.addTPair(oStartT, thisOne, endT, true);
4276                }
4277                if (!thisOne.done() && !other.done()) {
4278                    thisOne.addTCancel(startT, endT, other, oStartT, oEndT);
4279                }
4280            } else {
4281                if (startT > 0 || oStartT > 0
4282                        || thisOne.isMissing(startT) || other.isMissing(oStartT)) {
4283                    thisOne.addTPair(startT, other, oStartT, true);
4284                }
4285                if (endT < 1 || oEndT < 1
4286                        || thisOne.isMissing(endT) || other.isMissing(oEndT)) {
4287                    other.addTPair(oEndT, thisOne, endT, true);
4288                }
4289                if (!thisOne.done() && !other.done()) {
4290                    thisOne.addTCoincident(startT, endT, other, oStartT, oEndT);
4291                }
4292            }
4293        #if DEBUG_CONCIDENT
4294            thisOne.debugShowTs();
4295            other.debugShowTs();
4296        #endif
4297        #if DEBUG_SHOW_WINDING
4298            debugShowWindingValues(contourList);
4299        #endif
4300        }
4301    }
4302
4303    const SkTArray<Segment>& segments() {
4304        return fSegments;
4305    }
4306
4307    void setOperand(bool isOp) {
4308        fOperand = isOp;
4309    }
4310
4311    void setOppXor(bool isOppXor) {
4312        fOppXor = isOppXor;
4313        int segmentCount = fSegments.count();
4314        for (int test = 0; test < segmentCount; ++test) {
4315            fSegments[test].setOppXor(isOppXor);
4316        }
4317    }
4318
4319    void setXor(bool isXor) {
4320        fXor = isXor;
4321    }
4322
4323    void sortSegments() {
4324        int segmentCount = fSegments.count();
4325        fSortedSegments.setReserve(segmentCount);
4326        for (int test = 0; test < segmentCount; ++test) {
4327            *fSortedSegments.append() = &fSegments[test];
4328        }
4329        QSort<Segment>(fSortedSegments.begin(), fSortedSegments.end() - 1);
4330        fFirstSorted = 0;
4331    }
4332
4333    const SkPoint& start() const {
4334        return fSegments.front().pts()[0];
4335    }
4336
4337    void toPath(PathWrapper& path) const {
4338        int segmentCount = fSegments.count();
4339        const SkPoint& pt = fSegments.front().pts()[0];
4340        path.deferredMove(pt);
4341        for (int test = 0; test < segmentCount; ++test) {
4342            fSegments[test].addCurveTo(0, 1, path, true);
4343        }
4344        path.close();
4345    }
4346
4347    void toPartialBackward(PathWrapper& path) const {
4348        int segmentCount = fSegments.count();
4349        for (int test = segmentCount - 1; test >= 0; --test) {
4350            fSegments[test].addCurveTo(1, 0, path, true);
4351        }
4352    }
4353
4354    void toPartialForward(PathWrapper& path) const {
4355        int segmentCount = fSegments.count();
4356        for (int test = 0; test < segmentCount; ++test) {
4357            fSegments[test].addCurveTo(0, 1, path, true);
4358        }
4359    }
4360
4361#if 0 // FIXME: obsolete, remove
4362    // OPTIMIZATION: feel pretty uneasy about this. It seems like once again
4363    // we need to sort and walk edges in y, but that on the surface opens the
4364    // same can of worms as before. But then, this is a rough sort based on
4365    // segments' top, and not a true sort, so it could be ameniable to regular
4366    // sorting instead of linear searching. Still feel like I'm missing something
4367    Segment* topSegment(SkScalar& bestY) {
4368        int segmentCount = fSegments.count();
4369        SkASSERT(segmentCount > 0);
4370        int best = -1;
4371        Segment* bestSegment = NULL;
4372        while (++best < segmentCount) {
4373            Segment* testSegment = &fSegments[best];
4374            if (testSegment->done()) {
4375                continue;
4376            }
4377            bestSegment = testSegment;
4378            break;
4379        }
4380        if (!bestSegment) {
4381            return NULL;
4382        }
4383        SkScalar bestTop = bestSegment->activeTop();
4384        for (int test = best + 1; test < segmentCount; ++test) {
4385            Segment* testSegment = &fSegments[test];
4386            if (testSegment->done()) {
4387                continue;
4388            }
4389            if (testSegment->bounds().fTop > bestTop) {
4390                continue;
4391            }
4392            SkScalar testTop = testSegment->activeTop();
4393            if (bestTop > testTop) {
4394                bestTop = testTop;
4395                bestSegment = testSegment;
4396            }
4397        }
4398        bestY = bestTop;
4399        return bestSegment;
4400    }
4401#endif
4402
4403    Segment* topSortableSegment(const SkPoint& topLeft, SkPoint& bestXY) {
4404        int segmentCount = fSortedSegments.count();
4405        SkASSERT(segmentCount > 0);
4406        Segment* bestSegment = NULL;
4407        int sortedIndex = fFirstSorted;
4408        for ( ; sortedIndex < segmentCount; ++sortedIndex) {
4409            Segment* testSegment = fSortedSegments[sortedIndex];
4410            if (testSegment->done()) {
4411                if (sortedIndex == fFirstSorted) {
4412                    ++fFirstSorted;
4413                }
4414                continue;
4415            }
4416            SkPoint testXY;
4417            testSegment->activeLeftTop(testXY);
4418            if (testXY.fY < topLeft.fY) {
4419                continue;
4420            }
4421            if (testXY.fY == topLeft.fY && testXY.fX <= topLeft.fX) {
4422                continue;
4423            }
4424            if (bestXY.fY < testXY.fY) {
4425                continue;
4426            }
4427            if (bestXY.fY == testXY.fY && bestXY.fX < testXY.fX) {
4428                continue;
4429            }
4430            bestSegment = testSegment;
4431            bestXY = testXY;
4432        }
4433        return bestSegment;
4434    }
4435
4436    Segment* undoneSegment(int& start, int& end) {
4437        int segmentCount = fSegments.count();
4438        for (int test = 0; test < segmentCount; ++test) {
4439            Segment* testSegment = &fSegments[test];
4440            if (testSegment->done()) {
4441                continue;
4442            }
4443            testSegment->undoneSpan(start, end);
4444            return testSegment;
4445        }
4446        return NULL;
4447    }
4448
4449    int updateSegment(int index, const SkPoint* pts) {
4450        Segment& segment = fSegments[index];
4451        segment.updatePts(pts);
4452        return segment.verb() + 1;
4453    }
4454
4455#if DEBUG_TEST
4456    SkTArray<Segment>& debugSegments() {
4457        return fSegments;
4458    }
4459#endif
4460
4461#if DEBUG_DUMP
4462    void dump() {
4463        int i;
4464        const char className[] = "Contour";
4465        const int tab = 4;
4466        SkDebugf("%s %p (contour=%d)\n", className, this, fID);
4467        for (i = 0; i < fSegments.count(); ++i) {
4468            SkDebugf("%*s.fSegments[%d]:\n", tab + sizeof(className),
4469                    className, i);
4470            fSegments[i].dump();
4471        }
4472        SkDebugf("%*s.fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)\n",
4473                tab + sizeof(className), className,
4474                fBounds.fLeft, fBounds.fTop,
4475                fBounds.fRight, fBounds.fBottom);
4476        SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className),
4477                className, fContainsIntercepts);
4478        SkDebugf("%*s.fContainsCurves=%d\n", tab + sizeof(className),
4479                className, fContainsCurves);
4480    }
4481#endif
4482
4483#if DEBUG_ACTIVE_SPANS
4484    void debugShowActiveSpans() {
4485        for (int index = 0; index < fSegments.count(); ++index) {
4486            fSegments[index].debugShowActiveSpans();
4487        }
4488    }
4489
4490    void validateActiveSpans() {
4491        for (int index = 0; index < fSegments.count(); ++index) {
4492            fSegments[index].validateActiveSpans();
4493        }
4494    }
4495#endif
4496
4497#if DEBUG_SHOW_WINDING
4498    int debugShowWindingValues(int totalSegments, int ofInterest) {
4499        int count = fSegments.count();
4500        int sum = 0;
4501        for (int index = 0; index < count; ++index) {
4502            sum += fSegments[index].debugShowWindingValues(totalSegments, ofInterest);
4503        }
4504  //      SkDebugf("%s sum=%d\n", __FUNCTION__, sum);
4505        return sum;
4506    }
4507
4508    static void debugShowWindingValues(SkTDArray<Contour*>& contourList) {
4509   //     int ofInterest = 1 << 1 | 1 << 5 | 1 << 9 | 1 << 13;
4510    //    int ofInterest = 1 << 4 | 1 << 8 | 1 << 12 | 1 << 16;
4511        int ofInterest = 1 << 5 | 1 << 8;
4512        int total = 0;
4513        int index;
4514        for (index = 0; index < contourList.count(); ++index) {
4515            total += contourList[index]->segments().count();
4516        }
4517        int sum = 0;
4518        for (index = 0; index < contourList.count(); ++index) {
4519            sum += contourList[index]->debugShowWindingValues(total, ofInterest);
4520        }
4521 //       SkDebugf("%s total=%d\n", __FUNCTION__, sum);
4522    }
4523#endif
4524
4525protected:
4526    void setBounds() {
4527        int count = fSegments.count();
4528        if (count == 0) {
4529            SkDebugf("%s empty contour\n", __FUNCTION__);
4530            SkASSERT(0);
4531            // FIXME: delete empty contour?
4532            return;
4533        }
4534        fBounds = fSegments.front().bounds();
4535        for (int index = 1; index < count; ++index) {
4536            fBounds.add(fSegments[index].bounds());
4537        }
4538    }
4539
4540private:
4541    SkTArray<Segment> fSegments;
4542    SkTDArray<Segment*> fSortedSegments;
4543    int fFirstSorted;
4544    SkTDArray<Coincidence> fCoincidences;
4545    SkTDArray<const Contour*> fCrosses;
4546    Bounds fBounds;
4547    bool fContainsIntercepts;
4548    bool fContainsCurves;
4549    bool fOperand; // true for the second argument to a binary operator
4550    bool fXor;
4551    bool fOppXor;
4552#if DEBUG_DUMP
4553    int fID;
4554#endif
4555};
4556
4557class EdgeBuilder {
4558public:
4559
4560EdgeBuilder(const PathWrapper& path, SkTArray<Contour>& contours)
4561    : fPath(path.nativePath())
4562    , fContours(contours)
4563{
4564    init();
4565}
4566
4567EdgeBuilder(const SkPath& path, SkTArray<Contour>& contours)
4568    : fPath(&path)
4569    , fContours(contours)
4570{
4571    init();
4572}
4573
4574void init() {
4575    fCurrentContour = NULL;
4576    fOperand = false;
4577    fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
4578#if DEBUG_DUMP
4579    gContourID = 0;
4580    gSegmentID = 0;
4581#endif
4582    fSecondHalf = preFetch();
4583}
4584
4585void addOperand(const SkPath& path) {
4586    SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
4587    fPathVerbs.pop();
4588    fPath = &path;
4589    fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
4590    preFetch();
4591}
4592
4593void finish() {
4594    walk();
4595    complete();
4596    if (fCurrentContour && !fCurrentContour->segments().count()) {
4597        fContours.pop_back();
4598    }
4599    // correct pointers in contours since fReducePts may have moved as it grew
4600    int cIndex = 0;
4601    int extraCount = fExtra.count();
4602    SkASSERT(extraCount == 0 || fExtra[0] == -1);
4603    int eIndex = 0;
4604    int rIndex = 0;
4605    while (++eIndex < extraCount) {
4606        int offset = fExtra[eIndex];
4607        if (offset < 0) {
4608            ++cIndex;
4609            continue;
4610        }
4611        fCurrentContour = &fContours[cIndex];
4612        rIndex += fCurrentContour->updateSegment(offset - 1,
4613                &fReducePts[rIndex]);
4614    }
4615    fExtra.reset(); // we're done with this
4616}
4617
4618ShapeOpMask xorMask() const {
4619    return fXorMask[fOperand];
4620}
4621
4622protected:
4623
4624void complete() {
4625    if (fCurrentContour && fCurrentContour->segments().count()) {
4626        fCurrentContour->complete();
4627        fCurrentContour = NULL;
4628    }
4629}
4630
4631// FIXME:remove once we can access path pts directly
4632int preFetch() {
4633    SkPath::RawIter iter(*fPath); // FIXME: access path directly when allowed
4634    SkPoint pts[4];
4635    SkPath::Verb verb;
4636    do {
4637        verb = iter.next(pts);
4638        *fPathVerbs.append() = verb;
4639        if (verb == SkPath::kMove_Verb) {
4640            *fPathPts.append() = pts[0];
4641        } else if (verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
4642            fPathPts.append(verb, &pts[1]);
4643        }
4644    } while (verb != SkPath::kDone_Verb);
4645    return fPathVerbs.count() - 1;
4646}
4647
4648void walk() {
4649    SkPath::Verb reducedVerb;
4650    uint8_t* verbPtr = fPathVerbs.begin();
4651    uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
4652    const SkPoint* pointsPtr = fPathPts.begin();
4653    const SkPoint* finalCurveStart = NULL;
4654    const SkPoint* finalCurveEnd = NULL;
4655    SkPath::Verb verb;
4656    while ((verb = (SkPath::Verb) *verbPtr++) != SkPath::kDone_Verb) {
4657        switch (verb) {
4658            case SkPath::kMove_Verb:
4659                complete();
4660                if (!fCurrentContour) {
4661                    fCurrentContour = fContours.push_back_n(1);
4662                    fCurrentContour->setOperand(fOperand);
4663                    fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_Mask);
4664                    *fExtra.append() = -1; // start new contour
4665                }
4666                finalCurveEnd = pointsPtr++;
4667                goto nextVerb;
4668            case SkPath::kLine_Verb:
4669                // skip degenerate points
4670                if (pointsPtr[-1].fX != pointsPtr[0].fX
4671                        || pointsPtr[-1].fY != pointsPtr[0].fY) {
4672                    fCurrentContour->addLine(&pointsPtr[-1]);
4673                }
4674                break;
4675            case SkPath::kQuad_Verb:
4676
4677                reducedVerb = QuadReduceOrder(&pointsPtr[-1], fReducePts);
4678                if (reducedVerb == 0) {
4679                    break; // skip degenerate points
4680                }
4681                if (reducedVerb == 1) {
4682                    *fExtra.append() =
4683                            fCurrentContour->addLine(fReducePts.end() - 2);
4684                    break;
4685                }
4686                fCurrentContour->addQuad(&pointsPtr[-1]);
4687                break;
4688            case SkPath::kCubic_Verb:
4689                reducedVerb = CubicReduceOrder(&pointsPtr[-1], fReducePts);
4690                if (reducedVerb == 0) {
4691                    break; // skip degenerate points
4692                }
4693                if (reducedVerb == 1) {
4694                    *fExtra.append() =
4695                            fCurrentContour->addLine(fReducePts.end() - 2);
4696                    break;
4697                }
4698                if (reducedVerb == 2) {
4699                    *fExtra.append() =
4700                            fCurrentContour->addQuad(fReducePts.end() - 3);
4701                    break;
4702                }
4703                fCurrentContour->addCubic(&pointsPtr[-1]);
4704                break;
4705            case SkPath::kClose_Verb:
4706                SkASSERT(fCurrentContour);
4707                if (finalCurveStart && finalCurveEnd
4708                        && *finalCurveStart != *finalCurveEnd) {
4709                    *fReducePts.append() = *finalCurveStart;
4710                    *fReducePts.append() = *finalCurveEnd;
4711                    *fExtra.append() =
4712                            fCurrentContour->addLine(fReducePts.end() - 2);
4713                }
4714                complete();
4715                goto nextVerb;
4716            default:
4717                SkDEBUGFAIL("bad verb");
4718                return;
4719        }
4720        finalCurveStart = &pointsPtr[verb - 1];
4721        pointsPtr += verb;
4722        SkASSERT(fCurrentContour);
4723    nextVerb:
4724        if (verbPtr == endOfFirstHalf) {
4725            fOperand = true;
4726        }
4727    }
4728}
4729
4730private:
4731    const SkPath* fPath;
4732    SkTDArray<SkPoint> fPathPts; // FIXME: point directly to path pts instead
4733    SkTDArray<uint8_t> fPathVerbs; // FIXME: remove
4734    Contour* fCurrentContour;
4735    SkTArray<Contour>& fContours;
4736    SkTDArray<SkPoint> fReducePts; // segments created on the fly
4737    SkTDArray<int> fExtra; // -1 marks new contour, > 0 offsets into contour
4738    ShapeOpMask fXorMask[2];
4739    int fSecondHalf;
4740    bool fOperand;
4741};
4742
4743class Work {
4744public:
4745    enum SegmentType {
4746        kHorizontalLine_Segment = -1,
4747        kVerticalLine_Segment = 0,
4748        kLine_Segment = SkPath::kLine_Verb,
4749        kQuad_Segment = SkPath::kQuad_Verb,
4750        kCubic_Segment = SkPath::kCubic_Verb,
4751    };
4752
4753    void addCoincident(Work& other, const Intersections& ts, bool swap) {
4754        fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
4755    }
4756
4757    // FIXME: does it make sense to write otherIndex now if we're going to
4758    // fix it up later?
4759    void addOtherT(int index, double otherT, int otherIndex) {
4760        fContour->addOtherT(fIndex, index, otherT, otherIndex);
4761    }
4762
4763    // Avoid collapsing t values that are close to the same since
4764    // we walk ts to describe consecutive intersections. Since a pair of ts can
4765    // be nearly equal, any problems caused by this should be taken care
4766    // of later.
4767    // On the edge or out of range values are negative; add 2 to get end
4768    int addT(double newT, const Work& other) {
4769        return fContour->addT(fIndex, newT, other.fContour, other.fIndex);
4770    }
4771
4772    bool advance() {
4773        return ++fIndex < fLast;
4774    }
4775
4776    SkScalar bottom() const {
4777        return bounds().fBottom;
4778    }
4779
4780    const Bounds& bounds() const {
4781        return fContour->segments()[fIndex].bounds();
4782    }
4783
4784    const SkPoint* cubic() const {
4785        return fCubic;
4786    }
4787
4788    void init(Contour* contour) {
4789        fContour = contour;
4790        fIndex = 0;
4791        fLast = contour->segments().count();
4792    }
4793
4794    bool isAdjacent(const Work& next) {
4795        return fContour == next.fContour && fIndex + 1 == next.fIndex;
4796    }
4797
4798    bool isFirstLast(const Work& next) {
4799        return fContour == next.fContour && fIndex == 0
4800                && next.fIndex == fLast - 1;
4801    }
4802
4803    SkScalar left() const {
4804        return bounds().fLeft;
4805    }
4806
4807    void promoteToCubic() {
4808        fCubic[0] = pts()[0];
4809        fCubic[2] = pts()[1];
4810        fCubic[3] = pts()[2];
4811        fCubic[1].fX = (fCubic[0].fX + fCubic[2].fX * 2) / 3;
4812        fCubic[1].fY = (fCubic[0].fY + fCubic[2].fY * 2) / 3;
4813        fCubic[2].fX = (fCubic[3].fX + fCubic[2].fX * 2) / 3;
4814        fCubic[2].fY = (fCubic[3].fY + fCubic[2].fY * 2) / 3;
4815    }
4816
4817    const SkPoint* pts() const {
4818        return fContour->segments()[fIndex].pts();
4819    }
4820
4821    SkScalar right() const {
4822        return bounds().fRight;
4823    }
4824
4825    ptrdiff_t segmentIndex() const {
4826        return fIndex;
4827    }
4828
4829    SegmentType segmentType() const {
4830        const Segment& segment = fContour->segments()[fIndex];
4831        SegmentType type = (SegmentType) segment.verb();
4832        if (type != kLine_Segment) {
4833            return type;
4834        }
4835        if (segment.isHorizontal()) {
4836            return kHorizontalLine_Segment;
4837        }
4838        if (segment.isVertical()) {
4839            return kVerticalLine_Segment;
4840        }
4841        return kLine_Segment;
4842    }
4843
4844    bool startAfter(const Work& after) {
4845        fIndex = after.fIndex;
4846        return advance();
4847    }
4848
4849    SkScalar top() const {
4850        return bounds().fTop;
4851    }
4852
4853    SkPath::Verb verb() const {
4854        return fContour->segments()[fIndex].verb();
4855    }
4856
4857    SkScalar x() const {
4858        return bounds().fLeft;
4859    }
4860
4861    bool xFlipped() const {
4862        return x() != pts()[0].fX;
4863    }
4864
4865    SkScalar y() const {
4866        return bounds().fTop;
4867    }
4868
4869    bool yFlipped() const {
4870        return y() != pts()[0].fY;
4871    }
4872
4873protected:
4874    Contour* fContour;
4875    SkPoint fCubic[4];
4876    int fIndex;
4877    int fLast;
4878};
4879
4880#if DEBUG_ADD_INTERSECTING_TS
4881static void debugShowLineIntersection(int pts, const Work& wt,
4882        const Work& wn, const double wtTs[2], const double wnTs[2]) {
4883    return;
4884    if (!pts) {
4885        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g %1.9g,%1.9g)\n",
4886                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
4887                wt.pts()[1].fX, wt.pts()[1].fY, wn.pts()[0].fX, wn.pts()[0].fY,
4888                wn.pts()[1].fX, wn.pts()[1].fY);
4889        return;
4890    }
4891    SkPoint wtOutPt, wnOutPt;
4892    LineXYAtT(wt.pts(), wtTs[0], &wtOutPt);
4893    LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
4894    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4895            __FUNCTION__,
4896            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
4897            wt.pts()[1].fX, wt.pts()[1].fY, wtOutPt.fX, wtOutPt.fY);
4898    if (pts == 2) {
4899        SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
4900    }
4901    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4902            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
4903            wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
4904    if (pts == 2) {
4905        SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
4906    }
4907    SkDebugf("\n");
4908}
4909
4910static void debugShowQuadLineIntersection(int pts, const Work& wt,
4911        const Work& wn, const double wtTs[2], const double wnTs[2]) {
4912    if (!pts) {
4913        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
4914                " (%1.9g,%1.9g %1.9g,%1.9g)\n",
4915                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
4916                wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
4917                wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY);
4918        return;
4919    }
4920    SkPoint wtOutPt, wnOutPt;
4921    QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
4922    LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
4923    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4924            __FUNCTION__,
4925            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
4926            wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
4927            wtOutPt.fX, wtOutPt.fY);
4928    if (pts == 2) {
4929        QuadXYAtT(wt.pts(), wtTs[1], &wtOutPt);
4930        SkDebugf(" wtTs[1]=%1.9g (%1.9g,%1.9g)", wtTs[1], wtOutPt.fX, wtOutPt.fY);
4931    }
4932    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4933            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
4934            wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
4935    if (pts == 2) {
4936        LineXYAtT(wn.pts(), wnTs[1], &wnOutPt);
4937        SkDebugf(" wnTs[1]=%1.9g (%1.9g,%1.9g)", wnTs[1], wnOutPt.fX, wnOutPt.fY);
4938    }
4939    SkDebugf("\n");
4940}
4941
4942static void debugShowQuadIntersection(int pts, const Work& wt,
4943        const Work& wn, const double wtTs[2], const double wnTs[2]) {
4944    if (!pts) {
4945        SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
4946                " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n",
4947                __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY,
4948                wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
4949                wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY,
4950                wn.pts()[2].fX, wn.pts()[2].fY );
4951        return;
4952    }
4953    SkPoint wtOutPt, wnOutPt;
4954    QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
4955    QuadXYAtT(wn.pts(), wnTs[0], &wnOutPt);
4956    SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4957            __FUNCTION__,
4958            wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
4959            wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY,
4960            wtOutPt.fX, wtOutPt.fY);
4961    if (pts == 2) {
4962        SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
4963    }
4964    SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
4965            wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
4966            wn.pts()[1].fX, wn.pts()[1].fY, wn.pts()[2].fX, wn.pts()[2].fY,
4967            wnOutPt.fX, wnOutPt.fY);
4968    if (pts == 2) {
4969        SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
4970    }
4971    SkDebugf("\n");
4972}
4973#else
4974static void debugShowLineIntersection(int , const Work& ,
4975        const Work& , const double [2], const double [2]) {
4976}
4977
4978static void debugShowQuadLineIntersection(int , const Work& ,
4979        const Work& , const double [2], const double [2]) {
4980}
4981
4982static void debugShowQuadIntersection(int , const Work& ,
4983        const Work& , const double [2], const double [2]) {
4984}
4985#endif
4986
4987static bool addIntersectTs(Contour* test, Contour* next) {
4988
4989    if (test != next) {
4990        if (test->bounds().fBottom < next->bounds().fTop) {
4991            return false;
4992        }
4993        if (!Bounds::Intersects(test->bounds(), next->bounds())) {
4994            return true;
4995        }
4996    }
4997    Work wt;
4998    wt.init(test);
4999    bool foundCommonContour = test == next;
5000    do {
5001        Work wn;
5002        wn.init(next);
5003        if (test == next && !wn.startAfter(wt)) {
5004            continue;
5005        }
5006        do {
5007            if (!Bounds::Intersects(wt.bounds(), wn.bounds())) {
5008                continue;
5009            }
5010            int pts;
5011            Intersections ts;
5012            bool swap = false;
5013            switch (wt.segmentType()) {
5014                case Work::kHorizontalLine_Segment:
5015                    swap = true;
5016                    switch (wn.segmentType()) {
5017                        case Work::kHorizontalLine_Segment:
5018                        case Work::kVerticalLine_Segment:
5019                        case Work::kLine_Segment: {
5020                            pts = HLineIntersect(wn.pts(), wt.left(),
5021                                    wt.right(), wt.y(), wt.xFlipped(), ts);
5022                            debugShowLineIntersection(pts, wt, wn,
5023                                    ts.fT[1], ts.fT[0]);
5024                            break;
5025                        }
5026                        case Work::kQuad_Segment: {
5027                            pts = HQuadIntersect(wn.pts(), wt.left(),
5028                                    wt.right(), wt.y(), wt.xFlipped(), ts);
5029                            break;
5030                        }
5031                        case Work::kCubic_Segment: {
5032                            pts = HCubicIntersect(wn.pts(), wt.left(),
5033                                    wt.right(), wt.y(), wt.xFlipped(), ts);
5034                            break;
5035                        }
5036                        default:
5037                            SkASSERT(0);
5038                    }
5039                    break;
5040                case Work::kVerticalLine_Segment:
5041                    swap = true;
5042                    switch (wn.segmentType()) {
5043                        case Work::kHorizontalLine_Segment:
5044                        case Work::kVerticalLine_Segment:
5045                        case Work::kLine_Segment: {
5046                            pts = VLineIntersect(wn.pts(), wt.top(),
5047                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
5048                            debugShowLineIntersection(pts, wt, wn,
5049                                    ts.fT[1], ts.fT[0]);
5050                            break;
5051                        }
5052                        case Work::kQuad_Segment: {
5053                            pts = VQuadIntersect(wn.pts(), wt.top(),
5054                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
5055                            break;
5056                        }
5057                        case Work::kCubic_Segment: {
5058                            pts = VCubicIntersect(wn.pts(), wt.top(),
5059                                    wt.bottom(), wt.x(), wt.yFlipped(), ts);
5060                            break;
5061                        }
5062                        default:
5063                            SkASSERT(0);
5064                    }
5065                    break;
5066                case Work::kLine_Segment:
5067                    switch (wn.segmentType()) {
5068                        case Work::kHorizontalLine_Segment:
5069                            pts = HLineIntersect(wt.pts(), wn.left(),
5070                                    wn.right(), wn.y(), wn.xFlipped(), ts);
5071                            debugShowLineIntersection(pts, wt, wn,
5072                                    ts.fT[1], ts.fT[0]);
5073                            break;
5074                        case Work::kVerticalLine_Segment:
5075                            pts = VLineIntersect(wt.pts(), wn.top(),
5076                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
5077                            debugShowLineIntersection(pts, wt, wn,
5078                                    ts.fT[1], ts.fT[0]);
5079                            break;
5080                        case Work::kLine_Segment: {
5081                            pts = LineIntersect(wt.pts(), wn.pts(), ts);
5082                            debugShowLineIntersection(pts, wt, wn,
5083                                    ts.fT[1], ts.fT[0]);
5084                            break;
5085                        }
5086                        case Work::kQuad_Segment: {
5087                            swap = true;
5088                            pts = QuadLineIntersect(wn.pts(), wt.pts(), ts);
5089                            debugShowQuadLineIntersection(pts, wn, wt,
5090                                    ts.fT[0], ts.fT[1]);
5091                            break;
5092                        }
5093                        case Work::kCubic_Segment: {
5094                            swap = true;
5095                            pts = CubicLineIntersect(wn.pts(), wt.pts(), ts);
5096                            break;
5097                        }
5098                        default:
5099                            SkASSERT(0);
5100                    }
5101                    break;
5102                case Work::kQuad_Segment:
5103                    switch (wn.segmentType()) {
5104                        case Work::kHorizontalLine_Segment:
5105                            pts = HQuadIntersect(wt.pts(), wn.left(),
5106                                    wn.right(), wn.y(), wn.xFlipped(), ts);
5107                            break;
5108                        case Work::kVerticalLine_Segment:
5109                            pts = VQuadIntersect(wt.pts(), wn.top(),
5110                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
5111                            break;
5112                        case Work::kLine_Segment: {
5113                            pts = QuadLineIntersect(wt.pts(), wn.pts(), ts);
5114                            debugShowQuadLineIntersection(pts, wt, wn,
5115                                    ts.fT[0], ts.fT[1]);
5116                            break;
5117                        }
5118                        case Work::kQuad_Segment: {
5119                            pts = QuadIntersect(wt.pts(), wn.pts(), ts);
5120                            debugShowQuadIntersection(pts, wt, wn,
5121                                    ts.fT[0], ts.fT[1]);
5122                            break;
5123                        }
5124                        case Work::kCubic_Segment: {
5125                            wt.promoteToCubic();
5126                            pts = CubicIntersect(wt.cubic(), wn.pts(), ts);
5127                            break;
5128                        }
5129                        default:
5130                            SkASSERT(0);
5131                    }
5132                    break;
5133                case Work::kCubic_Segment:
5134                    switch (wn.segmentType()) {
5135                        case Work::kHorizontalLine_Segment:
5136                            pts = HCubicIntersect(wt.pts(), wn.left(),
5137                                    wn.right(), wn.y(), wn.xFlipped(), ts);
5138                            break;
5139                        case Work::kVerticalLine_Segment:
5140                            pts = VCubicIntersect(wt.pts(), wn.top(),
5141                                    wn.bottom(), wn.x(), wn.yFlipped(), ts);
5142                            break;
5143                        case Work::kLine_Segment: {
5144                            pts = CubicLineIntersect(wt.pts(), wn.pts(), ts);
5145                            break;
5146                        }
5147                        case Work::kQuad_Segment: {
5148                            wn.promoteToCubic();
5149                            pts = CubicIntersect(wt.pts(), wn.cubic(), ts);
5150                            break;
5151                        }
5152                        case Work::kCubic_Segment: {
5153                            pts = CubicIntersect(wt.pts(), wn.pts(), ts);
5154                            break;
5155                        }
5156                        default:
5157                            SkASSERT(0);
5158                    }
5159                    break;
5160                default:
5161                    SkASSERT(0);
5162            }
5163            if (!foundCommonContour && pts > 0) {
5164                test->addCross(next);
5165                next->addCross(test);
5166                foundCommonContour = true;
5167            }
5168            // in addition to recording T values, record matching segment
5169            if (pts == 2) {
5170                if (wn.segmentType() <= Work::kLine_Segment
5171                        && wt.segmentType() <= Work::kLine_Segment) {
5172                    wt.addCoincident(wn, ts, swap);
5173                    continue;
5174                }
5175                if (wn.segmentType() == Work::kQuad_Segment
5176                        && wt.segmentType() == Work::kQuad_Segment
5177                        && ts.coincidentUsed() == 2) {
5178                    wt.addCoincident(wn, ts, swap);
5179                    continue;
5180                }
5181
5182            }
5183            for (int pt = 0; pt < pts; ++pt) {
5184                SkASSERT(ts.fT[0][pt] >= 0 && ts.fT[0][pt] <= 1);
5185                SkASSERT(ts.fT[1][pt] >= 0 && ts.fT[1][pt] <= 1);
5186                int testTAt = wt.addT(ts.fT[swap][pt], wn);
5187                int nextTAt = wn.addT(ts.fT[!swap][pt], wt);
5188                wt.addOtherT(testTAt, ts.fT[!swap][pt ^ ts.fFlip], nextTAt);
5189                wn.addOtherT(nextTAt, ts.fT[swap][pt ^ ts.fFlip], testTAt);
5190            }
5191        } while (wn.advance());
5192    } while (wt.advance());
5193    return true;
5194}
5195
5196// resolve any coincident pairs found while intersecting, and
5197// see if coincidence is formed by clipping non-concident segments
5198static void coincidenceCheck(SkTDArray<Contour*>& contourList, int total) {
5199    int contourCount = contourList.count();
5200    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
5201        Contour* contour = contourList[cIndex];
5202        contour->resolveCoincidence(contourList);
5203    }
5204    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
5205        Contour* contour = contourList[cIndex];
5206        contour->findTooCloseToCall();
5207    }
5208}
5209
5210static int contourRangeCheckX(SkTDArray<Contour*>& contourList, double mid,
5211        const Segment* current, int index, int endIndex, bool opp) {
5212    const SkPoint& basePt = current->xyAtT(endIndex);
5213    int contourCount = contourList.count();
5214    SkScalar bestX = SK_ScalarMin;
5215    const Segment* test = NULL;
5216    int tIndex;
5217    double tHit;
5218    bool crossOpp;
5219    for (int cTest = 0; cTest < contourCount; ++cTest) {
5220        Contour* contour = contourList[cTest];
5221        bool testOpp = contour->operand() ^ current->operand() ^ opp;
5222        if (basePt.fX < contour->bounds().fLeft) {
5223            continue;
5224        }
5225        if (bestX > contour->bounds().fRight) {
5226            continue;
5227        }
5228        const Segment* next = contour->crossedSegmentX(basePt, bestX, tIndex, tHit, testOpp);
5229        if (next) {
5230            test = next;
5231            crossOpp = testOpp;
5232        }
5233    }
5234    if (!test) {
5235        return 0;
5236    }
5237    return test->windingAtT(tHit, tIndex, crossOpp);
5238}
5239
5240static int contourRangeCheckY(SkTDArray<Contour*>& contourList, double mid,
5241        const Segment* current, int index, int endIndex, bool opp) {
5242    const SkPoint& basePt = current->xyAtT(endIndex);
5243    int contourCount = contourList.count();
5244    SkScalar bestY = SK_ScalarMin;
5245    const Segment* test = NULL;
5246    int tIndex;
5247    double tHit;
5248    bool crossOpp;
5249    for (int cTest = 0; cTest < contourCount; ++cTest) {
5250        Contour* contour = contourList[cTest];
5251        bool testOpp = contour->operand() ^ current->operand() ^ opp;
5252        if (basePt.fY < contour->bounds().fTop) {
5253            continue;
5254        }
5255        if (bestY > contour->bounds().fBottom) {
5256            continue;
5257        }
5258        const Segment* next = contour->crossedSegmentY(basePt, bestY, tIndex, tHit, testOpp);
5259        if (next) {
5260            test = next;
5261            crossOpp = testOpp;
5262        }
5263    }
5264    if (!test) {
5265        return 0;
5266    }
5267    return test->windingAtT(tHit, tIndex, crossOpp);
5268}
5269
5270// project a ray from the top of the contour up and see if it hits anything
5271// note: when we compute line intersections, we keep track of whether
5272// two contours touch, so we need only look at contours not touching this one.
5273// OPTIMIZATION: sort contourList vertically to avoid linear walk
5274static int innerContourCheck(SkTDArray<Contour*>& contourList,
5275        const Segment* current, int index, int endIndex, bool opp) {
5276    const SkPoint& basePt = current->xyAtT(endIndex);
5277    int contourCount = contourList.count();
5278    SkScalar bestY = SK_ScalarMin;
5279    const Segment* test = NULL;
5280    int tIndex;
5281    double tHit;
5282    bool crossOpp;
5283    for (int cTest = 0; cTest < contourCount; ++cTest) {
5284        Contour* contour = contourList[cTest];
5285        bool testOpp = contour->operand() ^ current->operand() ^ opp;
5286        if (basePt.fY < contour->bounds().fTop) {
5287            continue;
5288        }
5289        if (bestY > contour->bounds().fBottom) {
5290            continue;
5291        }
5292        const Segment* next = contour->crossedSegmentY(basePt, bestY, tIndex, tHit, testOpp);
5293        if (next) {
5294            test = next;
5295            crossOpp = testOpp;
5296        }
5297    }
5298    if (!test) {
5299        return 0;
5300    }
5301    int winding, windValue;
5302    // If the ray hit the end of a span, we need to construct the wheel of
5303    // angles to find the span closest to the ray -- even if there are just
5304    // two spokes on the wheel.
5305    const Angle* angle = NULL;
5306    if (approximately_zero(tHit - test->t(tIndex))) {
5307        SkTDArray<Angle> angles;
5308        int end = test->nextSpan(tIndex, 1);
5309        if (end < 0) {
5310            end = test->nextSpan(tIndex, -1);
5311        }
5312        test->addTwoAngles(end, tIndex, angles);
5313        SkASSERT(angles.count() > 0);
5314        if (angles[0].segment()->yAtT(angles[0].start()) >= basePt.fY) {
5315#if DEBUG_SORT
5316            SkDebugf("%s early return\n", __FUNCTION__);
5317#endif
5318            return SK_MinS32;
5319        }
5320        test->buildAngles(tIndex, angles, false);
5321        SkTDArray<Angle*> sorted;
5322        // OPTIMIZATION: call a sort that, if base point is the leftmost,
5323        // returns the first counterclockwise hour before 6 o'clock,
5324        // or if the base point is rightmost, returns the first clockwise
5325        // hour after 6 o'clock
5326        bool sortable = Segment::SortAngles(angles, sorted);
5327        if (!sortable) {
5328            return SK_MinS32;
5329        }
5330#if DEBUG_SORT
5331        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
5332#endif
5333        // walk the sorted angle fan to find the lowest angle
5334        // above the base point. Currently, the first angle in the sorted array
5335        // is 12 noon or an earlier hour (the next counterclockwise)
5336        int count = sorted.count();
5337        int left = -1;
5338        int mid = -1;
5339        int right = -1;
5340        bool baseMatches = test->yAtT(tIndex) == basePt.fY;
5341        for (int index = 0; index < count; ++index) {
5342            angle = sorted[index];
5343            if (angle->unsortable()) {
5344                continue;
5345            }
5346            if (baseMatches && angle->isHorizontal()) {
5347                continue;
5348            }
5349            double indexDx = angle->dx();
5350            test = angle->segment();
5351            if (test->verb() > SkPath::kLine_Verb && approximately_zero(indexDx)) {
5352                const SkPoint* pts = test->pts();
5353                indexDx = pts[2].fX - pts[1].fX - indexDx;
5354            }
5355            if (indexDx < 0) {
5356                left = index;
5357            } else if (indexDx > 0) {
5358                right = index;
5359                int previous = index - 1;
5360                if (previous < 0) {
5361                    previous = count - 1;
5362                }
5363                const Angle* prev = sorted[previous];
5364                if (prev->dy() >= 0 && prev->dx() > 0 && angle->dy() < 0) {
5365#if DEBUG_SORT
5366                    SkDebugf("%s use prev\n", __FUNCTION__);
5367#endif
5368                    right = previous;
5369                }
5370                break;
5371            } else {
5372                mid = index;
5373            }
5374        }
5375        if ((left < 0 || right < 0) && mid >= 0) {
5376            angle = sorted[mid];
5377            Segment* midSeg = angle->segment();
5378            int end = angle->end();
5379            if (midSeg->unsortable(end)) {
5380                return SK_MinS32;
5381            }
5382        }
5383        if (left < 0 && right < 0) {
5384            left = mid;
5385        }
5386        if (left < 0 && right < 0) {
5387            SkASSERT(0);
5388            return SK_MinS32; // unsortable
5389        }
5390        if (left < 0) {
5391            left = right;
5392        } else if (left >= 0 && mid >= 0 && right >= 0
5393                && sorted[mid]->sign() == sorted[right]->sign()) {
5394            left = right;
5395        }
5396        angle = sorted[left];
5397        test = angle->segment();
5398        winding = crossOpp ? test->oppSum(angle) : test->windSum(angle);
5399        SkASSERT(winding != SK_MinS32);
5400        windValue = crossOpp ? test->oppValue(angle) : test->windValue(angle);
5401#if DEBUG_WINDING
5402        SkDebugf("%s angle winding=%d windValue=%d sign=%d\n", __FUNCTION__, winding,
5403                windValue, angle->sign());
5404#endif
5405    } else {
5406        winding = crossOpp ? test->oppSum(tIndex) : test->windSum(tIndex);
5407        if (winding == SK_MinS32) {
5408            return SK_MinS32; // unsortable
5409        }
5410        windValue = crossOpp ? test->oppValue(tIndex) : test->windValue(tIndex);
5411#if DEBUG_WINDING
5412        SkDebugf("%s single winding=%d windValue=%d\n", __FUNCTION__, winding,
5413                windValue);
5414#endif
5415    }
5416    // see if a + change in T results in a +/- change in X (compute x'(T))
5417    SkScalar dx = (*SegmentDXAtT[test->verb()])(test->pts(), tHit);
5418    if (test->verb() > SkPath::kLine_Verb && approximately_zero(dx)) {
5419        const SkPoint* pts = test->pts();
5420        dx = pts[2].fX - pts[1].fX - dx;
5421    }
5422#if DEBUG_WINDING
5423    SkDebugf("%s dx=%1.9g\n", __FUNCTION__, dx);
5424#endif
5425    SkASSERT(dx != 0);
5426    if (winding * dx > 0) { // if same signs, result is negative
5427        winding += dx > 0 ? -windValue : windValue;
5428#if DEBUG_WINDING
5429        SkDebugf("%s final winding=%d\n", __FUNCTION__, winding);
5430#endif
5431    }
5432    return winding;
5433}
5434
5435static Segment* findUndone(SkTDArray<Contour*>& contourList, int& start, int& end) {
5436    int contourCount = contourList.count();
5437    Segment* result;
5438    for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
5439        Contour* contour = contourList[cIndex];
5440        result = contour->undoneSegment(start, end);
5441        if (result) {
5442            return result;
5443        }
5444    }
5445    return NULL;
5446}
5447
5448
5449
5450static Segment* findChase(SkTDArray<Span*>& chase, int& tIndex, int& endIndex) {
5451    while (chase.count()) {
5452        Span* span;
5453        chase.pop(&span);
5454        const Span& backPtr = span->fOther->span(span->fOtherIndex);
5455        Segment* segment = backPtr.fOther;
5456        tIndex = backPtr.fOtherIndex;
5457        SkTDArray<Angle> angles;
5458        int done = 0;
5459        if (segment->activeAngle(tIndex, done, angles)) {
5460            Angle* last = angles.end() - 1;
5461            tIndex = last->start();
5462            endIndex = last->end();
5463   #if TRY_ROTATE
5464            *chase.insert(0) = span;
5465   #else
5466            *chase.append() = span;
5467   #endif
5468            return last->segment();
5469        }
5470        if (done == angles.count()) {
5471            continue;
5472        }
5473        SkTDArray<Angle*> sorted;
5474        bool sortable = Segment::SortAngles(angles, sorted);
5475#if DEBUG_SORT
5476        sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
5477#endif
5478        if (!sortable) {
5479            continue;
5480        }
5481        // find first angle, initialize winding to computed fWindSum
5482        int firstIndex = -1;
5483        const Angle* angle;
5484        int winding;
5485        do {
5486            angle = sorted[++firstIndex];
5487            segment = angle->segment();
5488            winding = segment->windSum(angle);
5489        } while (winding == SK_MinS32);
5490        int spanWinding = segment->spanSign(angle->start(), angle->end());
5491    #if DEBUG_WINDING
5492        SkDebugf("%s winding=%d spanWinding=%d\n",
5493                __FUNCTION__, winding, spanWinding);
5494    #endif
5495        // turn span winding into contour winding
5496        if (spanWinding * winding < 0) {
5497            winding += spanWinding;
5498        }
5499    #if DEBUG_SORT
5500        segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0);
5501    #endif
5502        // we care about first sign and whether wind sum indicates this
5503        // edge is inside or outside. Maybe need to pass span winding
5504        // or first winding or something into this function?
5505        // advance to first undone angle, then return it and winding
5506        // (to set whether edges are active or not)
5507        int nextIndex = firstIndex + 1;
5508        int angleCount = sorted.count();
5509        int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
5510        angle = sorted[firstIndex];
5511        winding -= angle->segment()->spanSign(angle);
5512        do {
5513            SkASSERT(nextIndex != firstIndex);
5514            if (nextIndex == angleCount) {
5515                nextIndex = 0;
5516            }
5517            angle = sorted[nextIndex];
5518            segment = angle->segment();
5519            int maxWinding = winding;
5520            winding -= segment->spanSign(angle);
5521    #if DEBUG_SORT
5522            SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
5523                    segment->debugID(), maxWinding, winding, angle->sign());
5524    #endif
5525            tIndex = angle->start();
5526            endIndex = angle->end();
5527            int lesser = SkMin32(tIndex, endIndex);
5528            const Span& nextSpan = segment->span(lesser);
5529            if (!nextSpan.fDone) {
5530#if 1
5531            // FIXME: this be wrong. assign startWinding if edge is in
5532            // same direction. If the direction is opposite, winding to
5533            // assign is flipped sign or +/- 1?
5534                if (useInnerWinding(maxWinding, winding)) {
5535                    maxWinding = winding;
5536                }
5537                segment->markWinding(lesser, maxWinding);
5538#endif
5539                break;
5540            }
5541        } while (++nextIndex != lastIndex);
5542   #if TRY_ROTATE
5543        *chase.insert(0) = span;
5544   #else
5545        *chase.append() = span;
5546   #endif
5547        return segment;
5548    }
5549    return NULL;
5550}
5551
5552#if DEBUG_ACTIVE_SPANS
5553static void debugShowActiveSpans(SkTDArray<Contour*>& contourList) {
5554    int index;
5555    for (index = 0; index < contourList.count(); ++ index) {
5556        contourList[index]->debugShowActiveSpans();
5557    }
5558    for (index = 0; index < contourList.count(); ++ index) {
5559        contourList[index]->validateActiveSpans();
5560    }
5561}
5562#endif
5563
5564static bool windingIsActive(int winding, int spanWinding) {
5565    // FIXME: !spanWinding test must be superflorous, true?
5566    return winding * spanWinding <= 0 && abs(winding) <= abs(spanWinding)
5567            && (!winding || !spanWinding || winding == -spanWinding);
5568}
5569
5570static Segment* findSortableTop(SkTDArray<Contour*>& contourList, int& index,
5571        int& endIndex, SkPoint& topLeft, bool& unsortable, bool onlySortable) {
5572    Segment* result;
5573    do {
5574        SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
5575        int contourCount = contourList.count();
5576        Segment* topStart = NULL;
5577        for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
5578            Contour* contour = contourList[cIndex];
5579            const Bounds& bounds = contour->bounds();
5580            if (bounds.fBottom < topLeft.fY) {
5581                continue;
5582            }
5583            if (bounds.fBottom == topLeft.fY && bounds.fRight < topLeft.fX) {
5584                continue;
5585            }
5586            Segment* test = contour->topSortableSegment(topLeft, bestXY);
5587            if (test) {
5588                topStart = test;
5589            }
5590        }
5591        if (!topStart) {
5592            return NULL;
5593        }
5594        topLeft = bestXY;
5595        result = topStart->findTop(index, endIndex, unsortable, onlySortable);
5596    } while (!result);
5597    return result;
5598}
5599
5600static int updateWindings(const Segment* current, int index, int endIndex, int& spanWinding) {
5601    int lesser = SkMin32(index, endIndex);
5602    spanWinding = current->spanSign(index, endIndex);
5603    int winding = current->windSum(lesser);
5604    bool inner = useInnerWinding(winding - spanWinding, winding);
5605#if DEBUG_WINDING
5606    SkDebugf("%s id=%d t=%1.9g spanWinding=%d winding=%d sign=%d"
5607            " inner=%d result=%d\n",
5608            __FUNCTION__, current->debugID(), current->t(lesser),
5609            spanWinding, winding, SkSign32(index - endIndex),
5610            useInnerWinding(winding - spanWinding, winding),
5611            inner ? winding - spanWinding : winding);
5612#endif
5613    if (inner) {
5614        winding -= spanWinding;
5615    }
5616    return winding;
5617}
5618
5619typedef int (*RangeChecker)(SkTDArray<Contour*>& contourList, double mid,
5620        const Segment* current, int index, int endIndex, bool opp);
5621
5622static int rightAngleWinding(RangeChecker rangeChecker, SkTDArray<Contour*>& contourList,
5623        Segment* current, int index, int endIndex, bool opp) {
5624    double test = 0.9;
5625    int contourWinding;
5626    do {
5627        contourWinding = (*rangeChecker)(contourList, test, current, index, endIndex, opp);
5628        if (contourWinding != SK_MinS32) {
5629            return contourWinding;
5630        }
5631        test /= 2;
5632    } while (!approximately_negative(test));
5633    SkASSERT(0); // should be OK to comment out, but interested when this hits
5634    return contourWinding;
5635}
5636
5637static Segment* tryRightAngleRay(SkTDArray<Contour*>& contourList, int& index,
5638        int& endIndex, SkPoint& topLeft, bool& unsortable, RangeChecker& rangeChecker) {
5639    // the simple upward projection of the unresolved points hit unsortable angles
5640    // shoot rays at right angles to the segment to find its winding, ignoring angle cases
5641    topLeft.fX = topLeft.fY = SK_ScalarMin;
5642    Segment* current;
5643    do {
5644        current = findSortableTop(contourList, index, endIndex, topLeft, unsortable, false);
5645        SkASSERT(current); // FIXME: return to caller that path cannot be simplified (yet)
5646        // find bounds
5647        Bounds bounds;
5648        bounds.setPoint(current->xyAtT(index));
5649        bounds.add(current->xyAtT(endIndex));
5650        SkScalar width = bounds.width();
5651        SkScalar height = bounds.height();
5652        if (width > height) {
5653            if (approximately_negative(width)) {
5654                continue; // edge is too small to resolve meaningfully
5655            }
5656            rangeChecker = contourRangeCheckY;
5657        } else {
5658            if (approximately_negative(height)) {
5659                continue; // edge is too small to resolve meaningfully
5660            }
5661            rangeChecker = contourRangeCheckX;
5662        }
5663    } while (!current);
5664    return current;
5665}
5666
5667static Segment* findSortableTopOld(SkTDArray<Contour*>& contourList, bool& firstContour, int& index,
5668        int& endIndex, SkPoint& topLeft, int& contourWinding, bool& unsortable) {
5669    Segment* current;
5670    do {
5671        current = findSortableTop(contourList, index, endIndex, topLeft, unsortable, true);
5672        if (!current) {
5673            break;
5674        }
5675        if (firstContour) {
5676            contourWinding = 0;
5677            firstContour = false;
5678            break;
5679        }
5680        int sumWinding = current->windSum(SkMin32(index, endIndex));
5681        // FIXME: don't I have to adjust windSum to get contourWinding?
5682        if (sumWinding == SK_MinS32) {
5683            sumWinding = current->computeSum(index, endIndex, false);
5684        }
5685        if (sumWinding == SK_MinS32) {
5686            contourWinding = innerContourCheck(contourList, current, index, endIndex, false);
5687        } else {
5688            contourWinding = sumWinding;
5689            int spanWinding = current->spanSign(index, endIndex);
5690            bool inner = useInnerWinding(sumWinding - spanWinding, sumWinding);
5691            if (inner) {
5692                contourWinding -= spanWinding;
5693            }
5694#if DEBUG_WINDING
5695            SkDebugf("%s sumWinding=%d spanWinding=%d sign=%d inner=%d result=%d\n",
5696                    __FUNCTION__, sumWinding, spanWinding, SkSign32(index - endIndex),
5697                    inner, contourWinding);
5698#endif
5699        }
5700    } while (contourWinding == SK_MinS32);
5701    if (contourWinding != SK_MinS32) {
5702#if DEBUG_WINDING
5703        SkDebugf("%s contourWinding=%d\n", __FUNCTION__, contourWinding);
5704#endif
5705        return current;
5706    }
5707    RangeChecker rangeChecker = NULL;
5708    current = tryRightAngleRay(contourList, index, endIndex, topLeft, unsortable, rangeChecker);
5709    contourWinding = rightAngleWinding(rangeChecker, contourList, current, index, endIndex, false);
5710    return current;
5711}
5712
5713// Each segment may have an inside or an outside. Segments contained within
5714// winding may have insides on either side, and form a contour that should be
5715// ignored. Segments that are coincident with opposing direction segments may
5716// have outsides on either side, and should also disappear.
5717// 'Normal' segments will have one inside and one outside. Subsequent connections
5718// when winding should follow the intersection direction. If more than one edge
5719// is an option, choose first edge that continues the inside.
5720    // since we start with leftmost top edge, we'll traverse through a
5721    // smaller angle counterclockwise to get to the next edge.
5722// returns true if all edges were processed
5723static bool bridgeWinding(SkTDArray<Contour*>& contourList, PathWrapper& simple) {
5724    bool firstContour = true;
5725    bool unsortable = false;
5726    bool topUnsortable = false;
5727    bool firstRetry = false;
5728    bool closable = true;
5729    SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
5730    do {
5731        int index, endIndex;
5732        // iterates while top is unsortable
5733        int contourWinding;
5734        Segment* current = findSortableTopOld(contourList, firstContour, index, endIndex, topLeft,
5735                contourWinding, topUnsortable);
5736        if (!current) {
5737            if (topUnsortable) {
5738                topUnsortable = false;
5739                SkASSERT(!firstRetry);
5740                firstRetry = true;
5741                topLeft.fX = topLeft.fY = SK_ScalarMin;
5742                continue;
5743            }
5744            break;
5745        }
5746        int winding = contourWinding;
5747        int spanWinding = current->spanSign(index, endIndex);
5748        // FIXME: needs work. While it works in limited situations, it does
5749        // not always compute winding correctly. Active should be removed and instead
5750        // the initial winding should be correctly passed in so that if the
5751        // inner contour is wound the same way, it never finds an accumulated
5752        // winding of zero. Inside 'find next', we need to look for transitions
5753        // other than zero when resolving sorted angles.
5754        SkTDArray<Span*> chaseArray;
5755        do {
5756            bool active = windingIsActive(winding, spanWinding);
5757        #if DEBUG_WINDING
5758            SkDebugf("%s active=%s winding=%d spanWinding=%d\n",
5759                    __FUNCTION__, active ? "true" : "false",
5760                    winding, spanWinding);
5761        #endif
5762            do {
5763                SkASSERT(unsortable || !current->done());
5764                int nextStart = index;
5765                int nextEnd = endIndex;
5766                Segment* next = current->findNextWinding(chaseArray, active,
5767                        nextStart, nextEnd, winding, spanWinding, unsortable);
5768                if (!next) {
5769                    if (active && !unsortable && simple.hasMove()
5770                            && current->verb() != SkPath::kLine_Verb
5771                            && !simple.isClosed()) {
5772                        current->addCurveTo(index, endIndex, simple, true);
5773                        SkASSERT(simple.isClosed());
5774                    }
5775                    break;
5776                }
5777        #if DEBUG_FLOW
5778                SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
5779                        current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY,
5780                        current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY);
5781        #endif
5782                current->addCurveTo(index, endIndex, simple, active);
5783                current = next;
5784                index = nextStart;
5785                endIndex = nextEnd;
5786            } while (!simple.isClosed()
5787                    && ((active && !unsortable) || !current->done()));
5788            if (active) {
5789                if (!simple.isClosed()) {
5790                    SkASSERT(unsortable);
5791                    int min = SkMin32(index, endIndex);
5792                    if (!current->done(min)) {
5793                        current->addCurveTo(index, endIndex, simple, true);
5794                        current->markDone(min, winding ? winding : spanWinding);
5795                    }
5796                    closable = false;
5797                }
5798                simple.close();
5799            }
5800            current = findChase(chaseArray, index, endIndex);
5801        #if DEBUG_ACTIVE_SPANS
5802            debugShowActiveSpans(contourList);
5803        #endif
5804            if (!current) {
5805                break;
5806            }
5807            winding = updateWindings(current, index, endIndex, spanWinding);
5808        } while (true);
5809    } while (true);
5810    return closable;
5811}
5812
5813static Segment* findSortableTopNew(SkTDArray<Contour*>& contourList, bool& firstContour, int& index,
5814        int& endIndex, SkPoint& topLeft, bool& unsortable) {
5815    Segment* current;
5816    bool first = true;
5817    int contourWinding, oppContourWinding;
5818    do {
5819        current = findSortableTop(contourList, index, endIndex, topLeft, unsortable, true);
5820        if (!current) {
5821            if (first) {
5822                return NULL;
5823            }
5824            break;
5825        }
5826        first = false;
5827        if (firstContour) {
5828            current->initWinding(index, endIndex, 0, 0);
5829            firstContour = false;
5830            return current;
5831        }
5832        int minIndex = SkMin32(index, endIndex);
5833        int sumWinding = current->windSum(minIndex);
5834        if (sumWinding == SK_MinS32) {
5835            sumWinding = current->computeSum(index, endIndex, true);
5836            if (sumWinding != SK_MinS32) {
5837                return current;
5838            }
5839        }
5840        contourWinding = innerContourCheck(contourList, current, index, endIndex, false);
5841        if (contourWinding == SK_MinS32) {
5842            continue;
5843        }
5844        oppContourWinding = innerContourCheck(contourList, current, index, endIndex, true);
5845        if (oppContourWinding != SK_MinS32) {
5846            break;
5847        }
5848        current->initWinding(index, endIndex, contourWinding, oppContourWinding);
5849        return current;
5850    } while (true);
5851    if (!current) {
5852        // the simple upward projection of the unresolved points hit unsortable angles
5853        // shoot rays at right angles to the segment to find its winding, ignoring angle cases
5854        int (*checker)(SkTDArray<Contour*>& contourList, double mid,
5855                const Segment* current, int index, int endIndex, bool opp);
5856        current = tryRightAngleRay(contourList, index, endIndex, topLeft, unsortable, checker);
5857        contourWinding = rightAngleWinding(checker, contourList, current, index, endIndex, false);
5858        oppContourWinding = rightAngleWinding(checker, contourList, current, index, endIndex, true);
5859    }
5860    current->initWinding(index, endIndex, contourWinding, oppContourWinding);
5861    return current;
5862}
5863
5864// rewrite that abandons keeping local track of winding
5865static bool bridgeWindingX(SkTDArray<Contour*>& contourList, PathWrapper& simple) {
5866    bool firstContour = true;
5867    bool unsortable = false;
5868    bool topUnsortable = false;
5869    bool firstRetry = false;
5870    SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
5871    do {
5872        int index, endIndex;
5873        Segment* current = findSortableTopNew(contourList, firstContour, index, endIndex, topLeft,
5874                topUnsortable);
5875        if (!current) {
5876            if (topUnsortable) {
5877                topUnsortable = false;
5878                SkASSERT(!firstRetry);
5879                firstRetry = true;
5880                topLeft.fX = topLeft.fY = SK_ScalarMin;
5881                continue;
5882            }
5883            break;
5884        }
5885        SkTDArray<Span*> chaseArray;
5886        do {
5887            if (current->activeWinding(index, endIndex)) {
5888                do {
5889            #if DEBUG_ACTIVE_SPANS
5890                    if (!unsortable && current->done()) {
5891                        debugShowActiveSpans(contourList);
5892                    }
5893            #endif
5894                    SkASSERT(unsortable || !current->done());
5895                    int nextStart = index;
5896                    int nextEnd = endIndex;
5897                    Segment* next = current->findNextWinding(chaseArray, nextStart, nextEnd,
5898                            unsortable);
5899                    if (!next) {
5900                        if (!unsortable && simple.hasMove()
5901                                && current->verb() != SkPath::kLine_Verb
5902                                && !simple.isClosed()) {
5903                            current->addCurveTo(index, endIndex, simple, true);
5904                            SkASSERT(simple.isClosed());
5905                        }
5906                        break;
5907                    }
5908                    current->addCurveTo(index, endIndex, simple, true);
5909                    current = next;
5910                    index = nextStart;
5911                    endIndex = nextEnd;
5912                } while (!simple.isClosed() && ((!unsortable) || !current->done()));
5913                if (current->activeWinding(index, endIndex) && !simple.isClosed()) {
5914                    SkASSERT(unsortable);
5915                    int min = SkMin32(index, endIndex);
5916                    if (!current->done(min)) {
5917                        current->addCurveTo(index, endIndex, simple, true);
5918                        current->markDoneUnary(min);
5919                    }
5920                }
5921                simple.close();
5922            } else {
5923                Span* last = current->markAndChaseDoneBinary(index, endIndex);
5924                if (last) {
5925                    *chaseArray.append() = last;
5926                }
5927            }
5928            current = findChase(chaseArray, index, endIndex);
5929        #if DEBUG_ACTIVE_SPANS
5930            debugShowActiveSpans(contourList);
5931        #endif
5932            if (!current) {
5933                break;
5934            }
5935        } while (true);
5936    } while (true);
5937    return simple.someAssemblyRequired();
5938}
5939
5940// returns true if all edges were processed
5941static bool bridgeXor(SkTDArray<Contour*>& contourList, PathWrapper& simple) {
5942    Segment* current;
5943    int start, end;
5944    bool unsortable = false;
5945    bool closable = true;
5946    while ((current = findUndone(contourList, start, end))) {
5947        do {
5948            SkASSERT(unsortable || !current->done());
5949            int nextStart = start;
5950            int nextEnd = end;
5951            Segment* next = current->findNextXor(nextStart, nextEnd, unsortable);
5952            if (!next) {
5953                if (!unsortable && simple.hasMove()
5954                        && current->verb() != SkPath::kLine_Verb
5955                        && !simple.isClosed()) {
5956                    current->addCurveTo(start, end, simple, true);
5957                    SkASSERT(simple.isClosed());
5958                }
5959                break;
5960            }
5961        #if DEBUG_FLOW
5962            SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
5963                    current->debugID(), current->xyAtT(start).fX, current->xyAtT(start).fY,
5964                    current->xyAtT(end).fX, current->xyAtT(end).fY);
5965        #endif
5966            current->addCurveTo(start, end, simple, true);
5967            current = next;
5968            start = nextStart;
5969            end = nextEnd;
5970        } while (!simple.isClosed() && (!unsortable || !current->done()));
5971        if (!simple.isClosed()) {
5972            SkASSERT(unsortable);
5973            int min = SkMin32(start, end);
5974            if (!current->done(min)) {
5975                current->addCurveTo(start, end, simple, true);
5976                current->markDone(min, 1);
5977            }
5978            closable = false;
5979        }
5980        simple.close();
5981    #if DEBUG_ACTIVE_SPANS
5982        debugShowActiveSpans(contourList);
5983    #endif
5984    }
5985    return closable;
5986}
5987
5988static void fixOtherTIndex(SkTDArray<Contour*>& contourList) {
5989    int contourCount = contourList.count();
5990    for (int cTest = 0; cTest < contourCount; ++cTest) {
5991        Contour* contour = contourList[cTest];
5992        contour->fixOtherTIndex();
5993    }
5994}
5995
5996static void sortSegments(SkTDArray<Contour*>& contourList) {
5997    int contourCount = contourList.count();
5998    for (int cTest = 0; cTest < contourCount; ++cTest) {
5999        Contour* contour = contourList[cTest];
6000        contour->sortSegments();
6001    }
6002}
6003
6004static void makeContourList(SkTArray<Contour>& contours, SkTDArray<Contour*>& list,
6005        bool evenOdd, bool oppEvenOdd) {
6006    int count = contours.count();
6007    if (count == 0) {
6008        return;
6009    }
6010    for (int index = 0; index < count; ++index) {
6011        Contour& contour = contours[index];
6012        contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd);
6013        *list.append() = &contour;
6014    }
6015    QSort<Contour>(list.begin(), list.end() - 1);
6016}
6017
6018static bool approximatelyEqual(const SkPoint& a, const SkPoint& b) {
6019    return AlmostEqualUlps(a.fX, b.fX) && AlmostEqualUlps(a.fY, b.fY);
6020}
6021
6022    /*
6023        check start and end of each contour
6024        if not the same, record them
6025        match them up
6026        connect closest
6027        reassemble contour pieces into new path
6028    */
6029static void assemble(const PathWrapper& path, PathWrapper& simple) {
6030#if DEBUG_PATH_CONSTRUCTION
6031    SkDebugf("%s\n", __FUNCTION__);
6032#endif
6033    SkTArray<Contour> contours;
6034    EdgeBuilder builder(path, contours);
6035    builder.finish();
6036    int count = contours.count();
6037    int outer;
6038    SkTDArray<int> runs; // indices of partial contours
6039    for (outer = 0; outer < count; ++outer) {
6040        const Contour& eContour = contours[outer];
6041        const SkPoint& eStart = eContour.start();
6042        const SkPoint& eEnd = eContour.end();
6043#if DEBUG_ASSEMBLE
6044        SkDebugf("%s contour", __FUNCTION__);
6045        if (!approximatelyEqual(eStart, eEnd)) {
6046            SkDebugf("[%d]", runs.count());
6047        } else {
6048            SkDebugf("   ");
6049        }
6050        SkDebugf(" start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n",
6051                eStart.fX, eStart.fY, eEnd.fX, eEnd.fY);
6052#endif
6053        if (approximatelyEqual(eStart, eEnd)) {
6054            eContour.toPath(simple);
6055            continue;
6056        }
6057        *runs.append() = outer;
6058    }
6059    count = runs.count();
6060    if (count == 0) {
6061        return;
6062    }
6063    SkTDArray<int> sLink, eLink;
6064    sLink.setCount(count);
6065    eLink.setCount(count);
6066    SkTDArray<double> sBest, eBest;
6067    sBest.setCount(count);
6068    eBest.setCount(count);
6069    int rIndex;
6070    for (rIndex = 0; rIndex < count; ++rIndex) {
6071        outer = runs[rIndex];
6072        const Contour& oContour = contours[outer];
6073        const SkPoint& oStart = oContour.start();
6074        const SkPoint& oEnd = oContour.end();
6075        double dx = oEnd.fX - oStart.fX;
6076        double dy = oEnd.fY - oStart.fY;
6077        double dist = dx * dx + dy * dy;
6078        sBest[rIndex] = eBest[rIndex] = dist;
6079        sLink[rIndex] = eLink[rIndex] = rIndex;
6080    }
6081    for (rIndex = 0; rIndex < count - 1; ++rIndex) {
6082        outer = runs[rIndex];
6083        const Contour& oContour = contours[outer];
6084        const SkPoint& oStart = oContour.start();
6085        const SkPoint& oEnd = oContour.end();
6086        double bestStartDist = sBest[rIndex];
6087        double bestEndDist = eBest[rIndex];
6088        for (int iIndex = rIndex + 1; iIndex < count; ++iIndex) {
6089            int inner = runs[iIndex];
6090            const Contour& iContour = contours[inner];
6091            const SkPoint& iStart = iContour.start();
6092            const SkPoint& iEnd = iContour.end();
6093            double dx = iStart.fX - oStart.fX;
6094            double dy = iStart.fY - oStart.fY;
6095            double dist = dx * dx + dy * dy;
6096            if (bestStartDist > dist && sBest[iIndex] > dist) {
6097                sBest[iIndex] = bestStartDist = dist;
6098                sLink[rIndex] = ~iIndex;
6099                sLink[iIndex] = ~rIndex;
6100            }
6101            dx = iEnd.fX - oStart.fX;
6102            dy = iEnd.fY - oStart.fY;
6103            dist = dx * dx + dy * dy;
6104            if (bestStartDist > dist && eBest[iIndex] > dist) {
6105                eBest[iIndex] = bestStartDist = dist;
6106                sLink[rIndex] = iIndex;
6107                eLink[iIndex] = rIndex;
6108            }
6109            dx = iStart.fX - oEnd.fX;
6110            dy = iStart.fY - oEnd.fY;
6111            dist = dx * dx + dy * dy;
6112            if (bestEndDist > dist && sBest[iIndex] > dist) {
6113                sBest[iIndex] = bestEndDist = dist;
6114                sLink[iIndex] = rIndex;
6115                eLink[rIndex] = iIndex;
6116            }
6117            dx = iEnd.fX - oEnd.fX;
6118            dy = iEnd.fY - oEnd.fY;
6119            dist = dx * dx + dy * dy;
6120            if (bestEndDist > dist && eBest[iIndex] > dist) {
6121                eBest[iIndex] = bestEndDist = dist;
6122                eLink[iIndex] = ~rIndex;
6123                eLink[rIndex] = ~iIndex;
6124            }
6125       }
6126    }
6127#if DEBUG_ASSEMBLE
6128    for (rIndex = 0; rIndex < count; ++rIndex) {
6129        int s = sLink[rIndex];
6130        int e = eLink[rIndex];
6131        SkDebugf("%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__, s < 0 ? 's' : 'e',
6132                s < 0 ? ~s : s, rIndex, rIndex, e < 0 ? 'e' : 's', e < 0 ? ~e : e);
6133    }
6134#endif
6135    rIndex = 0;
6136    do {
6137        bool forward = true;
6138        bool first = true;
6139        int sIndex = sLink[rIndex];
6140        SkASSERT(sIndex != INT_MAX);
6141        sLink[rIndex] = INT_MAX;
6142        int eIndex;
6143        if (sIndex < 0) {
6144            eIndex = sLink[~sIndex];
6145            sLink[~sIndex] = INT_MAX;
6146        } else {
6147            eIndex = eLink[sIndex];
6148            eLink[sIndex] = INT_MAX;
6149        }
6150        SkASSERT(eIndex != INT_MAX);
6151#if DEBUG_ASSEMBLE
6152        SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
6153                    sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
6154                    eIndex < 0 ? ~eIndex : eIndex);
6155#endif
6156        do {
6157            outer = runs[rIndex];
6158            const Contour& contour = contours[outer];
6159            if (first) {
6160                first = false;
6161                const SkPoint* startPtr = &contour.start();
6162                simple.deferredMove(startPtr[0]);
6163            }
6164            if (forward) {
6165                contour.toPartialForward(simple);
6166            } else {
6167                contour.toPartialBackward(simple);
6168            }
6169#if DEBUG_ASSEMBLE
6170            SkDebugf("%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex,
6171                eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex,
6172                sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
6173#endif
6174            if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
6175                simple.close();
6176                break;
6177            }
6178            if (forward) {
6179                eIndex = eLink[rIndex];
6180                SkASSERT(eIndex != INT_MAX);
6181                eLink[rIndex] = INT_MAX;
6182                if (eIndex >= 0) {
6183                    SkASSERT(sLink[eIndex] == rIndex);
6184                    sLink[eIndex] = INT_MAX;
6185                } else {
6186                    SkASSERT(eLink[~eIndex] == ~rIndex);
6187                    eLink[~eIndex] = INT_MAX;
6188                }
6189            } else {
6190                eIndex = sLink[rIndex];
6191                SkASSERT(eIndex != INT_MAX);
6192                sLink[rIndex] = INT_MAX;
6193                if (eIndex >= 0) {
6194                    SkASSERT(eLink[eIndex] == rIndex);
6195                    eLink[eIndex] = INT_MAX;
6196                } else {
6197                    SkASSERT(sLink[~eIndex] == ~rIndex);
6198                    sLink[~eIndex] = INT_MAX;
6199                }
6200            }
6201            rIndex = eIndex;
6202            if (rIndex < 0) {
6203                forward ^= 1;
6204                rIndex = ~rIndex;
6205            }
6206        } while (true);
6207        for (rIndex = 0; rIndex < count; ++rIndex) {
6208            if (sLink[rIndex] != INT_MAX) {
6209                break;
6210            }
6211        }
6212    } while (rIndex < count);
6213#if DEBUG_ASSEMBLE
6214    for (rIndex = 0; rIndex < count; ++rIndex) {
6215       SkASSERT(sLink[rIndex] == INT_MAX);
6216       SkASSERT(eLink[rIndex] == INT_MAX);
6217    }
6218#endif
6219}
6220
6221void simplifyx(const SkPath& path, SkPath& result) {
6222    // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
6223    result.reset();
6224    result.setFillType(SkPath::kEvenOdd_FillType);
6225    PathWrapper simple(result);
6226
6227    // turn path into list of segments
6228    SkTArray<Contour> contours;
6229    // FIXME: add self-intersecting cubics' T values to segment
6230    EdgeBuilder builder(path, contours);
6231    builder.finish();
6232    SkTDArray<Contour*> contourList;
6233    makeContourList(contours, contourList, false, false);
6234    Contour** currentPtr = contourList.begin();
6235    if (!currentPtr) {
6236        return;
6237    }
6238    Contour** listEnd = contourList.end();
6239    // find all intersections between segments
6240    do {
6241        Contour** nextPtr = currentPtr;
6242        Contour* current = *currentPtr++;
6243        Contour* next;
6244        do {
6245            next = *nextPtr++;
6246        } while (addIntersectTs(current, next) && nextPtr != listEnd);
6247    } while (currentPtr != listEnd);
6248    // eat through coincident edges
6249    coincidenceCheck(contourList, 0);
6250    fixOtherTIndex(contourList);
6251    sortSegments(contourList);
6252#if DEBUG_ACTIVE_SPANS
6253    debugShowActiveSpans(contourList);
6254#endif
6255    // construct closed contours
6256    if (builder.xorMask() == kWinding_Mask
6257                ? gUseOldBridgeWinding ? !bridgeWinding(contourList, simple)
6258                : bridgeWindingX(contourList, simple)
6259                : !bridgeXor(contourList, simple))
6260    { // if some edges could not be resolved, assemble remaining fragments
6261        SkPath temp;
6262        temp.setFillType(SkPath::kEvenOdd_FillType);
6263        PathWrapper assembled(temp);
6264        assemble(simple, assembled);
6265        result = *assembled.nativePath();
6266    }
6267}
6268
6269