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