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